Repository navigation
fix: NER-382 — attempt attach workspace drift guard - #123
Merged
Merged
Conversation
…E_DRIFT refusal, tests attempt attach silently discarded pre-attach edits inside .forge/worktrees/<attempt>/. This change (1) qualifies workspace_path as a materialization target in start/attempt-start payloads (additive workspace_role field + help text), (2) makes attach refuse with typed WORKSPACE_DRIFT (drifted paths in details, secret-filtered) unless --discard-workspace-changes is passed, via a read-only per-file equality check against the recorded materialized_content_ref, and (3) adds integration tests incl. the original silent-loss repro now failing loudly. Produced in the ccx contract pilot (experiment/ccx-spikes, experiments/ccx/RESULTS.md), Arm A stack; gates re-verified independently. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTeDdEu9Q4a96DdXK4tfju
…y primitive, private-label exclusion, machine-surface polish, test hardening Multi-persona review (run 20260706-145749-963e80e5) found two validated P1s sharing one root cause: the drift walk used weaker exclusion semantics than the scanner that built the recorded tree (gitignored build artifacts became permanent unclearable WORKSPACE_DRIFT — live reproduced), and the store hand-parsed native tree JSON. Both fixed by a new read-only forge-content-native workspace_equality primitive built on walk_worktree + tree_fingerprints; the store-side walk is deleted. Private-labeled paths are excluded from both sides of the equality (the advertised --discard flag could previously delete private files). Additive: attach schema entry, override_flag/recovery_hint details keys, workspace_role on list/show, replay injection for pre-upgrade rows. Seven new integration tests incl. gitignore-parity and override-cannot-bypass-DIRTY_WORKTREE. Design decisions deferred to NER-383. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTeDdEu9Q4a96DdXK4tfju
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.
Summary
forge attempt attachsilently discarded edits made inside a not-yet-attached attempt's workspace dir (.forge/worktrees/<id>) — the workspace path inattempt start's payload looked editable but was only a materialization target. Found dogfooding (ccx T2 spike). Fixes NER-382.Commit 1 — the guard:
workspace_pathis now qualified by an additiveworkspace_role: "materialization_target"field (start/attempt-start payloads + replay) with matching help/schema text.attempt attachrefuses with new typedWORKSPACE_DRIFT(drifted paths secret-redacted likeDIRTY_WORKTREE) when the workspace dir no longer equals its recordedmaterialized_content_ref, unless--discard-workspace-changesis passed. The override discards workspace drift only — it can never bypassDIRTY_WORKTREE(tested).Commit 2 — multi-persona review fixes (run 20260706-145749-963e80e5; 15 findings, 8 independently validated, 1 live-reproduced):
forge-content-native::workspace_equalityprimitive built onwalk_worktree+tree_fingerprints; the hand-rolled store-side walk is deleted (−199 lines).--discardflag would delete private files; validated composition).attempt attachschema entry, structuredoverride_flag/recovery_hintdetails keys,workspace_roleonattempt list/show, replay injection for pre-upgrade rows.Deferred by design → NER-383: four refusal-semantics decisions (crash-retry hinge, deleted-dir semantics, lock ordering, non-Unix symlink arm) with proposed defaults.
Provenance
Implementation produced in the contract-pilot experiment (branch
experiment/ccx-spikes,experiments/ccx/RESULTS.md): frozen task contracts, fresh brief-only sessions, independently re-run acceptance gates, two blinded scorers, then the full/ce-code-reviewgate with per-finding validators.scripts/ci.shgreen at both commits.Verification
cargo fmt --all --check/cargo test --workspace(621 passed) /cargo clippy --workspace --all-targets -- -D warnings/scripts/ci.shincl. e2e eval — all green, run independently after the fix round.DIRTY_WORKTREE.🤖 Generated with Claude Code
https://claude.ai/code/session_01GTeDdEu9Q4a96DdXK4tfju
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.