* 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>
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-publishskill workflow) when context is not already established. (CONCEPTS: publish, under Flagged ambiguities.) - "manifest" →
tools-manifest.json(the MCP tool catalog). The other manifests (manifest.jsonfor plugin metadata,.printing-press.jsonfor 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). |