Conversation
…in Principles (#328) The cross-op sentence "This applies to all comment-posting operations (…)" lived inside post-resolution-summary's compose step, where a reader of any OTHER comment-posting operation's section never reaches it. Move the cross-op scope to Principle 8 as its own sub-bullet, and leave post-resolution-summary's op-local clause stating only what that operation's own body must not reproduce. Principle 8 is where the containment contract is already stated once for the whole agent; naming the four posting operations there makes the rule reachable from the principle rather than from one operation's step 5. Refs #328
…rence module (#326, SG-8) git.md is billed on every Git spawn (PF-026), and half its operation roster was never a tracker fact: pull requests, PR reviews and PR checks stay on GitHub under every issue-tracker provider. Those eight operations' `**Process:**` bodies move to a new generated module, src/assets/mds/git/_pr.mds -> references/pr/{op}.md — one file set for everyone, installed unconditionally, named by a fixed literal path that composes nothing from the provider token. dist/agents/git.md: 58,803 -> 45,400 ch (920 -> 801 L). What deliberately STAYED, each for a guard that reads git.md alone: - both summary ops' sentence naming references/publication-gate.md ([DR-20](i) reads the agent alone); - post-resolution-summary's op-local non-reproduction clause (Principle 8 must be readable from the op's OWN section); - resolve-review-threads' step 3, the D9 gate application (D9 has one authority, and the frozen fixture samples that exact line); - every `**Input:**`, `**Degradation (D4):**` and `**Output:**`. SG-8 is satisfied as a condition, not waived: the two summary ops move in the same commit as their guards, every repointed guard carries a known-bad probe, and `## Comment-sink scrub (D11)` never leaves the agent. The non-vacuity proof SG-8 actually asks for is the new D11 probe — the posting SET is the same 8 ops before and after, so green alone proved nothing; dropping references/pr/ must take it to a named set of 5. Guard classification is per literal, at the call site, per ADR-025 — 'union' only where the text provably moved, 'sole' everywhere else. Two corpora are deliberately narrower than the full sink corpus: AC-0.6b's remote-I/O detection reads git.md union pr/ (the full union would detect setup-task through its PROVIDER mechanics, changing the guard's subject), and its D4-evidence half stays git.md-only (PF-027). The frozen fixture tests/fixtures/golden/github-status-lines.txt is BYTE-UNCHANGED: six entries joined STATUS_LINE_REFERENCE_FILES and two samples became straddle splits, but every sampled byte still exists in the same order. No re-capture authorisation was spent. Verified by cmp against main and by an --unfreeze --out-dir re-derivation. Floors raised (never lowered): installed-reference-count-github 13->21, installed-reference-count-provider 24->32, generated/packed manifest 34->42, capability-hoist-block-floor 49->57. New floor git-agent-remote-io-ops = 14, replacing a bare > 0 that one detected op satisfies. tests/fixtures/golden/git-agent.md is expected red until its own fixture-only commit (PF-057). Refs #326
The PR-host reference tree landed in the previous commit but nothing pruned it: `references/pr/` was overlaid and preserved whole by the full-install pre-clean, so a retired op's document, a shadow-supplied file, or a stale copy from an older build stayed inside the installed skill indefinitely. Parameterise the prune by subtree and drive it from one list: - D-CONVERGED-SUBTREES names `tracker/` and `pr/` — the directories whose every file is generated. The references ROOT stays exempt for the inverse reason (hand-authored documents beside the generated ones, no manifest of which is which — D-OVERLAY-FLAT-UNIT). - `prunePreservingRecoveryCopies` takes the subtree instead of hard-coding `tracker/` in three places, so a recovery copy stranded under one subtree skips THAT subtree only rather than refusing to converge the other. - `pruneConvergedSubtrees` merges the sweeps into the one SweepResult `ReferenceOverlayResult.pruned` and `recordSweep` already carry; no caller changes. Sweep names are now relative to the references ROOT (`pr/stale.md`, `tracker/probe-provider`). Merging two sweeps that each named paths relative to their own root would report `stale.md` for a file in either of them — an install-report line naming a file the user cannot find. It also matches the stranded-skip failure, which has always named its subtree from the root. `devflow tracker --set` needs no change: `pr/` is wanted under every provider (ADR-026), so a switch converges its contents and never adds or removes it. Tests: a `pr/` arm mirroring the tracker convergence arms — stale file removed and named, a deleted generated document put back, and the stranded-recovery scoping. Non-vacuity per ADR-024/PF-018: the replaced tracker-only rule is spelled out in the test and shown to leave the same seeded orphan standing. Verified RED by narrowing CONVERGED_SUBTREES to `[TRACKER_SUBTREE]` — the two convergence arms fail, the probe stays green. Refs #326
…he PR-host row (#326) The two phase-named git.md ceilings become one. BUDGET_GIT_MD is re-derived downward 55_750 -> 45_150 against a measured 45_068, and is now the live gate on dist/agents/git.md; the Phase-3 companion and the preamble-allowance arithmetic that split the file into two gated halves are gone, since a single number gates the whole artifact again. The three loaded-set rows fall with it, every character of the fall being git.md's: GitHub 80_200 -> 67_200 (measured 67_123), jira 89_500 -> 76_500 (76_427), linear 91_700 -> 78_700 (78_610). Each now sits below the value it was re-baselined from in September, so that authorisation is fully spent back. A fourth row is added. references/pr/ is installed under every tracker, so a PR operation costs the same bytes on all three paths and belongs on a row of its own rather than folded into the per-provider ones or onto the GitHub row, which is scoped to tracker ops. BUDGET_LOADED_SET_PR_HOST = 59_100 against a measured 59_033, with references/github-api.md as a written exclusion (LOADED_SET_WRITTEN_EXCLUSIONS): two of these ops loaded that file long before any split existed and #326 moved only the line that names it. What the exclusion owes in return is recorded row 2c-ex, which prints the same maximum with the file charged, plus an arm asserting the unexcluded figure would NOT fit under the ceiling -- so the exclusion is load-bearing, not a rounding convenience. The round-trip table's collector is generalised over the pointer prefix and now prints both vocabularies: 11 `**Mechanics:**` sites and 8 `**PR mechanics:**` sites. Both stay recorded, never asserted. Refs #326
…lit (#326) Fixture-only. `npm run test:golden:update -- git-agent` plus the equality baselines that pin it, all re-set from the updater's own output: GIT_AGENT_BYTES 58_549 -> 45_400 GIT_MD_CHARS 58_100 -> 45_068 GIT_MD_LINES 917 -> 801 TOTAL_CHARS 67_623 -> 54_591 TOTAL_LINES 1_222 -> 1_106 The SKILL_* pins do not move — neither skill file was touched — and tests/fixtures/golden/github-status-lines.txt stays byte-identical to main; its updater still refuses without --unfreeze, and no authorisation was spent. Reviewed as a text diff: the fixture loses the eight PR/review operations' step bodies and gains their `**PR mechanics:**` pointers, the load rule's PR-mechanics arm, the merged-step rule generalised to two references, the two reworded D10 naming sentences, post-resolution-summary's op-local non-reproduction clause, and Principle 8's #328 sub-bullet. All eighteen `## Operation:` sections and all eighteen `**Process:**` headings survive. Refs #326
…326) - Move the sinkCorpusWithoutPrHost JSDoc off gitPlusPrHostCorpus (it had landed on the wrong function during the split) and give gitPlusPrHostCorpus its own correct doc comment. - Factor the two known-bad probes that seed a defect into a single references/pr/{op}.md corpus entry into a shared seedPrHostFile helper, removing duplicated corpus-mapping scaffolding while keeping each probe's assertion and defect untouched.
Both probes restated their live arm's predicate inline instead of calling
it, so each stayed green after the arm it guards was weakened — the PF-018
shape every other probe in this branch avoids by driving a shared collector.
- reference-reachability: extract `anchorsOnLineOne(body, op)` and call it
from the PR-host parity arm and its probe; the probe also asserts the
positive direction, so a predicate gone constant-false is caught too.
- git-agent: hoist `REMOTE_PLACEHOLDER_RE` to describe scope so the
containment negative arm and its probe share one regex.
Proven by mutation: `startsWith` -> `includes` and narrowing the regex to
`/\{body\}/` each take the corresponding probe red, and neither did before.
- git-agent.test.ts: drop the unused PR_HOST_OPS import. - Hoist the D11 posting predicate into one isPostingSection() the live forward guard and its SG-8 known-bad probe both call, so narrowing it takes the guard (and the probe's named set) red instead of leaving a frozen copy of the old spelling behind. - Hoist the D10 per-op containment check into d10Reaches() and name the fail-closed literal once, so the known-bad probe reads the table it freezes rather than re-spelling its literal and its predicate. - Retitle the SG-8 probe: the narrowing is 8 -> 5, not a halving. - numeric-floors.json: restore the literal em-dashes and arrows that a whole-file re-serialization turned into \u escapes, cutting the diff against main from 18 hunks to the 5 that carry real entry changes. No floor or ceiling value changed. Refs #326
…D-INSTALL-SET The D-INSTALL-SET docblock said the build emits 34 reference files. It emits 42 since the eight PR-host operations gained their own module. Refs #326
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.
refactor(git-agent): move the 8 PR/review op bodies to references/pr and collapse the git.md ceilings (#326, #328)
Summary
Moves the 8 PR/review
**Process:**bodies out ofsrc/assets/agents/git.mdsinto a new,provider-independent reference module (
src/assets/mds/git/_pr.mds→ installed atreferences/pr/), then spends the recovered headroom by collapsing the phase-namedgit.mdbyte ceilings onto one live gate per shape and regenerating the golden.
Why
references/pr/and not a fourth provider tree.ensure-pr-ready,validate-branch,post-review-summary,check-ci-status,fetch-review-threads,resolve-review-threads,post-resolution-summaryandcheck-merge-readinessare PR mechanics, not issue-trackermechanics — PRs stay on GitHub under every tracker provider (
github,jira,linearallopen PRs on GitHub; only the issue side of tracker mechanics is pluggable). So the module is
installed unconditionally, once, converged the same way
references/tracker/is, rather thanduplicated per provider.
What stayed in
git.md. Every operation keeps its## Operation:heading and**Process:**label — pointing at**PR mechanics:** load references/pr/{op}.md— plus:resolve-review-threadsstep 3, applying the D9 gate, stays in the agent (it is an action,not documentation — see the Known trade-off note below);
references/publication-gate.md;post-resolution-summary's op-local non-reproduction clause.The
## Comment-sink scrub (D11)section is byte-identical tomain— SG-8 forbade moving it,and it didn't move.
#328 folded in. Commit
9af9764(fix(git-agent): state the comment-posting non-reproduction rule once in Principles) landed first: the cross-op non-reproduction sentencethat used to live inside
post-resolution-summarystep 5 — invisible to apost-review-summaryspawn that never reads that section — is now a Principle 8 sub-bulletevery spawn reads, with the op-local half restated at
post-resolution-summaryitself. Foldingit in first meant the SG-8 move (commit
decf75f) carried a settled cross-op rule rather thaninventing one mid-split.
Numbers
main)dist/agents/git.mdreferences/pr/**githubjira/linearCeilings — before → after
budget-git-mdbudget-git-md-p3budget-loaded-set(GitHub)budget-loaded-set-jirabudget-loaded-set-linearbudget-loaded-set-pr-hostpreamble-max-linesSupersession note.
budget-git-md-p3(58,870) was the live git.md gate andbudget-git-md(55,750) its declared base, kept apart so a Phase-3 preamble revision could be read as a delta
from an unraised number. #326 cut 13,032 characters out of the always-loaded agent, which makes
the split pointless: one number now gates the whole artifact. The pair is recorded as superseded
once, in
budget-git-md's manifest description; nothing in the source says "P3 removed"(ADR-003, and ADR-027's condition is met).
Every provider row now sits below the value its 2026-09-20 re-baseline raised it from (GitHub
below the pre-split 77,824, jira below 88,660, linear below 91,000) — that authorisation is
fully spent back.
The new PR-host row.
BUDGET_LOADED_SET_PR_HOST = PRELOADED + max over PR_HOST_OPS of (chars(pr/{op}.md) + every reference that op's own git.md section names). Nomax_opterm ofits own — an op's PR-host file is already inside its one-spawn load. Gate = 54,591 + 4,442
(
post-review-summary, the max) = 59,033.references/github-api.md(21,166 ch) is awritten exclusion (
LOADED_SET_WRITTEN_EXCLUSIONSinbudget-model.ts) — without it,fetch-review-threads/resolve-review-threadswould push the gate to 77,674, recorded as shape2c-exrather than gated. Non-vacuity is asserted twice: a named-set arm pinning that exactlyfetch-review-threadsandresolve-review-threadsreach the excluded file, and an arm assertingthe unexcluded figure would exceed the ceiling — so the exclusion is load-bearing, not a rounding
convenience.
Byte-budget recorded tables, verbatim at the branch tip:
SG-8 discharge
SG-8 forbade moving
post-review-summary/post-resolution-summarymechanics unless the D10and D11 guards move in the same PR. They did:
repointed to
gitPlusPrHostCorpus()—git.md ∪ references/pr/**— via a single namedpredicate,
d10Reaches(corpus, op, literal)(tests/git-agent.test.ts:1547), called by boththe live guard (
:1550) and the known-bad probe (:1561), and the fail-closed literal itselfis named once,
D10_FAIL_CLOSED_LITERAL = 'treat as PUBLIC'(:1518).isPostingSection(sec)(tests/git-agent.test.ts:1769) — one predicate, called by the ≥8forward guard (
:1772) and the SG-8 known-bad probe (:1827).d11-posting-opsstays>= 8— the posting SET is still thesame 8 operations before and after the move.
Non-vacuity proof. The floor of 8 alone can't show the union corpus is load-bearing (the
forward guard stayed green through the whole move). Driving
isPostingSectionover the sinkcorpus with
references/pr/**dropped narrows the posting set from 8 to exactly 5, named(not counted, so losing one op and gaining an unrelated one can't pass as agreement):
Three of the eight vanish entirely (
post-review-summary,post-resolution-summary,resolve-review-threadspost only frompr/);ensure-pr-readysurvives at a reduced surfacebecause it sits in both rosters — step 4a's create moved to
pr/, step 4b's edit stayed intracker/{provider}/.Mutation proof on
isPostingSection. Narrowing the predicate (e.g. dropping the-F body=@arm) takes both the forward guard and the SG-8 probe red together, because both nowread the same function — there is no longer a second, frozen copy of the rule that could stay
green after the live one is weakened.
Containment proof
Transient script (never committed): for every non-blank line of the 8
**Process:**bodies atmain:src/assets/agents/git.mds, asserts the line is verbatim in_pr.mdsor a declaredRETAINED / REWORDED / DELETED exception; for every non-blank line
git.mdsgained vsmain,asserts it matches a declared insertion.
Frozen fixture
tests/fixtures/golden/github-status-lines.txtis byte-identical tomain(
cmp: IDENTICAL);extractStatusLines()was retargeted instead (six newpr/entries inSTATUS_LINE_REFERENCE_FILES, plus two more straddle splits). No re-capture authorisation wasrequested or spent — the three prior authorisations on this fixture remain fully spent, and this
branch adds none.
Red-proof table
gitPlusPrHostCorpusdetection scope (AC-0.6b remote-I/O sweep)tests/git-agent.test.ts:101setup-taskgets detected as remote-I/O through PROVIDER mechanics it never touched — a subject change the guard must not tolerate; kept scoped togit.md ∪ pr/deliberately (deviation 3)d10Reachestests/git-agent.test.ts:1547(predicate),:1550(live),:1561(probe)seedPrHostFile('post-review-summary', …)deletes'treat as PUBLIC'from onepr/filed10Reachesthe live guard calls; reports exactlypost-review-summary, not the sibling op that still carries the sentenceisPostingSectiontests/git-agent.test.ts:1769(predicate),:1772(forward, ≥8),:1827(SG-8 probe)sinkCorpusWithoutPrHost()— dropreferences/pr/**from the corpus[backlink-shipped-issues, ensure-pr-ready, ensure-traceable-issue, manage-debt, post-wave-report]; mutation ofisPostingSection(e.g. dropping the-F body=@arm) takes both the guard and the probe red togetheranchorsOnLineOnetests/tracker/reference-reachability.test.ts:328(predicate),:538(probe)displaced = "Load this first.\n\n## Operation: {op}\n…"(anchor not on line 1)anchorsOnLineOnethe live arm calls; fails on the displaced body AND asserts the positive direction (wellFormed) so a predicate gone constant-false is also caught (mutation:startsWith→includestakes it red)REMOTE_PLACEHOLDER_REtests/git-agent.test.ts:2406(shared regex),:2408(live arm),:2471(probe)pr/compose template withEcho the thread {title} verbatim.git.md; mutation: narrowing the regex to/\{body\}/takes the probe redpruneTrackerSubtreeOnly(frozen pre-#326 rule) vs. liveoverlayGeneratedReferencestests/installer/reference-overlay.test.ts:733(frozen rule),:803/:815(live), known-baditimmediately following:803pr/retired-op.mdleft by an older buildpr/retired-op.md); the frozenpruneTrackerSubtreeOnlyprobe leaves the SAME file standing and never names it — proving the old rule really was tracker-scoped, not merely undertestednameableFromseeded readertests/tracker/budget-model.ts:220; probe attests/tracker/byte-budget.test.ts:1064Then read \references/smuggled.md` for the rest.` only for the PR-host op's own filenameableFrom(op, injectedReader)reports[op → smuggled.md]— proves the PR-host hop is reachable through the injected reader without writing intodist/mid-suite (PF-055)FORBIDDEN_SCOPEStests/guards/provider-scope.test.ts:420(list),:432(loop)dist/skills/git/references/pr/seeded with ajira/lineartoken in its header proseinScope.length > 0) and provider-token-free the same as thegithubtree — apr/file naming a provider is flagged exactly like one undertracker/github/would be; this caught the real "jira user" phrase in_pr.mds's header during this branch (deviation 6)Two commits made these probes trustworthy rather than merely present:
538da24hoistedanchorsOnLineOneandREMOTE_PLACEHOLDER_REto describe-scope so the live arm and itsknown-bad probe read the same predicate/regex instead of two independently hand-spelled copies
(proven by mutation:
startsWith→includesand narrowing the regex each now take theprobe red, which they did not before);
83f6c2fdid the same forisPostingSectionandd10Reaches/D10_FAIL_CLOSED_LITERAL, and retitled the SG-8 probe (the narrowing is 8→5, not ahalving).
Deviations from the plan
git.md ∪ pr/, not the full sink corpus. Overthe full union,
setup-taskis detected as remote-I/O through its provider mechanics — textan earlier phase moved, for an op this commit never touched — changing the guard's subject.
Widened to exactly what git.md: second size cut — move the 8 PR/review op bodies to references (SG-7) #326 moved (
gitPlusPrHostCorpus()), the ADR-025-correct reading.ensure-pr-readysurvivesthe narrowing (it's in both rosters), so the correct assertion is a named set — a bare count
of 5 is equally satisfied by losing
ensure-pr-readyand gaining an unrelated op.[DR-20](ii)'s distinctness assertion is scoped to the three expected basenames, notcorpus-wide.
ensure-pr-ready.mdnow legitimately exists at four paths (pr/+ threeproviders), so a corpus-wide distinctness check is false on its face. Scoped instead to: each
of the three expected labels names exactly one file.
before commit 2 (
decf75f) returned 13,400. The Principle-8 bullet costs more than thesentence it replaced; kept the settled wording verbatim rather than shrinking it to buy back
200 bytes commit 2 returns 60× over. All three ceilings are green at the tip with large
margins — squash-merge makes the transient breach moot, noted here for the record.
manage-debt-archive-capoccurrences4 → 6. Two new summary-cap known-bad probes arecounted sites under the existing
toContain('60000')pattern; left at 4, the non-vacuityprobe stops discriminating. The
flooritself is untouched.pr/stale.md), not sub-root-relative(
stale.md) — plain concatenation would make astale.mdremoved frompr/and oneremoved from
tracker/render as the same user-facing string.2csplit into gated2cand recorded2c-ex. Two rows were added, not tworeplacing five:
2cis the gated PR-host figure (54,591 + 4,442 = 59,033),2c-exis thesame maximum with the
github-api.mdexclusion charged (54,591 + 23,083 = 77,674) —recorded, not gated, so a reader can always tell which number the ceiling actually enforces.
Known trade-off
resolve-review-threadsis a three-part straddle:pr/holds the loop preamble plus steps 1,2 and 4;
git.mdkeeps step 3 — applying the D9 gate — because it is an action, notdocumentation. This is the first PR-host split where the retained git.md half is executable
rather than a pointer or a naming sentence. Mitigated by the merged-step rule (generalised in
this branch to cover two references): every loaded reference's steps carry this operation's own
ordering, so step 3 interleaves correctly with the moved steps by number regardless of which
file it physically lives in.
Verification
npm run build && npx vitest run --exclude 'tests/eager-memory-refresh.test.ts'→ 155 files / 5,537 tests, 0 failures, 48.9s. Known flakes named and shown not to be this
branch:
model-discoveryT1 (passed first time this run),decisions-usage-scanlock timing,and
redact-secretsadversarial backtracking-budget (Phase A observed it once; provenpre-existing by stashing all changes and re-running the same file, which failed on a
different test) — each green standalone / on later runs.
npm run test:integration→ 5 files / 50 tests, 0 failures, 38s.git status --porcelainempty afterwards.npm pack --dry-run: 434 files, 1.2 MB; 42 files underdist/skills/git/references/(floor
packed-reference-manifest-size= 42, exact), 8 underpr/.HOMEforced to a scratch dir (real~/.claudeverified untouchedthroughout):
pr/stale.mdis pruned on the very nextinit— the installer prune now convergesreferences/pr/the same way it convergesreferences/tracker/(D-CONVERGED-SUBTREES).Follow-ups
CLAUDE.md,CHANGELOG.md,docs/reference/**, plus registering the retired literals58,870and55,750intests/guards/retired-wording.test.tsonce the changelog prose thatstill spells them is edited.
tracker-references/KNOWLEDGE.md,test-harness/KNOWLEDGE.mdandinstaller-shadowing/KNOWLEDGE.mdare stale on the counts,the retired ceiling names, and the D-CONVERGED-SUBTREES prune boundary.
check-ci-statusstep-5 classifier non-total bug — pre-existing inmain, moved verbatiminto
references/pr/check-ci-status.mdby this PR, not fixed by it. Filed separately:see
check-ci-statusstep 5 classifier is not total;check-merge-readinessdefaults to READY on the gap #352.<300 linestarget) and item 1 of chore(prompt-surface): put devflow on a diet — condense every installed surface without losing detail #342's scope(moving the 8 PR/review op bodies, as a funding step toward its devflow-wide token diet) are
the parts this PR makes progress on or closes outright — see Related Issues below for which is
which.
55,750) and the knowledge-base refresh are pending user approval and will land on this branch
before merge.
Related Issues
Closes #326
Closes #328
Refs #289 — this PR does not meet #289's own acceptance criterion of
git.mdunder 300 lines(now 801, down from 917); substantial progress, not full closure.
Refs #342 — this PR completes item 1 of #342's scope (the git.md PR-host cut); the remaining
prose pass and the rest of the devflow-wide diet are still open.