Files
spiky02plateau 5a429c1da1 feat(skills): make Printing Press phases progressive and resumable (#3723)
* feat(skill): restructure SKILL.md into router + phases/ progressive disclosure

Split the 333 KB main skill into a ~5k-token router and 21 per-phase
files under skills/printing-press/phases/, read at phase entry like
references/. Phase bodies moved verbatim (byte-coverage verified);
cross-phase references repaired to name their files; each phase file
ends with a Next: pointer.

Closes #3708

* feat(skill): update phase pointers in sibling skills, tests, and docs

Point sibling skills (polish, reprint, output-review, publish, retro),
the skill-reading Go tests, verify-go-floor.py, and current docs at the
new phases/ files. Historical brainstorms and retros keep their original
references as records.

Refs #3708

* test(skill): bundle phases/ into contract readers, validate phase chain

Teach the pipeline contract reader to concatenate the router with its
phases/ files so section-marker contracts keep holding after the split;
update one reprint-skill assertion for the linked Phase 5.6 pointer; add
a chain-integrity test asserting the exact phases/ file set, the router
index referencing each file, and every Next: pointer targeting the
correct successor.

Refs #3708

* test(skill): use strings.Builder in bundled contract reader

Refs #3708

* test(skill): assert router phase index positionally, not by substring

Parse the phase-index table rows in document order and require each
row's link text and target to agree and to match the expected file at
that position, so a swapped row or text/target mismatch fails.

Refs #3708

* feat(skill): add execution-context slicing rules to build and dogfood phases

Validated across three full production prints: phase-scoped instruction
loading is necessary but not sufficient for the heavy phases. Phase 3's
instructions are ~14k tokens, but its execution on a 35+ command CLI can
pass 300k tokens in a single agent, degrading instruction-following long
before anything visibly fails. The same applies to full live dogfood
matrices.

Add to the build phase: a per-agent context budget (~150-200k), a
canonical slice order (foundation -> core engine -> analytics ->
ingest/report/close), build-green slice boundaries, and artifact-based
handoff via the build log.

Add to the dogfood phase: the same budget with a proofs-dir handoff
entry, continuing in a fresh agent; the runner-owned acceptance-marker
workflow is explicitly unchanged.

* fix(skills): enforce durable phase handoffs

* fix(skills): polish durable phase handoffs

* test(skills): validate explicit phase steps

* fix(cli): allow documented hold and rework handoffs in phase receipts

The receipt state machine only accepted the canonical linear order, but
the skill text documents seven non-linear routes: discovery rework from
the absorb and reachability gates, the build-infeasible return to the
absorb gate, the shipcheck hold jump to promote-and-archive, the review
scope-change return, and the promote-gate backtrack to dogfood. Any of
them would deadlock a live run at the receipt gate. Completing a phase
now accepts a --next limited to these documented handoffs; an alternate
handoff requires a note, cannot be combined with --skip, and everything
else stays canonical.

* refactor(cli): type receipt events and share the canonical phase graph

Receipt events were untyped string constants and the canonical phase
list was declared three times across the state machine and the skill
contract tests. Events now carry a named type per the categorical-const
rule, and the tests read the phase graph from the binary, so the skill
files are checked against the graph the machine actually enforces.

* fix(skills): record hold and rework handoffs in phase receipts

The skill documents seven non-linear routes, but the phase files never
said how to record them, so the receipt gate would reject the very
handoffs the text prescribes. Each route now records its receipt with
the documented --next and a note. The promote-phase marker gate is
scoped to ship verdicts so a hold run archives without dogfood markers
instead of bouncing back into the dogfood it deliberately skipped. The
router documents the full alternate set, the restart pointer for
interrupted phases, and where a fresh conversation finds the run's
state file.

* docs(skills): point skill-authoring trigger at phase files too

* style(cli): simplify alternate lookups per modernize lint

* fix(cli): survive torn writes to the phase receipt ledger

An interrupted append could leave a truncated final line, and the
strict reader then rejected the whole ledger, permanently blocking
status, enter, complete, and resume for that run. A malformed or blank
final line is now treated as a torn write that never happened - the
append was never acknowledged - while corruption anywhere else in the
ledger remains a hard error.

* fix(skills): keep sibling skills standalone, no cross-skill file paths

Review feedback: skills are installed as standalone folders, so a
sibling skill must not link files inside another skill's folder. Cross-
skill pointers now name the skill and phase semantically or are omitted
where the surrounding text already carries the meaning.

* test(cli): align reprint promote-routing contract with standalone wording

The standalone-skills pass reworded the reprint skill's Phase 5.6
reference from a cross-skill file link to semantic prose, but the
promote-routing contract test still asserted the old link form. The
test mirrors prose, so its expected phrase follows the rewording.

* fix(cli): repair torn ledger tail on append instead of only skipping it

Review caught a real gap in the torn-write recovery: the read path
tolerated a torn final line but left its bytes on disk, so the next
O_APPEND write fused the new receipt onto the fragment and later reads
dropped both. The writer now repairs the file before appending -
truncating a torn tail, or finishing a complete receipt that lost only
its newline - while anything the reader treats as hard corruption is
left untouched for it to report. Reads stay pure.

Tests cover the fusion scenario end to end: torn tail, then append,
then re-read returns the valid prefix plus the new receipt.

* refactor(cli): share one ledger parser and tighten torn-tail policy

Two review follow-ups on the receipt ledger:

The reader and the append-path repair each carried their own parsing
loop, inviting semantic drift. Both now share parsePhaseReceiptLedger,
the single statement of ledger shape. The torn-tail tolerance also
narrows: the writer emits each receipt and its newline in one ordered
write, so an interrupted append can only leave an unterminated final
fragment. A malformed line that ends in a newline is genuine corruption
and hard-errors again instead of being silently dropped.

Stored-receipt validation now enforces the writer's alternate-route
invariants on read as well: a completed alternate handoff requires a
note, and a skipped receipt can never take an alternate handoff.

* fix(cli): let rework return to the gate that ordered it

The absorb and reachability gates both route discovery rework into
06-browser-sniff-gate, which carried no outbound alternate edges. Nothing
was skipped - expectedNextPhase is index+1, so a run sent 09 --next 06
walks back forward through 07, 08 and 09 and every transition validates.
The cost is the replay itself: re-entering 08-ecosystem-absorb-gate means
re-entering its unconditional "WAIT for approval" step, so a cleared-browser
capture retry re-prompts the user to re-approve an unchanged absorb
manifest. Phase 09's own text says only to re-enter Phase 1.7 and never
mentions re-approval, so prose and graph disagreed and the user paid for it.

Give 06 a return edge to exactly the gates that can order rework into it,
the absorb gate and the reachability gate. The edge is the inverse of the
existing rework edge and nothing more.

07-crowd-sniff-gate deliberately gets no entry. The absorb gate is the only
gate that reworks it, and the absorb gate is already 07's canonical next, so
the return route it needs is the canonical edge and always was. Adding it to
the alternate map would change no routing decision and would put a duplicate
in the allowed-handoff list that allowedNextPhases builds. The doc comment
above the map now states the rule with that carve-out, so the next rework
edge added carries its return edge only when the canonical next does not
already provide one.

06's phase file gains the two matching alternate completion blocks, prefaced
by the rule that a phase entered from a rework handoff completes back to its
sender rather than to Next:. The --next targets in those blocks are read from
the binary graph by the skill contract test, so the files and the state
machine keep cross-checking each other.

TestPhaseReceiptsAcceptEveryDocumentedAlternateHandoff now derives its edge
list from the exported graph accessors instead of restating it as a literal.
The name was already overstating what a hand-maintained list covers, and
deriving it means an edge added later is covered without editing the test.

* refactor(skills): cut printing-press always-loaded context by 70%

The router was still 327 lines in the July shape while the phase split
carried every procedure it described. It reshapes to the same spine the
retro router landed with: Result / Next consumer / Done / Intent, then
Boundaries, Authority, Steps, and a bare two-column phase index. 98 lines,
locked by a test.

Nothing is rewritten, only relocated. Durable Phase Receipts becomes
references/phase-receipts.md verbatim, plus the 06 return edges that commit
"let rework return to the gate that ordered it" added to the graph and never
recorded in the router's handoff list. Orientation & Briefing and the
Multi-Source Priority Gate become references/run-resolution.md, the same
filename and the same job as the retro skill's: resolve what to build, from
what source, in what order. Codex Mode merges into the existing
references/codex-delegation.md, where the delegation loop it introduced has
lived since the split.

The ten Rules compress to four Boundaries. Six of them already say the same
thing in the phase file that enforces them: the dogfood matrix in 18,
ship-with-gaps in 12, absorb-gate scope in 08 and 11, the runstate layout in
02, the fix-loop cap in 12 and 18, fetch-docs in its own reference. The
Default and Polish Mode blocks are dropped; one described doing nothing
special and the other routed to a sibling skill the front-matter description
already routes. Outputs folds into Result. The per-phase purpose and gate
columns go with them.

Two pointers moved with the content and are repointed here rather than left
dangling: the six receipt assertions in the skill contract test now read
references/phase-receipts.md, and phases/03 no longer says the priority gate
is "above" when it is a reference away. Four phase files that deep-linked
router anchors now name the reference instead.

The publish skill's mandatory PII step names its file again. Replacing the
cross-skill traversal path with prose satisfied the standalone-skills rule
but left a step marked mandatory with nothing to execute.

* fix(cli): bind rework returns to the gate that ordered them

Giving 06-browser-sniff-gate return edges to both gates that rework it left
the pair unconstrained, and the two gates do not lead to the same place. A run
ordered back by the absorb gate (08 --next 06) could complete 06 --next 09,
and 09's canonical next is 10-generate, so generate proceeds on a capture the
absorb gate never re-reviewed. That is exactly the review the absorb gate
ordered the rework to get. The reverse mix is harmless only by accident: a
09-ordered rework returning via 08 still walks canonically back through 09.

Enforce the binding at complete time. printingPressReturnBoundPhases names the
phases whose alternate edges are pure return edges, today just 06. For those,
a non-canonical --next must equal the phase recorded in the most recent
handoff into this phase from one of its own alternates, and the error names
that origin. The scope matters: the map's other edges are not returns. 08 and
09 into the sniff gates order rework, 11 and 17 into 08 jump back to replay
forward, and 12 into 20 is a forward jump. A generic "return to your most
recent sender" rule would force the absorb gate entered from the local code
review to complete back to that review, which is not the contract.

Nothing loses its only route. The canonical handoff is never bound, so a run
that does want 07 and 08 re-run still completes 06 to 07 and replays forward
exactly as before the return edges existed. A 06 reached on the canonical
route now has no return edge at all, which is the same statement: its return
edges answer rework orders, and there is no order to answer.

The check reads the ledger slice CompletePhase already parsed, so the append
path still touches the file once and the read path stays pure. Stored ledgers
are validated as before, so a ledger written by an earlier binary still reads.

The derived-edges test now gives each return-bound walk the rework order that
makes its setup legal, deriving the origin from the edge's own target.

* fix(skills): pin phase IDs, recovery state, and hold backtrack

Keep live skill IDs on filename stems, stop Phase 14 from skipping to dogfood,
round-trip receipt recovery fields through PipelineState, and refuse 20→18 after a shipcheck hold.

Co-authored-by: Trevin Chow <tmchow@users.noreply.github.com>

* chore(ci): retrigger conversation-resolution status

All review threads on #3723 are resolved. The All conversations resolved
commit status is still the failure posted before those threads closed,
because later fork review events 403'd posting a replacement. This empty
commit fires pull_request_target, which can write the status.

Co-authored-by: Trevin Chow <tmchow@users.noreply.github.com>

---------

Co-authored-by: Trevin Chow <trevin@trevinchow.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Trevin Chow <tmchow@users.noreply.github.com>
2026-09-06 22:27:14 +00:00
..