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

8.0 KiB

Glossary

Operational naming and disambiguation conventions for this repo, plus the implementation-level names — packages, subcommands, on-disk files — that CONCEPTS.md deliberately omits to stay code-free.

For what a domain noun means — the Printing Press, printed CLI, spec, brief, manuscript, library, verify, dogfood, scorecard, emboss, polish, retro, creator, and the rest — see CONCEPTS.md at the repo root. This file covers two things CONCEPTS.md does not: (1) how to refer to overloaded terms, and (2) the concrete files, packages, and subcommands that back those concepts.

Naming conventions

Use the canonical term in your own responses so intent stays unambiguous. If the user's phrasing is ambiguous and the distinction affects what action to take, ask before acting.

In skills and user-facing output (GitHub issues, retro documents, confirmation prompts), use "the Printing Press" as the system name — never "the machine." Skills run as a plugin without AGENTS.md loaded, so readers will not have the inline glossary stub. "The machine" is fine in AGENTS.md, code comments, and developer conversation within this repo.

Subsystem names are fine alongside the Printing Press name. When skills produce diagnostic output (retro findings, issue tables, work units), use component names — generator, scorer, skills, binary — to tell developers where to fix something. "Fix the Printing Press" is useless as an action item; "fix the scorer — it penalizes cookie auth" is actionable.

Default disambiguation conventions

These defaults resolve overloaded words; follow the cross-reference for the full concept.

  • "library" → local library (~/printing-press/library/<api-slug>/). The public library is always called out explicitly: "public library" or "public library repo." (CONCEPTS: local library, public library.)
  • "publish" → prefer "the publish step" (the pipeline's publish phase) or "publish to the public library" (the /printing-press-publish skill workflow) when context is not already established. (CONCEPTS: publish, under Flagged ambiguities.)
  • "manifest" → tools-manifest.json (the MCP tool catalog). The other manifests (manifest.json for plugin metadata, .printing-press.json for provenance) are always called by full name. (See Implementation reference.)
  • "catalog" → qualify the noun. Use "public library catalog" for the category-organized index of finished CLIs, and "tool catalog" for MCP/tool manifests.
  • "the CLI" → a printed CLI, not the generator binary. Say "cli-printing-press binary" or "generator binary" for the latter. (CONCEPTS: printed CLI; below: the cli-printing-press binary.)

On-disk locations for the artifact concepts — local library, manuscripts, runstate — live in ARTIFACTS.md, not here.

Implementation reference

Concrete names that back the concepts — kept here, out of CONCEPTS.md, because they are file paths, package names, and subcommands that move as the code moves.

Many concepts are also cli-printing-press subcommands (generate, verify, dogfood, scorecard, emboss, browser-sniff, crowd-sniff, device-sniff / bluetooth-sniff, …) or skill workflows (polish, reprint, retro); their meaning is in CONCEPTS.md. The table below lists names that are purely tooling — packages, conventions, diagnostic subcommands, and on-disk files with no standalone domain meaning.

Term What it is
the cli-printing-press binary The Go binary built from cmd/cli-printing-press/. Commands: generate, verify, emboss, scorecard, publish, etc. Always say "cli-printing-press binary" or "generator binary" — never just "the CLI."
ble-probe The BLE device-sniff probe surface (scan, inspect, read, subscribe, capture write evidence) packaged as a standalone binary built from cmd/ble-probe/, for machines without the full Printing Press checkout. Same surface as cli-printing-press device-sniff ble; built via scripts/build-ble-probe.sh.
cliutil Generator-owned Go package emitted into every printed CLI at internal/cliutil/. Shared helpers for agent-authored novel code: cliutil.FanoutRun (aggregation commands), cliutil.CleanText (text normalization), cliutil.IsVerifyEnv() (the side-effect short-circuit). Generator-reserved namespace — do not hand-author here or shadow its exports.
cobratree Generator-owned package at internal/mcp/cobratree/. The MCP server walks the printed CLI's Cobra tree at startup and registers shell-out tools for user-facing commands that lack a typed endpoint tool. Classification rules and the framework skip list live in cobratree/classify.go.tmpl. Generator-reserved namespace.
canonicalargs Subpackage at internal/canonicalargs/ exporting Lookup(name) (string, bool) for cross-domain positional placeholders (since, until, tag, vertical). Domain-specific names belong in the spec author's Param.Default, not here — "never change the machine for one CLI's edge case."
side-effect command convention Two-part rule for hand-written novel commands with visible actions: (1) print by default, require explicit opt-in (--launch, --send, --play) to act; (2) short-circuit when cliutil.IsVerifyEnv() is true (the verifier sets PRINTING_PRESS_VERIFY=1 in every mock-mode subprocess). Documented in skills/printing-press/phases/11-build-the-goat.md.
machine-owned freshness Opt-in freshness contract for store-backed printed CLIs using cache.enabled. In --data-source auto, covered paths may run a bounded pre-read refresh; --data-source local never refreshes, --data-source live must not mutate the store, and env opt-out only disables the freshness hook. Current-cache freshness, not full historical backfill.
mcp spec surface Fields on the spec's mcp: block: transport: [stdio, http], intents:, orchestration: code/endpoint-mirror, endpoint_tools: hidden. Empty mcp: keeps endpoint-mirror emission for small APIs and auto-compiles both transports at or under the remote-transport threshold; larger APIs auto-apply the code-orchestration pattern unless opted out.
mcp-sync Binary subcommand (cli-printing-press mcp-sync <cli-dir>) migrating generated MCP surfaces from the old static novel-feature list to the runtime Cobra-tree mirror; rewrites generated MCP files, regenerates tools-manifest.json, and refuses a hand-edited internal/mcp/tools.go without --force.
regen-merge Binary subcommand (cli-printing-press regen-merge <cli-dir> --fresh <fresh-dir>) that AST-classifies each Go file in a published CLI against a fresh tree, applies safe templated overwrites, restores lost AddCommand registrations, and merges go.mod while preserving the monorepo module path. Lives in internal/pipeline/regenmerge/.
auth doctor Binary subcommand (cli-printing-press auth doctor) scanning every installed CLI's tools-manifest.json and reporting env-var status (ok/suspicious/not_set/no_auth/unknown) with redacted fingerprints. Diagnostic only; never gates or probes the network. Lives in internal/authdoctor/.
mcp-audit Binary subcommand (cli-printing-press mcp-audit) walking every library CLI and reporting transport, tool-design, and per-CLI MCP recommendations. Diagnostic only; exit 0 regardless of findings. Supports --json.
tools-manifest.json MCP tool catalog at a printed CLI's root — per-tool name, description, parameters, auth metadata. "The manifest" without qualifier means this file. Backs the MCP surface concept (CONCEPTS.md).
manifest.json Claude plugin manifest at a printed CLI's root — display_name, description, homepage, version, and other plugin-host fields read when installing the CLI as a plugin.
.printing-press.json Provenance manifest at a printed CLI's root — spec URL, checksum, run id, printing-press version, timestamp; api_name is the canonical API identity, cli_name the executable name. Backs the provenance concept (CONCEPTS.md).