Skip to content

feat(acq): make --clone a neutral option, emulated on msb via a managed host-side scratch clone - #423

Draft
basiliskus wants to merge 2 commits into
mainfrom
feat/issue-403-neutral-clone
Draft

feat(acq): make --clone a neutral option, emulated on msb via a managed host-side scratch clone#423
basiliskus wants to merge 2 commits into
mainfrom
feat/issue-403-neutral-clone

Conversation

@basiliskus

Copy link
Copy Markdown
Contributor

Implements #403. AI-assisted.

What

--clone (env: ACQ_CLONE=1) becomes acq-owned neutral vocabulary, the same trajectory as --image/ADR-0022 and volumes:/ADR-0023. acq extracts the flag at dispatch and never forwards it raw: sbx re-injects its native sbx create --clone; msb emulates disposable-primary semantics with a managed host-side scratch clone. Design and divergences are recorded in ADR-0027.

msb emulation

  • git clone --no-hardlinks of the primary (must be a git repo root) into $XDG_STATE_HOME/acq/clones/<sandbox>/<repo>. The physical copy is load-bearing: a same-filesystem clone hardlinks object files an agent could modify through the scratch .git.
  • The scratch mounts rw at the original workspace path in the guest (verified msb 0.6.15 mounts --volume src:dst with src != dst), so agent cwd, kits, and docs behave exactly as a non-clone run. Secondaries unchanged.
  • A sandbox-<name> remote in the host checkout gives sbx-parity recovery: git fetch sandbox-<name> (inert, hash-verified objects; hooks/config never cross).
  • acq rm warns about unfetched commits, then deletes the scratch and the remote (same gone-after-remove rule as ADR-0023 derived volumes). A failed create cleans its own fresh scratch. Re-attach with --clone prints the applies-only-at-create note, mirroring --image.

Deliberate divergence from sbx (per the issue, ADR-0027)

A git clone carries committed state only: no gitignored/untracked files (the host-build-state contamination trap), and no uncommitted edits to tracked files. Create prints a notice on a dirty tree; acq cp remains the escape hatch.

Also in this PR

fix(test): the suite's stubbed ssh-keygen wrote key material to whatever -f pointed at, which let a mis-isolated fixture reach a real ~/.ssh file through the host's ssh-signing git config. It now refuses to write outside $STUBDIR.

Testing

  • 11 new tests in test/bats/116-clone-option.bats (written failing-first): mount remap + --no-hardlinks physical copy + remote registration, env-flag equivalence, non-repo/subdir/no-workspace rejection, dirty-tree notice, secondary mounts untouched, rm cleanup, unfetched-commit warning, re-attach note, sbx passthrough.
  • Verified live end-to-end on msb 0.6.15: clone mounted at the original path, host tree untouched, guest commit fetched back via git fetch sandbox-<name>, rm warning + full cleanup.
  • Full offline bats suite green; shellcheck and markdownlint clean.

…tch clone

Make --clone backend-neutral vocabulary (ADR-0027): acq owns the flag
(and ACQ_CLONE=1), extracts it at dispatch, and never forwards it raw.
sbx re-injects its native `sbx create --clone`; msb emulates disposable
primary semantics:

- git clone --no-hardlinks the primary (must be a git repo root) into
  $XDG_STATE_HOME/acq/clones/<sandbox>/<repo>; the physical copy is
  load-bearing (a same-fs clone hardlinks objects the guest could
  modify).
- Mount the scratch rw at the ORIGINAL workspace path in the guest
  (verified msb 0.6.15 mounts --volume src:dst with src != dst), so
  agent cwd and kits behave exactly as a non-clone run.
- Register a sandbox-<name> remote in the host checkout; recovery is
  sbx-parity: git fetch sandbox-<name> (inert, hash-verified objects).
- acq rm warns about unfetched commits, then deletes the scratch and
  the remote (same gone-after-remove rule as derived volumes); a failed
  create cleans up its own fresh scratch.
- Re-attach with --clone prints the same applies-only-at-create note
  as --image; a dirty host tree gets a committed-state-only notice.

Deliberate divergence from sbx, documented in ADR-0027: a git clone
carries committed state only (no gitignored/untracked files, no
uncommitted edits); acq cp remains the escape hatch.

Verified end-to-end on msb 0.6.15: clone mounted at the original path,
guest commit fetched back on the host, rm warning + full cleanup.

Closes #403
The stub wrote throwaway key material to whatever -f pointed at. A
fixture git commit that forgot to disable signing routed the host's
gpg.format=ssh config through the stubbed PATH, and the unguarded write
clobbered a real ~/.ssh public key file. Guard the write to $STUBDIR
and refuse loudly otherwise, so the offending test fails instead of
touching host state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant