fix(implement-loop): stamp a repo-root anchor into every stage prompt
In worktree sessions a dispatched agent's cwd can resolve to the primary checkout instead of the loop's working tree — observed as a per-dispatch race: 6/9 quality dispatches returning infra_blocked with the sha256-of-empty fingerprint over a real diff, and a tree-check counting the primary checkout's clean tree into a false no-op BLOCKED on a genuinely-DONE iteration. Remedy (validated in the field on the reporting run): the carrier gains repo_root, stamped into every stage prompt as an explicit 'git -C <root>' anchor with a wrong-directory tripwire (an empty diff or unexpected HEAD sha = wrong cwd, re-run against the anchor). When the carrier omits it, the first dispatched stage (mini preflight / standard plan-index) probes 'git rev-parse --show-toplevel' as a fallback — itself subject to the same race, so SKILL.md documents the field as effectively required in worktree sessions. compiler-driven-edit gets the same carrier field (same defect class, carrier-only). agent-template stage list updated in passing (plan-extract[-all], end-verify). closes #25
This commit is contained in:
@@ -50,6 +50,12 @@
|
||||
// Carrier — Workflow `args`:
|
||||
// edit_description: what type/signature change to make
|
||||
// def_site: the definition site (file + symbol) it originates from
|
||||
// repo_root: optional but strongly recommended (required in worktree
|
||||
// sessions — issue #25): absolute path of the working tree
|
||||
// this edit operates on, stamped into both stage prompts
|
||||
// as a `git -C` anchor so a dispatched agent whose cwd
|
||||
// resolves to the primary checkout cannot verify the
|
||||
// wrong tree.
|
||||
// A non-object carrier or a missing required field fails fast as an infra
|
||||
// BLOCKED before any agent is dispatched (issue #24).
|
||||
|
||||
@@ -87,7 +93,7 @@ if ((carrier !== undefined && carrier !== null && typeof carrier !== 'object') |
|
||||
}
|
||||
}
|
||||
|
||||
const { edit_description, def_site } = carrier || {}
|
||||
const { edit_description, def_site, repo_root } = carrier || {}
|
||||
|
||||
const missingFields = Object.entries({ edit_description, def_site })
|
||||
.filter(([, v]) => typeof v !== 'string' || !v.trim())
|
||||
@@ -107,6 +113,18 @@ const STANDING =
|
||||
'(its "## Skills plugin: project facts" name the build and test commands) and ' +
|
||||
'`git log -10 --format=full`. Resolve the build/test commands from those facts.'
|
||||
|
||||
// Working-directory anchor (issue #25): same defect class as implement-loop —
|
||||
// in a worktree session a dispatched agent's cwd can resolve to the primary
|
||||
// checkout and verify the wrong (clean) tree. Carrier-supplied only here (two
|
||||
// stages, no cheap probe slot); '' when absent.
|
||||
const ANCHOR =
|
||||
typeof repo_root === 'string' && repo_root.trim()
|
||||
? `\n\nWORKING-DIRECTORY ANCHOR (do not skip): the working tree lives at ${repo_root.trim()}. Run EVERY git ` +
|
||||
`command as \`git -C ${repo_root.trim()} ...\` and run the build/test commands from that directory. An empty ` +
|
||||
'`git diff HEAD` or an unexpected HEAD sha means you are in the WRONG directory — re-run against the anchor; ' +
|
||||
'never report a clean tree from an unanchored cwd.'
|
||||
: ''
|
||||
|
||||
const EDIT_SCHEMA = {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
@@ -159,7 +177,7 @@ const VERIFY_SCHEMA = {
|
||||
// ---- Phase 1 — make the edit and let the compiler enumerate the sites ----
|
||||
phase('Edit + propagate')
|
||||
const edit = await agent(
|
||||
`${STANDING}\n\nMake this behaviour-preserving type/signature edit at its definition site, then propagate it ` +
|
||||
`${STANDING}${ANCHOR}\n\nMake this behaviour-preserving type/signature edit at its definition site, then propagate it ` +
|
||||
'MECHANICALLY across every site the build flags — let the type checker enumerate the edit sites. Introduce NO ' +
|
||||
'new behaviour, add NO new test, change NO existing test. If a flagged site cannot be resolved without making a ' +
|
||||
'design decision, OR resolving it would encode new behaviour, STOP and report it as a hole rather than guessing. ' +
|
||||
@@ -207,7 +225,7 @@ if (!edit.applied_changes) {
|
||||
// ---- Phase 2 — verify (the independently-invokable phase) ---------------
|
||||
phase('Verify')
|
||||
const verify = await agent(
|
||||
`${STANDING}\n\nVerify the edit is behaviour-preserving WITHOUT changing any code or test. Run the project build ` +
|
||||
`${STANDING}${ANCHOR}\n\nVerify the edit is behaviour-preserving WITHOUT changing any code or test. Run the project build ` +
|
||||
'and the full test suite. Report whether the build is clean and whether the suite is green AND UNCHANGED — i.e. ' +
|
||||
'every test passes and NO test was added, removed, or weakened versus the pre-edit baseline (compare `git diff ' +
|
||||
'HEAD` for test-file changes). Also report working_tree_dirty — whether `git status --porcelain` / `git diff HEAD` ' +
|
||||
|
||||
Reference in New Issue
Block a user