Refused clone-mount sandbox creation on a shallow repository with an actionable message instead of a silent empty workspace (FR-058) - #28
Merged
Conversation
…actionable message instead of a silent empty workspace (FR-058)
There was a problem hiding this comment.
Pull request overview
Adds an FR-058 preflight to prevent creating mount: clone sandboxes from shallow Git repositories, avoiding the “empty workspace + silent failure” mode caused by git clone --reference refusing shallow sources. This is implemented consistently across the VS Code extension create paths and the generated project CLI, with accompanying documentation/spec updates.
Changes:
- Added a new
src/git.tsmodule for read-only host git probes (isShallowRepository) used to gate clone-mount creation. - Added
assertMountUsable()checks insrc/ops.tson all sandbox create paths (Connect/Create, Shell-create, Rebuild before destructive steps). - Added clone-mount shallow-repo refusal to the generated
.sandbox/scripts/sbx.shtemplate and updated canonical docs + spec.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/script.ts | Adds a shallow-repo preflight for clone-mount sandbox creation in the generated CLI template. |
| src/ops.ts | Refuses clone-mount creation on shallow repos before any sbx mutation; reorders rebuild checks ahead of destructive steps. |
| src/git.ts | Introduces a read-only git probe (rev-parse --is-shallow-repository) via the existing log.run runner. |
| docs/specs/completed/015 - Clone Mount Preflight.md | Documents the iteration’s rationale/behavior and tradeoffs (preflight only, fail-open probe). |
| docs/Features.md | Adds FR-058 feature documentation and notes on create preconditions. |
| docs/Architecture.md | Updates module map/dependency direction and documents the new preflight behavior and limitations. |
| CLAUDE.md | Updates module map/dependency direction to include git.ts. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
… terminal hand-off for git fetch --unshallow (FR-058)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Risk & Size
Risk: Medium
Size: Medium
What & Why
A sandbox with
mount: clonecreated on a shallow repository came up with an emptyworkspace and said nothing: sbx copies the repo in with
git clone --reference <read-only host mount>, git refuses a shallow source(
fatal: reference repository '/run/sandbox/source' is shallow), and the failure happensinside the sandbox at start-up —
sbx createitself exits 0. Worse, it never self-heals:once the agent writes into the empty directory sbx pre-created, every later start fails on
already exists and is not an empty directoryand the original cause is gone.FR-058 refuses that create before the first sbx call and names the fix. Spec:
docs/specs/completed/015 - Clone Mount Preflight.md(shipped); canonical docs updated inthe same change — Features FR-058 (+ notes on FR-003/FR-052) and Architecture §4/§5/§9/§13/§14.
Changes
src/git.ts(new): read-only host git probes —isShallowRepository(dir)viagit -C <dir> rev-parse --is-shallow-repository, run through thelog.tsrunner.-Crather than a spawn cwd so a workspace inside a repository resolves the containing
repo, matching sbx's own precondition. Fails open on any error.
src/ops.ts:assertMountUsable()on every create path (createOrAttach,rebuildRef,shellRef), gated onmount: clone; attaching to an existing sandbox is untouched. Therefusal is a modal dialog — it ends the action the user just asked for, and the
explanation does not survive a notification's one-line clamp — naming the cause,
git fetch --unshallowand what running it does, plus themount: directalternative.terminal.tsgainedopenHostCommandTerminal, which opens ahost terminal in the repository with
git fetch --unshallowtyped but not executed.The extension never runs it — fetching history changes what the user's working copy
contains — but the user does not have to type it either.
ops.HandledErrorsentinel: raised after the dialog, skipped by the errorreporters in
extension.ts,tree.tsandform.ts(form's localHandledErrornowextends it), so the dialog is never chased by a duplicate toast.
src/ops.ts(Rebuild): workspace resolution, the UNC translation and the new preflightmoved to the top of the operation. They previously ran after
docker buildandsbx rm, so a workspace problem surfaced once the old instance was already destroyed; arefusal now leaves the sandbox intact.
src/script.ts: the same guard rendered into the generated project CLI'screate_instance(FR-052 parity), same message, same fail-open rule.direction), §5 (preflight before the first sbx call), §9 (why clone mode needs full
history), §13 (CLI parity), §14 (the general silent-clone-failure limitation and why a
post-create probe was not built); CLAUDE.md module map.
How to Verify
npm run verify— exits 0 (tsc strict + esbuild bundle).git rev-parse --is-shallow-repositoryprintstrue, define a sandbox withmount: clone, press Connect. Expected: a modal explaining the shallow history andnaming
git fetch --unshallow, and no sandbox created (sbx lsunchanged). Beforethis change the sandbox was created and the agent landed in an empty workspace.
Open Terminal must open a host terminal in the repository with the command typed in
and not run, and no second error toast may appear behind the dialog.
mount: direct— Connect still works (nothing is cloned).git fetch --unshallowin that repository, Connect on the clone-mount sandboxcreates it and the in-sandbox workspace holds a real clone (
.gitpresent).without removing the existing instance.
.sandbox/scripts/sbx.shpassesbash -n, and itsconnect/create path dies with the same message on a shallow repo.The shallow failure and its fix were reproduced against sbx v0.31.3 on a real shallow
repository (probe sandbox created and removed); the author has run the manual acceptance.