Repository navigation
feat(skills): sync sbxenv authoring workflow into docker-sandboxes-env - #130
melmennaoui wants to merge 3 commits into
Conversation
Adapt docker/sandbox-kit-spec skills/sbxenv (75b2696a) into the existing docker-sandboxes-env owner instead of adding an overlapping skill: create/update workflow, live kit selection and pinning with the bundled scripts/kits.py helper (copied unchanged), and a full field reference. Refresh the guidance for sbx v0.51.0 and the published environment-files docs: --force replaces -y/--auto-approve, env exec offers interactive creation of a missing sandbox, user defaults, MCP command approval, recreate-on-change rules, adoption recovery, and per-command flags. Add offline tests for the helper's release ordering, pinning, and failure exits, and eval prompts for scaffolding, upgrading kits, and non-interactive exec. Bump the skill to 0.2.0. Signed-off-by: Mohamed EL MENNAOUI <mohamed.elmennaoui@docker.com>
Add a credential-free live scenario: the agent writes an sbxenv.yaml beside a Playwright project, composes the built-in shell agent with a kit from the live catalog pinned to a digest, and previews it with `sbx env plan` without creating, running, or force-approving anything. Document that `sbx env plan` does not resolve kit references (an invented kit or missing tag plans cleanly on sbx v0.51.0), so references must be checked with the helper before trusting a clean plan. Signed-off-by: Mohamed EL MENNAOUI <mohamed.elmennaoui@docker.com>
There was a problem hiding this comment.
🔴 Critical issues
Adds a live kit selection and pinning workflow for sandbox environments. The new workflow and eval cleanup have failure-path risks.
3 findings
[medium] Describe the release selected for the environment
Location: skills/docker-sandboxes-env/references/authoring-workflow.md:62
The workflow describes the untagged candidate, which resolves to latest, before selecting newestRelease. If those tags point to different versions, the subsequent steps use the wrong version's arguments, credentials, and host grants. The final checklist permits pin instead of describe, so it does not correct this. Describe the selected release before configuring it.
Confidence: strong (100/100)
[medium] Do not report a successful pin without a digest
Location: skills/docker-sandboxes-env/scripts/kits.py:573
If a registry returns HTTP 200 without a Docker-Content-Digest header, manifest returns None. Both pin_one and pinned update_one then format a reference without a digest and report success. This can silently remove an existing pin or claim to pin an unpinned reference. Reject a missing digest when a pinned result is requested.
Confidence: strong (100/100)
[high] Limit cleanup to sandboxes owned by this scenario
Location: skills/docker-sandboxes-env/evals/scaffold-pin-plan.yaml:59
This cleanup applies to every sandbox that appears during the scenario, not just one created by the agent. The harness takes a global sbx ls snapshot and force-removes the difference. A sandbox another user or process creates while the eval runs can therefore be deleted. Also, if the initial listing fails, the harness treats the snapshot as empty and can remove existing sandboxes when the later listing succeeds. Isolate the scenario's resources or restrict cleanup to a verified scenario-owned identity.
Confidence: strong (100/100)
1 recommended validation
Check a helper-pinned kit during sandbox creation
What to check:
Reuse a run for this commit that creates a disposable environment with a helper-pinned public kit. If none exists, create one with the reviewed reference and check that the kit resolves successfully, then remove it.
Why:
The new live scenario runs only sbx env plan and forbids creation. SKILL.md states that plan does not resolve kit references. I can't check whether a creation test passed for this commit.
8 files omitted
8 out of scope
"CHANGELOG.md""README.md""evals/docker-sandboxes-env.md""skills/docker-sandboxes-env/SKILL.md""skills/docker-sandboxes-env/checks/verification.md""skills/docker-sandboxes-env/references/authoring-workflow.md""skills/docker-sandboxes-env/references/env-schema-fields.md""skills/docker-sandboxes-env/references/sources.md"
Finding IDs: f-9e505441b319a69a3187037d (describe-selected-release), f-10eb84f96525f5410f1217a1 (missing-digest-removes-pin), f-61c2ff38621662eb0003bb9d (cleanup-removes-unrelated-sandboxes).
| # Nothing should be created; this cleans up if the agent did anyway. | ||
| cleanup: | ||
| list: ["sbx", "ls", "-q"] | ||
| remove: ["sbx", "rm", "--force"] |
There was a problem hiding this comment.
[high] Limit cleanup to sandboxes owned by this scenario
This cleanup applies to every sandbox that appears during the scenario, not just one created by the agent. The harness takes a global sbx ls snapshot and force-removes the difference. A sandbox another user or process creates while the eval runs can therefore be deleted. Also, if the initial listing fails, the harness treats the snapshot as empty and can remove existing sandboxes when the later listing succeeds. Isolate the scenario's resources or restrict cleanup to a verified scenario-owned identity.
Confidence: 🟢 strong · 100/100.
Finding f-61c2ff38621662eb0003bb9d
| - When both `X` and `X-mixin` exist, `X` is the workload and `X-mixin` | ||
| layers that agent onto a different base. Use the mixin only when the user | ||
| wants that different base. | ||
| - For each OCI kit you keep, run `kits.py update <org>/<name>` (no tag) and |
There was a problem hiding this comment.
[medium] Describe the release selected for the environment
The workflow describes the untagged candidate, which resolves to latest, before selecting newestRelease. If those tags point to different versions, the subsequent steps use the wrong version's arguments, credentials, and host grants. The final checklist permits pin instead of describe, so it does not correct this. Describe the selected release before configuring it.
Confidence: 🟢 strong · 100/100.
Finding f-9e505441b319a69a3187037d
| tag = ref.tag or ("latest" if not ref.digest else None) | ||
| if tag is None: | ||
| return {"ref": text, "suggested": text, "changed": False, "note": "already digest-only"} | ||
| digest = manifest(ref, tag, method="HEAD")[0] |
There was a problem hiding this comment.
[medium] Do not report a successful pin without a digest
If a registry returns HTTP 200 without a Docker-Content-Digest header, manifest returns None. Both pin_one and pinned update_one then format a reference without a digest and report success. This can silently remove an existing pin or claim to pin an unpinned reference. Reject a missing digest when a pinned result is requested.
Confidence: 🟢 strong · 100/100.
Finding f-10eb84f96525f5410f1217a1
….51.0 Run checks/verification.md end to end on sbx v0.51.0 (macOS arm64) with an isolated app and interactive approvals, and record the results in checks/runtime-results.md. All steps pass. Fix the runbook: sign-in is per app, so a plain `sbx login` session does not sign in the isolated --app-name app; sign it in during step 1. Record that the documented subdirectory rename gap did not reproduce on this release and platform (the file is its own read-only bind mount), while keeping the documented guidance because sbx env plan and the docs still flag it. Signed-off-by: Mohamed EL MENNAOUI <mohamed.elmennaoui@docker.com>
Summary
Updates the experimental
docker-sandboxes-envskill (0.1.0 → 0.2.0) by adaptingsbxenvfrom docker/sandbox-kit-spec at75b2696a.docker-sandboxes-envalready ownssbxenv.yaml, so this extends that skill instead of adding a second one for the same file.SKILL.md; the full procedure is inreferences/authoring-workflow.md.scripts/kits.py(copied unchanged; SHA-2561ca05d5f…): a live Docker Hub helper for searching kits, summarizing descriptors, upgrading by version order and pinning digests.-f/--forcereplaces-y/--auto-approve; it approves one run without recording consent.env execoffers to create a missing sandbox interactively, and fails non-interactively.~/.sbxenv.yamluser defaults, MCP command approval, which changes need a recreate, recovery after lost environment state, and per-command flags.references/env-schema-fields.mdnow covers every top-level field.rememberHostCommandscaution, and the destroy-plan recheck afterpreRemove.--force. New prompts cover scaffolding (8), upgrading kits (9) and non-interactiveexec(10). Prompt 9 has static checks against the helper.skills/docker-sandboxes-env/evals/scaffold-pin-plan.yaml(credential-free): shell agent plus the Playwright kit from the live catalog, pinned to a digest, previewed withsbx env plan. Create, run and--forceare forbidden.sbx env plandoesn't resolve kit references; an invented kit or a missing tag plans cleanly. The skill now says to verify references with the helper first.scripts/test_kits_helper.pycovers release ordering, the prerelease gate, update and pin behavior, local-source handling and failure exits. Breaking the version ordering or forcing exit 0 makes the tests fail.Why a minor bump:
ownsanduse_whengain kit selection and pinning insidesbxenv.yaml. That adds scope; existing routing doesn't change, and the sibling skills already sendsbxenv.yamlwork here. Maintainers may prefer a major bump.Verification
VERSION_CHECK_BASE_SHA=56001ac5… task: 250 unit tests OK; 270 eval checks pass, 0 fail, 23 skipped; version policy and DCO OK; links and verification scripts OK.Helper run against live Docker Hub on 2026-11-10 with Python 3.9:
search,describe,update,pin, plus missing-repository and connection-failure exits.sbx env planon the asset with sbx v0.51.0 and an isolated app name: the plan renders with the documented<agent>-<workspace-basename>name. Plan-only probes showed that an unknown field fails, while a nonexistent tag and an invented kit both plan with exit 0.CI live scenarios:
scaffold-pin-planpasses 1/1 on both Claude (sonnet) and Codex, alongside the existing lifecycle scenario. Grading checks that the skill was invoked, that a plan succeeded, that nothing was created or force-approved, and that the answer names asbx/playwright:…@sha256:reference. It doesn't check which tool resolved the digest.Runtime runbook (
checks/verification.md, steps 0–8) on sbx v0.51.0, macOS arm64, with an isolated app and interactive approvals: all steps pass. Results are inchecks/runtime-results.md:initializeran twice andpostCreateonce, and the unchanged hook file was asked about again;preRemoveonly warned and removal went ahead;execon a missing sandbox exited 125 with "not found for this environment";Read-only file system.Questions for Sandboxes reviewers
sbx env planwarns that "the sandbox can rename" its directory. On v0.51.0 / macOS, though,mvof that directory failed withRead-only file system, because the file is its own read-only bind mount. Is the warning still accurate (other platforms or another attack path), or is the docs/plan text stale? The skill keeps the documented guidance until you confirm.--app-name. A plainsbx logindidn't sign in the isolated app. The sibling skills' runbooks say the opposite and will get a follow-up fix.Not verified / limitations
--skip-host-commands,rememberHostCommands, adoption recovery, Linux/Windows.references/sources.md:.zipas local;7d55286d, which is internal; public readers can only verify claims against the docs and the help output.Follow-ups
docker-sandboxes-lifecycleanddocker-sandboxes-network-credentialsstill mention "kit spec.yaml" (v2 wording). They are not changed here.