Initial Request
src/assets/agents/git.md is 938 L / 59,376 ch [verified @ e726874], re-sent on every Git spawn (PF-026: a shared agent prompt file is billed PER SPAWN). Roughly 9,400 of those characters are GitHub-specific mechanics — gh invocations, header names, rate-limit detectors — interleaved with the provider-independent contract (each op's **Input:**, its **Output:** template, its **Degradation (D4):** clause, the D4/D11 invariants).
Three live consequences:
- PF-023 has ~30 filename-composition sinks instead of one convergence point (GAP-10, CRITICAL). There is no single place where a provider is resolved, so any future provider token would have to be threaded through every sink.
- The always-loaded D4/D11 cross-cutting text is GitHub-specific while §F.1 declares it provider-independent (GAP-03, CRITICAL) — two authorities on the secret-redaction path. This is the same shape as the live D9 divergence Phase 0 repaired.
src/assets/skills/git/SKILL.md (283 L / 9,236 ch) carries two live safety contradictions: :196 if [ "$REMAINING" -lt 10 ]; then sleep 60; fi [verified] directly contradicts D4's STOP-the-fan-out rule at git.md:25; and :211 gh release create … --notes "$NOTES" [verified — [drift: plan-1, plan-2 and §B.2 all cite :212; the live line is :211]] is an inline-body recipe where create-release mandates --notes-file after a scrub whose failure is a HARD fail. Both are invisible to every existing guard: INLINE_BODY_RE (tests/git-agent.test.ts:412 [verified]) matches only gh (?:pr|issue), and GIT_AGENT_PATH scans only git.md.
Phase 2 splits contract from mechanics for GitHub only, moving mechanics into generated per-op skill references addressed skill-relatively, adds a ≤40-line provider-resolution preamble at git.md:29 [verified: :29 is the blank line after the D4 block :22-28 and before ## Publication gate (D10) at :30], replaces five divergent inline issue-parse rules in the command layer with one neutral vocabulary partial, and installs the generated references with a converge-not-merge staged swap that a shadow cannot subvert.
Honest user-visible-change statement (the phase label)
No change to any GitHub-rendered artifact. Tracked = #{n}, Depends on: #{n}, 42-jwt-auth.{ts}.md and issue: 42 are byte-identical to Phase 0 under github, and the frozen github-status-lines.txt fixture is untouched. New files appear under the installed skill directory (~/.claude/skills/devflow:git/references/tracker/github/); no new file appears in any user's project tree and no new prompt is asked. No Jira or Linear literal exists anywhere yet.
Phase 2 therefore delivers zero user-facing value and introduces two new failure modes (an overlay that can partially fail; a generated reference that can be absent at runtime) — GAP-45. That is recorded deliberately, not hidden: the release-coupling decision is in §2, release readiness.
Execution: SEQUENTIAL_CODE_AGENTS · context-risk: CRITICAL · Design artifact: .devflow/docs/design/tracker-phase-2.2026-09-05_1155.md (authoritative; local, gitignored — a 60k-truncated copy is posted as a collapsed comment).
Product Requirements
Depends on
Phase 1 (#323) merged to main. Tracking issue: #321.
Acceptance criteria
- AC-2.1 — the golden diff contains only the intended text moves; the frozen status-line fixture unchanged [DR-27(b)] the frozen-fixture half stays mechanical; the "only intended moves" half is bound to the containment-test exemption list created in P2-S6 ([DR-17]) — an asserted-non-empty, per-range justified list of deliberately rewritten line ranges
- AC-2.2 — containment passes with zero unaccounted lines (incl. moved
github-api.md/SKILL.md lines)
- AC-2.3 — the D11 guards stay green with the floor at
>= 8 over the joined corpus, not lowered, and fail on a known-bad sample [DR-18] the D11 forward guard extracts with mode 'union' over the joined corpus, named explicitly at the call site
- AC-2.4a — a shadowed
devflow:git receives the canonical GitHub references
- AC-2.4b — REWORDED [DR-05]: an unreadable generated reference ⇒ that provider's directory is left unchanged,
InstallReport.overlayFailures names the provider, and the install succeeds; an absent canonical GitHub reference ⇒ loud failure with a build hint — the provider directory is atomic: a per-file failure aborts that provider's swap, rms the tmp tree, and pushes the provider onto overlayFailures — it never renames a partial tree over a good one
- AC-2.4c — a shadow-supplied file under
references/tracker/** not in the manifest is absent after install
- AC-2.5 (re-derived, §F.4) —
bytes(dist/agents/git.md) ≤ 49600, bytes(skills/git/SKILL.md) ≤ 6600, loaded set ≤ 71562 on the worst-case tracker spawn, each a named constant with its derivation in a comment, evaluated as a four-shape table test; the only reference-naming line outside a tracker-op section is the single preamble load instruction [DR-12] the loaded-set formula gains + max over ops of (sum of every reference file that op's load instructions can name in one spawn), with a bidirectional structural check. [DR-13(a)] the preamble ceiling is promoted into this AC: "the preamble at git.md:29 is ≤40 lines". [DR-27(c)] the second clause gets its own assertion: "exactly one line in dist/agents/git.md names a references/tracker/ path, and it is inside the preamble", non-vacuous against a seeded second naming line
- AC-2.6 — all
git-agent.test.ts guards green and the guard count has not decreased; registry Guard 6 green with op names unchanged [DR-20] the guard-count accounting explicitly records the D10 scope guard's successor pair so the replacement is visibly not a net loss
- AC-2.7 — every generated Phase-2 reference line is reachable on the
gh path; no _mcp.md exists after a GitHub-only build; no Jira/Linear literal anywhere amended to the positive form: every generated Phase-2 reference line is reachable on the gh path; after a GitHub-only build not exists('references/tracker/_mcp.md') and '_mcp.md' not in read(references/tracker/github/{op}.md) for every op. Per Gate-2 D-D (clause (iii) read per phase), _mcp.md is NOT generated in Phase 2 — the guard text is re-scoped in 3a-4 (Conflict C5 / H7); Phase 2's wording is the correct Phase-2 form
- AC-2.8 — the retired-wording grep is clean against the Phase-2 allowlist
- AC-2.9 —
_tracker.mds ships the two-armed GitHub foreign-shape rule — ships two-armed from day one so no single-arm guard ever exists (clause (iii))
- AC-2.10 —
Tracked = #{n}, Depends on: #{n}, 42-jwt-auth.{ts}.md and issue: 42 byte-identical to Phase 0 under github
- AC-2.11 — UAC-28 (shadow overlay) is a release blocker, not merely an AC — Gate-2 D-B: the test is AC-2.4a; the "release blocker" label is a process label recorded in the release-readiness subsection — the label is
(process-only — PR checklist)
- AC-2.12 (new) —
collectSkillRefFiles is recursive, so the references/tracker/** guards are non-vacuous — lands in T1, in the same commit that creates the subtree (Conflict C7)
- AC-2.13 (new) — the D4 and D11 legend rows survive in
git.md; no surviving label lacks its definition — asserted as a set relation, not per-row
- Prefix-shippability — After phase N: (i)
npm run build && npm test && npm run test:integration && npm pack --dry-run are green; (ii) a fresh install from the tarball drives /plan → /implement → /code-review → /resolve → /release on a GitHub project with no new prompt and no new file in git status; (iii) every artifact in the tree has at least one reachable consumer in this phase's end-state — no file, define, list element, frontmatter key or conditional arm exists solely for a later phase (ADR-003); (iv) the frozen github-status-lines.txt fixture is byte-identical to its Phase-0 capture.
Subtasks
| # |
Domain |
Owned files (with anchors) |
Steps |
Depends on |
Gate before next |
Handoff contents |
| T1 |
build script / prompt assets / tests |
scripts/build-mds.ts (flat (module, op) list, N ≥ 8 from its first commit) · new src/assets/mds/tracker/_github.mds · src/assets/agents/git.mds preamble insert at :29 (≤40 lines) · src/core/mds-variants.ts (expandVariants introduced here, [DR-16]) · src/core/assets.ts (compiledSkillRefsDir()) · new tests/tracker/byte-budget.test.ts · tests/mds-variants.test.ts (the expandVariants describe moved in from Phase 1) · tests/skill-references.test.ts:96-108 (collectSkillRefFiles → recursive) |
P2-S1, P2-S2, P2-S3, P2-S13 |
Phase 1 merged to main |
G2.1 |
the (module, op) manifest as shipped (N ≥ 8 names); the preamble's final line count against the ≤40 ceiling and byte count; the load-instruction literal verbatim, so T2 restates it identically per op; the four-shape table's named rows incl. learn-conventions.md and publication-gate.md ([DR-12]); the explicit statement that the golden is expected RED from here |
| T2 |
prompt assets |
src/assets/agents/git.mds (10 ops' **Process:** blocks; D4 :22-28 / D11 :43-59 invariant-detector split; legend :84-98 per E10; D10 :30-41; learn-conventions :517-565; the two new Output-block producer lines) · src/assets/skills/git/SKILL.md (:73, :115-127, :152, :192-199, :206-214, :232-251, :252-264, :265-273) · src/assets/skills/git/references/github-api.md (5 tracker sections) |
P2-S4, P2-S5, P2-S6, P2-S7, P2-S8 |
T1 |
G2.2 |
the per-op retained/moved table (a Phase-2 gate deliverable per GAP-01) — one row per op × {moved lines, retained lines, extraction mode 'union'/'sole' used by each guard that reads it ([DR-18])}; the containment-test exemption list with a justification per rewritten range ([DR-17]); the exact - **PR link line**: and - **Branch token**: Output-block literals now emitted by setup-task and fetch-issue (verbatim, for T3); measured bytes(dist/agents/git.md) and bytes(SKILL.md) against the pins ≤ 49,600 / ≤ 6,600 |
| T3 |
prompt assets (commands + partials) |
new src/assets/commands/_partials/_tracker.mds · plan.mds · implement.mds · debug.mds · dynamic-build.mds (:73, :466-474, :522) · dynamic-plan.mds · _partials/_ticket_template.mds · _partials/_wave.mds · _partials/_engine.mds:232 · _partials/_preamble.mds:31, :75 · src/assets/agents/code.md (:35, :93, :95, :99) · src/assets/skills/docs-framework/SKILL.md (:45, :106, :144) · resolve.mds (:244, :352, :499, :508, :539, :619) · plan.mds (:350, :404, :440) |
P2-S9, P2-S10, P2-S11, P2-S12 |
T2 (producers land in T2's Output blocks; T3 wires the consumers — Conflict C11) |
G2.3 |
the five hosts that adopted _tracker.mds and their @import line numbers; confirmation that dynamic-build.mds:522's marker literal is gone and build-mds.test.ts:853 was replaced by the negative guard; the two disposition lines (_engine.mds:232 guard-with-test; _preamble.mds:75 explicit NO-CHANGE) |
| T4 |
installer + CLI |
src/targets/claude-code/installer.ts:571 + :37-45 · new recursive path-keyed prune (beside src/core/orphan-sweep.ts) · src/cli/commands/init.ts:1911 (formatOverlaySummary) · new tests/installer/reference-overlay.test.ts · tests/installer-new.test.ts (error-text repoint only) |
P2-S14 |
T1 (needs the generated tree in dist) |
G2.4 |
InstallReport's new field names (overlaidRefs, overlayFailures) and the render site; the manifest path the prune converges against; the atomic-provider-swap contract ([DR-05]) as implemented |
| T5 |
tests + docs |
tests/git-agent.test.ts (corpus follows the moved text) · tests/build-mds.test.ts · new tests/tracker/containment.test.ts · new tests/dynamic/depends-on-grammar.test.ts · new tests/guards/capability-hoist.test.ts ([DR-11] — renamed from identity-hoist) · widened INLINE_BODY_RE · the negative-guard battery · then, in its own commit, tests/fixtures/golden/git-agent.md regenerated · docs sweep |
P2-S15, P2-S16, P2-S17 |
T2–T4 |
G2.5 |
— (terminal) |
Gates
| Gate |
Must be green before |
Assertion |
| G2.1 |
T2 starts |
npm run build exits 0 with the new (module, op) list; the preamble compiles into dist/agents/git.md and is ≤40 lines; collectSkillRefFiles is recursive and sees the new subtree; expandVariants has ≥ 8 real pairs. The golden is expected RED from here — record the expectation explicitly in the handoff so no agent "fixes" it. |
| G2.2 |
T3 starts |
Containment: zero unaccounted lines across git.md ∪ dist/skills/git/references/** incl. the moved github-api.md / SKILL.md lines (AC-2.2), with the exemption list asserted non-empty and justified. Byte-budget table green: ≤ 49600 / ≤ 6600 / loaded set ≤ 71562 (AC-2.5). D11 floor >= 8 over the joined corpus in mode 'union', not lowered (AC-2.3). AC-2.13 (D4/D11 legend rows survive). |
| G2.3 |
T4 starts |
_tracker.mds two-armed rule present (AC-2.9); Tracked = #{n}, Depends on: #{n}, 42-jwt-auth.{ts}.md, issue: 42 byte-identical under github (AC-2.10); frozen status lines unchanged. |
| G2.4 |
T5's golden-regeneration commit |
AC-2.4a/b/c all green (shadow overlay, atomic unreadable-reference isolation, injected-file prune); the references/tracker/** guards proven non-vacuous (AC-2.12). |
| G2.5 |
PR opens |
Full prefix-shippability (i)–(iv); git-agent.test.ts guard count has not decreased (AC-2.6); the golden regeneration is a standalone commit reviewed as a text diff. |
/implement spawn notes
- One Code agent per subtask, strictly sequential; each verifies with
npm run build && npm test && npm run test:integration && npm pack --dry-run before handing off (R6: every commit is green on its own).
- T2 is spawned with the per-op commit instruction as its default (D-G(a)) — 10 pathspec-scoped commits, containment test after each.
gather-release-evidence is two commits (A then B) per [DR-17], so T2 lands 11 commits.
- Every prompt carries the H2 standing instruction and the "golden expected RED" statement verbatim.
- Every prompt carries §14's normative appendix inline. Do not pass a path to this artifact as a substitute —
.devflow/docs/ is gitignored.
CREATE_PR: false and PUSH: false on T1–T4; CREATE_PR: true and PUSH: true on T5, whose terminal act (after the golden-regeneration commit) opens the PR at G2.5. PUSH is a Code-agent input (code.md:34) that implement.mds's spawn template does not carry — state it explicitly in each spawn prompt.
HANDOFF_REQUIRED: true on T1–T4; each writes .devflow/docs/handoff-{branch_slug}.md with the Handoff-contents column of the §6 table; T5 reads it.
Execution strategy
SEQUENTIAL_CODE_AGENTS — 5 subtasks (T1 → T5). Context risk: CRITICAL.
Largest phase by volume (~40 files, ~2,500–3,500 lines) across four distinct domains, bound by one invariant that spans all of them: the containment test's zero unaccounted lines across git.md ∪ generated references.
Two parallel candidates were evaluated and rejected:
- Installer overlay (TS) ∥ prompt split (assets) — write-disjoint, but the overlay's tests install from
dist/skills/git/references/tracker/**, which only exists after the split's build manifest lands. Read closure overlaps completely.
- Command layer (
_tracker.mds + 5 hosts) ∥ git.md op split — write-disjoint, but both mutate tests/build-mds.test.ts (partial manifest, escaped-brace guard, DIST_FILES scope) and both sit inside the seam test's and the frozen fixture's corpus.
Plus the feature-wide disqualifier (PF-020 closure rule, DR-23 ALREADY-ADDRESSED): npm run build is rm -rf dist && … (package.json:20) in a shared worktree, and /implement has no worktree isolation (grep for worktree in implement.mds returns zero hits). Every Code agent's verification step deletes the shared dist/ while a sibling is mid-suite, and Phase 0 deliberately makes every dist-scanning guard fail loud on a missing directory (R3 / AC-0.16). Any concurrent pair manufactures nondeterministic red. This is a tooling limitation, not a plan limitation, and it holds for all four phases.
PR title
refactor(git-agent): split tracker mechanics into generated GitHub references
Implementation Plan
Design artifact (authoritative): .devflow/docs/design/tracker-phase-2.2026-09-05_1155.md — local and gitignored. A copy truncated at the 60k comment cap is posted as a collapsed comment: #324 (comment). Run with /implement .devflow/docs/design/tracker-phase-2.2026-09-05_1155.md. Tracking issue: #321.
Initial Request
src/assets/agents/git.mdis 938 L / 59,376 ch [verified @ e726874], re-sent on every Git spawn (PF-026: a shared agent prompt file is billed PER SPAWN). Roughly 9,400 of those characters are GitHub-specific mechanics —ghinvocations, header names, rate-limit detectors — interleaved with the provider-independent contract (each op's**Input:**, its**Output:**template, its**Degradation (D4):**clause, the D4/D11 invariants).Three live consequences:
src/assets/skills/git/SKILL.md(283 L / 9,236 ch) carries two live safety contradictions::196if [ "$REMAINING" -lt 10 ]; then sleep 60; fi[verified] directly contradicts D4's STOP-the-fan-out rule atgit.md:25; and:211gh release create … --notes "$NOTES"[verified — [drift: plan-1, plan-2 and §B.2 all cite:212; the live line is:211]] is an inline-body recipe wherecreate-releasemandates--notes-fileafter a scrub whose failure is a HARD fail. Both are invisible to every existing guard:INLINE_BODY_RE(tests/git-agent.test.ts:412[verified]) matches onlygh (?:pr|issue), andGIT_AGENT_PATHscans onlygit.md.Phase 2 splits contract from mechanics for GitHub only, moving mechanics into generated per-op skill references addressed skill-relatively, adds a ≤40-line provider-resolution preamble at
git.md:29[verified::29is the blank line after the D4 block:22-28and before## Publication gate (D10)at:30], replaces five divergent inline issue-parse rules in the command layer with one neutral vocabulary partial, and installs the generated references with a converge-not-merge staged swap that a shadow cannot subvert.Honest user-visible-change statement (the phase label)
Phase 2 therefore delivers zero user-facing value and introduces two new failure modes (an overlay that can partially fail; a generated reference that can be absent at runtime) — GAP-45. That is recorded deliberately, not hidden: the release-coupling decision is in §2, release readiness.
Execution:
SEQUENTIAL_CODE_AGENTS· context-risk: CRITICAL · Design artifact:.devflow/docs/design/tracker-phase-2.2026-09-05_1155.md(authoritative; local, gitignored — a 60k-truncated copy is posted as a collapsed comment).Product Requirements
Depends on
Phase 1 (#323) merged to
main. Tracking issue: #321.Acceptance criteria
github-api.md/SKILL.mdlines)>= 8over the joined corpus, not lowered, and fail on a known-bad sample [DR-18] the D11 forward guard extracts with mode'union'over the joined corpus, named explicitly at the call sitedevflow:gitreceives the canonical GitHub referencesInstallReport.overlayFailuresnames the provider, and the install succeeds; an absent canonical GitHub reference ⇒ loud failure with a build hint — the provider directory is atomic: a per-file failure aborts that provider's swap,rms the tmp tree, and pushes the provider ontooverlayFailures— it never renames a partial tree over a good onereferences/tracker/**not in the manifest is absent after installbytes(dist/agents/git.md) ≤ 49600,bytes(skills/git/SKILL.md) ≤ 6600, loaded set≤ 71562on the worst-case tracker spawn, each a named constant with its derivation in a comment, evaluated as a four-shape table test; the only reference-naming line outside a tracker-op section is the single preamble load instruction [DR-12] the loaded-set formula gains+ max over ops of (sum of every reference file that op's load instructions can name in one spawn), with a bidirectional structural check. [DR-13(a)] the preamble ceiling is promoted into this AC: "the preamble atgit.md:29is ≤40 lines". [DR-27(c)] the second clause gets its own assertion: "exactly one line indist/agents/git.mdnames areferences/tracker/path, and it is inside the preamble", non-vacuous against a seeded second naming linegit-agent.test.tsguards green and the guard count has not decreased; registry Guard 6 green with op names unchanged [DR-20] the guard-count accounting explicitly records the D10 scope guard's successor pair so the replacement is visibly not a net lossghpath; no_mcp.mdexists after a GitHub-only build; no Jira/Linear literal anywhere amended to the positive form: every generated Phase-2 reference line is reachable on theghpath; after a GitHub-only buildnot exists('references/tracker/_mcp.md')and'_mcp.md' not in read(references/tracker/github/{op}.md)for every op. Per Gate-2 D-D (clause (iii) read per phase),_mcp.mdis NOT generated in Phase 2 — the guard text is re-scoped in 3a-4 (Conflict C5 / H7); Phase 2's wording is the correct Phase-2 form_tracker.mdsships the two-armed GitHub foreign-shape rule — ships two-armed from day one so no single-arm guard ever exists (clause (iii))Tracked = #{n},Depends on: #{n},42-jwt-auth.{ts}.mdandissue: 42byte-identical to Phase 0 undergithub(process-only — PR checklist)collectSkillRefFilesis recursive, so thereferences/tracker/**guards are non-vacuous — lands in T1, in the same commit that creates the subtree (Conflict C7)git.md; no surviving label lacks its definition — asserted as a set relation, not per-rownpm run build && npm test && npm run test:integration && npm pack --dry-runare green; (ii) a fresh install from the tarball drives/plan → /implement → /code-review → /resolve → /releaseon a GitHub project with no new prompt and no new file ingit status; (iii) every artifact in the tree has at least one reachable consumer in this phase's end-state — no file, define, list element, frontmatter key or conditional arm exists solely for a later phase (ADR-003); (iv) the frozengithub-status-lines.txtfixture is byte-identical to its Phase-0 capture.Subtasks
scripts/build-mds.ts(flat(module, op)list, N ≥ 8 from its first commit) · newsrc/assets/mds/tracker/_github.mds·src/assets/agents/git.mdspreamble insert at:29(≤40 lines) ·src/core/mds-variants.ts(expandVariantsintroduced here, [DR-16]) ·src/core/assets.ts(compiledSkillRefsDir()) · newtests/tracker/byte-budget.test.ts·tests/mds-variants.test.ts(theexpandVariantsdescribe moved in from Phase 1) ·tests/skill-references.test.ts:96-108(collectSkillRefFiles→ recursive)(module, op)manifest as shipped (N ≥ 8 names); the preamble's final line count against the ≤40 ceiling and byte count; the load-instruction literal verbatim, so T2 restates it identically per op; the four-shape table's named rows incl.learn-conventions.mdandpublication-gate.md([DR-12]); the explicit statement that the golden is expected RED from heresrc/assets/agents/git.mds(10 ops'**Process:**blocks; D4:22-28/ D11:43-59invariant-detector split; legend:84-98per E10; D10:30-41;learn-conventions:517-565; the two new Output-block producer lines) ·src/assets/skills/git/SKILL.md(:73,:115-127,:152,:192-199,:206-214,:232-251,:252-264,:265-273) ·src/assets/skills/git/references/github-api.md(5 tracker sections)'union'/'sole'used by each guard that reads it ([DR-18])}; the containment-test exemption list with a justification per rewritten range ([DR-17]); the exact- **PR link line**:and- **Branch token**:Output-block literals now emitted bysetup-taskandfetch-issue(verbatim, for T3); measuredbytes(dist/agents/git.md)andbytes(SKILL.md)against the pins ≤ 49,600 / ≤ 6,600src/assets/commands/_partials/_tracker.mds·plan.mds·implement.mds·debug.mds·dynamic-build.mds(:73,:466-474,:522) ·dynamic-plan.mds·_partials/_ticket_template.mds·_partials/_wave.mds·_partials/_engine.mds:232·_partials/_preamble.mds:31,:75·src/assets/agents/code.md(:35,:93,:95,:99) ·src/assets/skills/docs-framework/SKILL.md(:45,:106,:144) ·resolve.mds(:244,:352,:499,:508,:539,:619) ·plan.mds(:350,:404,:440)_tracker.mdsand their@importline numbers; confirmation thatdynamic-build.mds:522's marker literal is gone andbuild-mds.test.ts:853was replaced by the negative guard; the two disposition lines (_engine.mds:232guard-with-test;_preamble.mds:75explicit NO-CHANGE)src/targets/claude-code/installer.ts:571+:37-45· new recursive path-keyed prune (besidesrc/core/orphan-sweep.ts) ·src/cli/commands/init.ts:1911(formatOverlaySummary) · newtests/installer/reference-overlay.test.ts·tests/installer-new.test.ts(error-text repoint only)dist)InstallReport's new field names (overlaidRefs,overlayFailures) and the render site; the manifest path the prune converges against; the atomic-provider-swap contract ([DR-05]) as implementedtests/git-agent.test.ts(corpus follows the moved text) ·tests/build-mds.test.ts· newtests/tracker/containment.test.ts· newtests/dynamic/depends-on-grammar.test.ts· newtests/guards/capability-hoist.test.ts([DR-11] — renamed fromidentity-hoist) · widenedINLINE_BODY_RE· the negative-guard battery · then, in its own commit,tests/fixtures/golden/git-agent.mdregenerated · docs sweepGates
npm run buildexits 0 with the new(module, op)list; the preamble compiles intodist/agents/git.mdand is ≤40 lines;collectSkillRefFilesis recursive and sees the new subtree;expandVariantshas ≥ 8 real pairs. The golden is expected RED from here — record the expectation explicitly in the handoff so no agent "fixes" it.git.md ∪ dist/skills/git/references/**incl. the movedgithub-api.md/SKILL.mdlines (AC-2.2), with the exemption list asserted non-empty and justified. Byte-budget table green:≤ 49600/≤ 6600/ loaded set≤ 71562(AC-2.5). D11 floor>= 8over the joined corpus in mode'union', not lowered (AC-2.3). AC-2.13 (D4/D11 legend rows survive)._tracker.mdstwo-armed rule present (AC-2.9);Tracked = #{n},Depends on: #{n},42-jwt-auth.{ts}.md,issue: 42byte-identical undergithub(AC-2.10); frozen status lines unchanged.references/tracker/**guards proven non-vacuous (AC-2.12).git-agent.test.tsguard count has not decreased (AC-2.6); the golden regeneration is a standalone commit reviewed as a text diff./implementspawn notesnpm run build && npm test && npm run test:integration && npm pack --dry-runbefore handing off (R6: every commit is green on its own).gather-release-evidenceis two commits (A then B) per [DR-17], so T2 lands 11 commits..devflow/docs/is gitignored.CREATE_PR: falseandPUSH: falseon T1–T4;CREATE_PR: trueandPUSH: trueon T5, whose terminal act (after the golden-regeneration commit) opens the PR at G2.5.PUSHis a Code-agent input (code.md:34) thatimplement.mds's spawn template does not carry — state it explicitly in each spawn prompt.HANDOFF_REQUIRED: trueon T1–T4; each writes.devflow/docs/handoff-{branch_slug}.mdwith the Handoff-contents column of the §6 table; T5 reads it.Execution strategy
SEQUENTIAL_CODE_AGENTS— 5 subtasks (T1 → T5). Context risk: CRITICAL.Largest phase by volume (~40 files, ~2,500–3,500 lines) across four distinct domains, bound by one invariant that spans all of them: the containment test's zero unaccounted lines across
git.md ∪ generated references.Two parallel candidates were evaluated and rejected:
dist/skills/git/references/tracker/**, which only exists after the split's build manifest lands. Read closure overlaps completely._tracker.mds+ 5 hosts) ∥git.mdop split — write-disjoint, but both mutatetests/build-mds.test.ts(partial manifest, escaped-brace guard,DIST_FILESscope) and both sit inside the seam test's and the frozen fixture's corpus.Plus the feature-wide disqualifier (PF-020 closure rule, DR-23 ALREADY-ADDRESSED):
npm run buildisrm -rf dist && …(package.json:20) in a shared worktree, and/implementhas no worktree isolation (grep forworktreeinimplement.mdsreturns zero hits). Every Code agent's verification step deletes the shareddist/while a sibling is mid-suite, and Phase 0 deliberately makes every dist-scanning guard fail loud on a missing directory (R3 / AC-0.16). Any concurrent pair manufactures nondeterministic red. This is a tooling limitation, not a plan limitation, and it holds for all four phases.PR title
refactor(git-agent): split tracker mechanics into generated GitHub referencesImplementation Plan
Design artifact (authoritative):
.devflow/docs/design/tracker-phase-2.2026-09-05_1155.md— local and gitignored. A copy truncated at the 60k comment cap is posted as a collapsed comment: #324 (comment). Run with/implement .devflow/docs/design/tracker-phase-2.2026-09-05_1155.md. Tracking issue: #321.