← back to Cli Printing Press
docs(plans): update pipeline plan with plan-first architecture
cd1cea5a7dea401a5f89d97c5efe1a09a93138d2 · 2026-03-24 07:21:51 -0700 · Matt Van Horn
Files touched
M docs/plans/2026-03-24-feat-autonomous-cli-pipeline-plan.md
Diff
commit cd1cea5a7dea401a5f89d97c5efe1a09a93138d2
Author: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Date: Tue Mar 24 07:21:51 2026 -0700
docs(plans): update pipeline plan with plan-first architecture
---
...2026-03-24-feat-autonomous-cli-pipeline-plan.md | 705 ++++++++++-----------
1 file changed, 332 insertions(+), 373 deletions(-)
diff --git a/docs/plans/2026-03-24-feat-autonomous-cli-pipeline-plan.md b/docs/plans/2026-03-24-feat-autonomous-cli-pipeline-plan.md
index f194242d..23b830bf 100644
--- a/docs/plans/2026-03-24-feat-autonomous-cli-pipeline-plan.md
+++ b/docs/plans/2026-03-24-feat-autonomous-cli-pipeline-plan.md
@@ -1,513 +1,472 @@
---
-title: "Autonomous CLI Pipeline - From API Name to Finished CLI"
+title: "Autonomous CLI Pipeline - Plan-First, Phase-Chained, From API Name to Finished CLI"
type: feat
status: active
date: 2026-03-24
---
-# Autonomous CLI Pipeline - From API Name to Finished CLI
+# Autonomous CLI Pipeline - Plan-First, Phase-Chained
-## Overview
-
-Transform the printing press from a single-pass generator into a multi-phase autonomous pipeline. The user says `printing-press print gmail`. The press discovers the spec, scaffolds, enriches with deep research, reviews, and ships - each phase writing checkpoint state and chaining to the next. Zero human intervention. Overnight quality.
-
-Inspired by OSC nightnight's proven patterns: checkpoint-based resumption, mechanical budget gates, CronCreate session chaining, JSONL event logging.
-
-## Problem Statement
-
-The press currently does one pass: spec in, CLI out, 70% quality. The missing 30% is information that exists in the spec and public docs but requires multiple analysis passes with different lenses to extract. A single context window can't hold spec parsing + deep doc research + dogfood analysis + enrichment application. The solution is phase chaining - the same pattern that lets OSC run for 8 hours overnight.
-
-## Architecture: The Print Pipeline
-
-```
-printing-press print gmail
- |
- [PREFLIGHT] - Go installed? Binary fresh? Disk space?
- |
- [DISCOVER] - Find OpenAPI spec (known-specs, apis-guru, WebSearch)
- |
- [SCAFFOLD] - Generate initial CLI (existing generate command)
- |
- [ENRICH] - Deep-read spec hints + research API docs -> spec overlay
- |
- [REGENERATE]- Re-run generator with enriched spec (SCAFFOLD + overlay)
- |
- [REVIEW] - Static analysis: help output, name quality, compilation, coverage
- |
- [SHIP] - git init, README, goreleaser validate, morning report
- |
- Done. CLI at ./gmail-cli/
-```
+## The Philosophy
-**Key decision: ENRICH modifies the spec, not generated code.** The generator remains the single source of truth for code output. ENRICH produces a YAML overlay that gets merged into the original spec before re-generation. This collapses the original 6-phase plan into 7 tighter phases (PREFLIGHT + DISCOVER + SCAFFOLD + ENRICH + REGENERATE + REVIEW + SHIP) where ENRICH + REGENERATE replace the earlier ENRICH + POLISH split.
+"The moment I have an idea, it's /ce:plan." - @mvanhorn
-## Scope Boundaries
+Traditional dev is 80% coding, 20% planning. This flips it. The thinking happens in the plan. The execution is mechanical. Every phase of the pipeline follows the same discipline: write a plan.md first, execute it with ce:work, then write the next plan. No phase starts work without a plan. No plan ships without execution.
-- No runtime library - templates only
-- No real API testing in REVIEW (no credential management) - static analysis only
-- No GitHub repo creation or release publishing in SHIP - local only
-- No Google Discovery format converter - use apis-guru pre-converted specs
-- No file upload/download generation (separate plan)
-- No batch mode (one API per pipeline invocation)
-- Single Claude Code skill with phase routing (not 7 separate skills)
+The pipeline is not a Go binary that runs 7 functions. It's a chain of plan.md files, each one written by ce:plan with full research agents, each one executed by ce:work with test verification. The Go binary is thin - it manages pipeline state and triggers the next plan. The intelligence lives in the plans.
-## Implementation Units
+This is the same pattern that produced 70 plan files and 263 commits on /last30days. The same pattern that runs OSC nightnight for 8 hours overnight. The same pattern that turned a lunch transcript into a product proposal.
-### Unit 1: Checkpoint Schema and State Machine
+## Overview
-**Goal:** Define the pipeline's backbone - the checkpoint JSON that every phase reads and writes. Model after nightnight's `~/.osc/nightnight-session.json`.
+User says: `printing-press print gmail`
-**Files:**
-- New: `internal/pipeline/checkpoint.go` - checkpoint types, read/write, phase enum
-- New: `internal/pipeline/events.go` - JSONL event logger
+What happens:
-**Approach:**
+```
+Phase 0: PREFLIGHT
+ -> ce:plan writes preflight-plan.md (check environment, find spec)
+ -> ce:work executes it
+ -> checkpoint updated
+
+Phase 1: SCAFFOLD
+ -> ce:plan writes scaffold-plan.md (generate initial CLI from spec)
+ -> ce:work executes it (runs printing-press generate, validates 7 gates)
+ -> checkpoint updated
+
+Phase 2: ENRICH
+ -> ce:plan writes enrich-plan.md (deep-read spec, research API docs, find hints)
+ -> ce:work executes it (produces spec overlay YAML)
+ -> checkpoint updated
+
+Phase 3: REGENERATE
+ -> ce:plan writes regenerate-plan.md (merge overlay, re-generate, re-validate)
+ -> ce:work executes it
+ -> checkpoint updated
+
+Phase 4: REVIEW
+ -> ce:plan writes review-plan.md (dogfood every command, check quality)
+ -> ce:work executes it (produces quality score + issue list)
+ -> checkpoint updated
+
+Phase 5: SHIP
+ -> ce:plan writes ship-plan.md (git init, README, morning report)
+ -> ce:work executes it
+ -> Done.
+```
-Checkpoint schema:
-```go
-type Checkpoint struct {
- APIName string `json:"api_name"`
- StartedAt time.Time `json:"started_at"`
- OutputDir string `json:"output_dir"`
- SpecPath string `json:"spec_path"` // discovered spec file
- OverlayPath string `json:"overlay_path"` // enrichment overlay
- ConventionsPath string `json:"conventions_path"` // conventions cache
- EventsLogPath string `json:"events_log_path"` // JSONL log
- Phases map[string]Phase `json:"phases"`
- Errors []string `json:"errors"`
-}
+Each phase is a full ce:plan -> ce:work cycle. Each plan.md gets the benefit of parallel research agents, codebase analysis, and prior learnings. Each ce:work execution gets fresh context, task tracking, and test verification.
-type Phase struct {
- Status string `json:"status"` // pending, in_progress, completed, failed
- StartedAt time.Time `json:"started_at"`
- Duration string `json:"duration"`
- Retries int `json:"retries"`
-}
-```
+The plan.md IS the checkpoint that survives everything. Context gets lost? Start a new session, point it at the plan, pick up where you left off.
-Checkpoint location: `~/.cache/printing-press/pipelines/<api-name>/checkpoint.json`
-Events log: `~/.cache/printing-press/pipelines/<api-name>/events.jsonl`
-Conventions cache: `~/.cache/printing-press/pipelines/<api-name>/conventions.json`
+## Why Plan-First Per Phase
-Phase order: `preflight -> discover -> scaffold -> enrich -> regenerate -> review -> ship`
+1. **Fresh context per phase.** ENRICH needs to deeply analyze an API's docs. That's a full context window. If it ran in the same session as SCAFFOLD, context would be exhausted. A new ce:plan session starts clean.
-Mechanical gate between phases: phase must be `completed` to advance. Failed after 2 retries = pipeline parks with morning report.
+2. **Research agents per phase.** ce:plan launches parallel research agents - repo analysis, learnings search, external docs. DISCOVER's research is different from ENRICH's research is different from REVIEW's research. Each phase needs its own research pass.
-**Test scenarios:**
-- Checkpoint round-trips through JSON marshal/unmarshal
-- Phase state machine transitions correctly (pending -> in_progress -> completed)
-- Events append to JSONL without corruption
+3. **Human checkpoint between phases.** Each plan.md is reviewable. In autonomous mode, the mechanical gate reviews it. In interactive mode, the human can read the plan before ce:work starts. "Does this enrichment plan look right before I spend 20 minutes executing it?"
-**Verification:** `go test ./internal/pipeline/...`
+4. **Crash recovery is free.** If a session dies mid-ENRICH, the enrich-plan.md is already on disk. Next session reads it and picks up. No special checkpoint serialization needed - the plan IS the state.
----
+5. **Compounding context.** Each plan.md can reference all prior plans. The REVIEW plan can say "In the scaffold plan, we generated 12 resources. In the enrich plan, we added defaults to 3 of them. Now let's verify all 12 look right." Plans compound like your strategy docs compound.
-### Unit 2: PREFLIGHT Phase
+## Architecture
-**Goal:** Validate environment before burning any tokens. Go installed, printing-press binary compiles, output dir clean.
+### The Thin Orchestrator (Go)
-**Files:**
-- New: `internal/pipeline/preflight.go`
+The `printing-press print` command is a thin loop:
-**Approach:**
-1. Check `go version` succeeds
-2. Check printing-press binary builds: `go build -o /tmp/pp-check ./cmd/printing-press`
-3. Check output dir doesn't exist (or `--force` flag)
-4. Check disk space > 500MB free
-5. Write checkpoint with preflight=completed
+```go
+func RunPipeline(apiName string, opts Options) error {
+ state := loadOrCreateState(apiName)
-**Test scenarios:**
-- Preflight passes on healthy system
-- Preflight fails gracefully when Go missing (clear error message)
+ phases := []string{"preflight", "scaffold", "enrich", "regenerate", "review", "ship"}
-**Verification:** Unit tests with mock exec
+ for _, phase := range phases {
+ if state.IsCompleted(phase) {
+ continue // resume mode - skip done phases
+ }
----
+ // Write the plan for this phase
+ planPath := state.PlanPath(phase) // e.g., docs/plans/gmail-pipeline/02-scaffold-plan.md
+ if !fileExists(planPath) {
+ // Generate phase-specific prompt and write it as the plan seed
+ writePlanSeed(state, phase, planPath)
+ }
-### Unit 3: DISCOVER Phase
+ // Mark phase in progress
+ state.Start(phase)
+ state.Save()
-**Goal:** Given an API name, find a usable OpenAPI spec. Check known-specs registry, then apis-guru, then WebSearch.
+ fmt.Fprintf(os.Stderr, "[%s] Plan at %s\n", phase, planPath)
+ fmt.Fprintf(os.Stderr, "[%s] Execute with: /ce:work %s\n", phase, planPath)
-**Files:**
-- New: `internal/pipeline/discover.go`
-- Update: `skills/printing-press/references/known-specs.md` - add apis-guru URL patterns
+ // In autonomous mode: the skill chains ce:plan -> ce:work automatically
+ // In interactive mode: the user runs ce:work manually
+ }
-**Approach:**
+ return nil
+}
+```
-Discovery pipeline (ordered by reliability):
-1. **Known-specs registry** - exact match on API name. Already has 12 verified URLs.
-2. **apis-guru directory** - fetch `https://raw.githubusercontent.com/APIs-guru/openapi-directory/main/APIs/<provider>/` and find the latest version. This covers 2,000+ APIs including all Google services.
-3. **WebSearch** - `"<api-name> openapi spec" site:github.com OR site:swagger.io` with 3 strategies
-4. **Fallback** - prompt the user (in interactive mode) or park (in autonomous mode)
+The Go binary doesn't execute phases. It writes plan seeds (structured prompts with all the context each phase needs) and manages state. The Claude Code skill does the actual ce:plan -> ce:work chaining.
-Spec quality gate: after fetching, validate:
-- Parses as valid OpenAPI (use existing `openapi.IsOpenAPI()` + `openapi.Parse()`)
-- Has at least 3 endpoints
-- Has at least 1 resource
-- Has a base URL
+### The Claude Code Skill (The Real Engine)
-If quality gate fails, try next discovery source.
+The printing-press skill becomes the orchestrator:
-**Conventions cache:** After successful parse, write to conventions cache:
-- Auth type and schemes detected
-- Number of resources/endpoints
-- Pagination patterns found
-- Global params detected
-- Common prefix (if any)
+```
+User: "print me a gmail CLI"
-**Test scenarios:**
-- Discovery finds Petstore from known-specs
-- Discovery finds Gmail from apis-guru
-- Discovery falls back to WebSearch for unknown APIs
-- Quality gate rejects specs with 0 endpoints
+Skill reads pipeline state
+ -> If no state: create it, start at preflight
+ -> If existing state: find next incomplete phase
-**Verification:** `go test ./internal/pipeline/...`, manual test with `gmail` and `stripe`
+For each phase:
+ 1. Run ce:plan with phase-specific prompt
+ - Prompt includes: API name, prior phase outputs, conventions cache
+ - ce:plan research agents analyze the specific needs of THIS phase
+ - ce:plan writes the plan.md
----
+ 2. Run ce:work on the plan.md
+ - ce:work breaks it into tasks, implements, tests, checks off criteria
+ - On completion: update pipeline state
-### Unit 4: SCAFFOLD Phase
+ 3. Chain to next phase
+ - CronCreate schedules the skill to resume in 30 seconds
+ - Fresh session, fresh context, next phase
+```
-**Goal:** Run the existing `printing-press generate` command on the discovered spec. Validate with 7 quality gates.
+This is exactly OSC nightnight's pattern: implement -> checkpoint -> chain -> fresh session -> implement.
-**Files:**
-- New: `internal/pipeline/scaffold.go`
-- Existing: `internal/generator/generator.go`, `internal/generator/validate.go`
+### Plan Directory Structure
-**Approach:**
-1. Read spec from checkpoint's `spec_path`
-2. Parse with existing openapi/spec parser
-3. Generate with existing generator
-4. Run 7 quality gates
-5. If gates fail: retry once with relaxed settings (skip lint gate), then park
-6. Update checkpoint with scaffold=completed
+```
+docs/plans/gmail-pipeline/
+ 00-preflight-plan.md # Environment checks, spec discovery
+ 01-scaffold-plan.md # Initial CLI generation
+ 02-enrich-plan.md # Deep spec analysis, overlay creation
+ 03-regenerate-plan.md # Merge overlay, re-generate
+ 04-review-plan.md # Quality analysis, dogfooding
+ 05-ship-plan.md # Finalize, morning report
+ state.json # Pipeline state (which phases are done)
+ conventions.json # Cached spec analysis (reused across phases)
+ overlay.yaml # Spec overlay from ENRICH (consumed by REGENERATE)
+ report.md # Final morning report
+```
-This is a thin wrapper around the existing `generate` + `validate` pipeline.
+Each plan.md follows the standard ce:plan format with frontmatter, acceptance criteria, implementation units. They're real plans, not stubs.
+
+### Phase-Specific Plan Seeds
+
+The Go binary writes "plan seeds" - structured prompts that ce:plan uses to write the full plan. Each seed contains:
+
+**Preflight seed:**
+- Check Go version, check press binary, check disk space
+- Find OpenAPI spec: check known-specs registry, then apis-guru (`APIs-guru/openapi-directory/APIs/<provider>/`), then WebSearch
+- Validate spec quality (parses, has 3+ endpoints, has base URL)
+- Write conventions cache (auth type, pagination patterns, resource count)
+- Acceptance: spec file downloaded, conventions cached, environment validated
+
+**Scaffold seed:**
+- Spec path from preflight
+- Run `printing-press generate --spec <path> --output <dir>`
+- Validate 7 quality gates pass
+- Acceptance: CLI compiles, all gates pass, `<cli> --help` works
+
+**Enrich seed:**
+- Read original spec from scaffold
+- Read conventions cache from preflight
+- Deep-read every parameter description for default value hints (e.g., "The special value `me` can be used")
+- Scan for `mediaUpload`, `x-google-*` extensions, multipart content types
+- Scan response schemas for sync token patterns (`historyId`, `syncToken`)
+- Scan for batch endpoint patterns (`:batchGet`, `:batchCreate`)
+- Check for endpoints with empty descriptions that could be enriched
+- WebSearch for `<api-name> API best practices CLI` to find community patterns
+- Write overlay.yaml with all discovered enrichments
+- Acceptance: overlay file exists, at least 1 enrichment found
+
+**Regenerate seed:**
+- Merge overlay.yaml with original spec
+- Re-run `printing-press generate` with merged spec
+- Re-validate 7 quality gates
+- If gates fail: fall back to original spec, log what broke
+- Acceptance: CLI compiles with enrichments, no regressions
+
+**Review seed:**
+- Build the CLI binary
+- Run `<cli> --help` and `<cli> <resource> --help` for every resource
+- Check: no command name > 40 chars, no empty descriptions on resources
+- Check: every GET endpoint has at least 1 query param flag
+- Check: no duplicate command names
+- Check: `<cli> doctor` exits 0
+- Check: binary size < 50MB
+- Produce quality score (0-100) and issue list
+- Acceptance: score > 70, all critical checks pass
+
+**Ship seed:**
+- Run `git init` in output directory
+- Create initial commit
+- Validate goreleaser config if present
+- Write morning report with: time per phase, enrichments applied, quality score, next steps for human
+- Acceptance: git repo initialized, morning report written
-**Test scenarios:**
-- SCAFFOLD succeeds for Petstore, Gmail, Discord, Stytch specs
-- SCAFFOLD retries on quality gate failure
-- SCAFFOLD parks after 2 failures
+## Scope Boundaries
-**Verification:** `go test ./...`, regenerate all 4 test specs
+- No real API testing (no credential management in autonomous mode)
+- No GitHub repo creation or release publishing
+- No Google Discovery format converter (use apis-guru)
+- No file upload/download generation
+- No batch mode (one API per invocation)
+- No Codex delegation for plan writing (ce:plan runs on Claude)
----
+## Implementation Units
-### Unit 5: ENRICH Phase - The Intelligence Layer
+### Unit 1: Pipeline State Manager (Go)
-**Goal:** Deep-read the original spec for hints the parser missed. Research the API's public docs. Produce a spec overlay that improves the generated CLI.
+**Goal:** The thin Go package that manages pipeline state and writes plan seeds.
**Files:**
-- New: `internal/pipeline/enrich.go`
-- New: `internal/pipeline/overlay.go` - spec overlay types and merge logic
+- New: `internal/pipeline/state.go` - state types, read/write, phase tracking
+- New: `internal/pipeline/seeds.go` - plan seed templates per phase
+- New: `internal/pipeline/state_test.go`
**Approach:**
-The overlay format mirrors `spec.APISpec` but every field is optional. Non-nil fields override the original spec when merged.
-
+State is minimal JSON:
```go
-type SpecOverlay struct {
- Description *string `yaml:"description,omitempty"`
- Resources map[string]ResourceOverlay `yaml:"resources,omitempty"`
-}
-
-type ResourceOverlay struct {
- Description *string `yaml:"description,omitempty"`
- Endpoints map[string]EndpointOverlay `yaml:"endpoints,omitempty"`
-}
-
-type EndpointOverlay struct {
- Description *string `yaml:"description,omitempty"`
- Params []ParamPatch `yaml:"params,omitempty"`
+type PipelineState struct {
+ APIName string `json:"api_name"`
+ OutputDir string `json:"output_dir"`
+ StartedAt time.Time `json:"started_at"`
+ Phases map[string]PhaseState `json:"phases"`
+ SpecPath string `json:"spec_path,omitempty"`
}
-type ParamPatch struct {
- Name string `yaml:"name"`
- Default *string `yaml:"default,omitempty"` // e.g., "me" for userId
+type PhaseState struct {
+ Status string `json:"status"` // pending, planned, executing, completed, failed
+ PlanPath string `json:"plan_path,omitempty"`
}
```
-Enrichment strategies (each runs independently, results merged):
+Note the extra status: `planned` means the plan.md exists but hasn't been executed yet. This is the human checkpoint - you can review the plan before ce:work runs.
-1. **Description hints** - scan param descriptions for default value hints. Gmail's userId says "The special value `me` can be used" - extract `me` as default.
-2. **mediaUpload detection** - scan for `x-]google-*` extensions or multipart content types. Flag endpoints that support file upload (future: generate upload commands).
-3. **Sync token patterns** - scan response schemas for `historyId`, `syncToken`, `nextSyncToken` fields. Flag resources that support incremental sync.
-4. **Batch endpoint detection** - scan for paths ending in `:batchGet`, `:batchCreate`, or `batch*` with array request bodies.
-5. **Better descriptions** - for endpoints with empty or generic descriptions, check if the operationId or path provides a clearer name.
-6. **Endpoint grouping hints** - for flat resources with many endpoints (like settings), detect naming patterns that suggest sub-groups (e.g., `cse-*`, `send-as-*`).
+Plan seeds are Go templates that produce markdown. Each seed is a structured prompt that ce:plan will expand into a full plan with research.
-Time budget: 15 minutes max. Each strategy gets 2 minutes. Partial results are written if time runs out.
-
-**Test scenarios:**
-- Gmail enrichment detects `me` default for userId
-- Gmail enrichment detects mediaUpload on messages/send
-- Overlay merges correctly with original spec (non-nil fields override)
-- Overlay merge preserves unmodified fields
-
-**Verification:** `go test ./internal/pipeline/...`, manual test with Gmail spec
+**Verification:** `go test ./internal/pipeline/...`
---
-### Unit 6: REGENERATE Phase
+### Unit 2: `print` CLI Command
-**Goal:** Merge the spec overlay with the original spec and re-run the generator.
+**Goal:** Add `printing-press print <api-name>` command that creates the pipeline directory and writes plan seeds.
**Files:**
-- New: `internal/pipeline/regenerate.go`
-- Update: `internal/spec/spec.go` - add `MergeOverlay()` method
+- Update: `internal/cli/root.go` - add print command
+- New: `internal/pipeline/pipeline.go` - orchestration logic
**Approach:**
-1. Load original spec from checkpoint
-2. Load overlay from checkpoint
-3. Merge: overlay fields replace original fields where non-nil
-4. Re-run generator with merged spec (overwrite existing output)
-5. Re-run 7 quality gates
-6. If gates fail: fall back to original spec (enrichment broke something), log the error
-**Test scenarios:**
-- Regenerate with overlay produces different output than without
-- Regenerate fallback works when overlay breaks compilation
-- Quality gates still pass after regeneration
+The print command:
+```
+printing-press print gmail [--output ./gmail-cli] [--force] [--resume]
+```
+
+It does NOT execute phases. It:
+1. Creates `docs/plans/<api-name>-pipeline/` directory
+2. Writes `state.json` with all phases pending
+3. Writes plan seeds for each phase as markdown files
+4. Prints instructions: "Pipeline ready. Run /ce:work docs/plans/gmail-pipeline/00-preflight-plan.md to start"
+
+In skill mode (autonomous), the skill takes over from here and chains ce:plan -> ce:work for each phase.
-**Verification:** `go test ./...`
+**Verification:** `go test ./...`, `printing-press print petstore` creates pipeline directory with plan seeds
---
-### Unit 7: REVIEW Phase - Static Quality Analysis
+### Unit 3: Claude Code Skill Update
-**Goal:** Automated quality assessment of the generated CLI. No API calls - static analysis only.
+**Goal:** Update the printing-press skill to support the autonomous pipeline with phase chaining.
**Files:**
-- New: `internal/pipeline/review.go`
+- Update: `skills/printing-press/SKILL.md`
**Approach:**
-Review checks (binary pass/fail):
-1. **Help completeness** - run `<cli> --help` and every `<cli> <resource> --help`. Verify exit code 0, non-empty output.
-2. **Name quality** - no command name > 40 chars, no raw operationId passthrough (contains dots or underscores), no duplicate command names.
-3. **Param coverage** - every GET endpoint has at least 1 non-positional param (if the original spec had query params). Flag endpoints where all params were filtered.
-4. **Description quality** - no empty descriptions on top-level resources. No descriptions that are just the endpoint name repeated.
-5. **Compilation clean** - `go vet` passes with zero warnings.
-6. **Binary size** - warn if > 50MB (something is wrong).
-7. **Doctor works** - `<cli> doctor` exits 0.
+New workflow in the skill:
-Review produces a quality score (0-100) and a list of issues. Score > 70 = PASS. Score < 70 = log issues in morning report but still PASS (don't block shipping over cosmetics).
+```
+Workflow: Autonomous Pipeline
+
+When user says "print <api-name>":
+
+1. Run `printing-press print <api-name>` to create pipeline directory
+2. Read state.json to find next phase
+3. For the next incomplete phase:
+ a. If plan.md doesn't exist yet:
+ - Read the plan seed
+ - Run ce:plan with the seed as input (this writes the full plan)
+ b. If plan.md exists but phase isn't completed:
+ - Run ce:work on the plan.md
+ c. After ce:work completes:
+ - Update state.json (mark phase completed)
+ - CronCreate to chain back to this skill in 30 seconds
+ - Fresh session picks up at step 2 with next phase
+
+Budget gate: after each phase, check total elapsed time. If > 3 hours, write
+partial morning report and stop. This prevents runaway overnight sessions.
+```
-**Test scenarios:**
-- Review passes for a well-generated CLI
-- Review catches empty descriptions
-- Review catches overly long command names
+The skill is the brain. The Go binary is the skeleton. The plans are the memory.
-**Verification:** `go test ./internal/pipeline/...`
+**Verification:** Manual test in Claude Code: "print me a petstore CLI"
---
-### Unit 8: SHIP Phase
+### Unit 4: Known-Specs Registry + apis-guru Integration
-**Goal:** Finalize the generated CLI for human consumption.
+**Goal:** Make PREFLIGHT's spec discovery actually work for common APIs.
**Files:**
-- New: `internal/pipeline/ship.go`
+- Update: `skills/printing-press/references/known-specs.md` - add apis-guru patterns
+- New: `internal/pipeline/discover.go` - spec discovery logic (used by plan seed generation)
**Approach:**
-1. Run `git init` in output directory
-2. Create initial commit: "Initial CLI generated by printing-press"
-3. Validate goreleaser config: `goreleaser check` (if installed) or skip
-4. Write morning report to `~/.cache/printing-press/pipelines/<api-name>/report.md`
-5. Update checkpoint with ship=completed, total duration
-6. Print summary to stderr
-
-Morning report includes:
-- API name and spec source
-- Resources and endpoint count
-- Quality score from REVIEW
-- Enrichments applied
-- Issues found
-- Time per phase
-- Next steps for the human (configure auth, test against real API, publish)
-
-**Test scenarios:**
-- SHIP creates git repo with initial commit
-- Morning report contains all required sections
-- Pipeline completion updates checkpoint correctly
-**Verification:** `go test ./internal/pipeline/...`
+Expand known-specs.md with apis-guru URL patterns:
+```
+## apis-guru patterns
+For any API not in the registry, try:
+https://raw.githubusercontent.com/APIs-guru/openapi-directory/main/APIs/{provider}/{version}/openapi.yaml
+
+Common providers:
+- googleapis.com/gmail/v1
+- googleapis.com/calendar/v3
+- googleapis.com/drive/v3
+- stripe.com/2023-10-16
+- twilio.com/2010-04-01
+```
+
+The discover.go file provides a `DiscoverSpec(apiName string) (string, error)` function that:
+1. Checks known-specs registry (exact match)
+2. Tries apis-guru URL pattern
+3. Returns the URL or path to the spec
+
+This is used by the preflight plan seed to tell ce:plan where to look.
+
+**Verification:** `go test ./internal/pipeline/...` with test cases for gmail, stripe, petstore
---
-### Unit 9: Pipeline Orchestrator and CLI Command
+### Unit 5: Spec Overlay Types and Merge
-**Goal:** Wire all phases together. Add `printing-press print <api-name>` command. Handle chaining, resume, and error recovery.
+**Goal:** Define the overlay format that ENRICH produces and REGENERATE consumes.
**Files:**
-- New: `internal/pipeline/pipeline.go` - orchestrator
-- Update: `internal/cli/root.go` - add `print` command
+- New: `internal/pipeline/overlay.go` - overlay types
+- Update: `internal/spec/spec.go` - add MergeOverlay method
**Approach:**
-The `print` command:
-```
-printing-press print gmail [--output ./gmail-cli] [--force] [--resume] [--phase enrich]
-```
-
-Flags:
-- `--output` - output directory (default: `./<api-name>-cli`)
-- `--force` - overwrite existing output
-- `--resume` - resume from checkpoint
-- `--phase` - run only a specific phase (for debugging)
-
-Orchestrator loop:
+The overlay is a YAML file that mirrors APISpec but every field is optional:
```go
-func RunPipeline(apiName string, opts Options) error {
- checkpoint := loadOrCreateCheckpoint(apiName, opts)
-
- phases := []struct {
- name string
- fn func(*Checkpoint) error
- }{
- {"preflight", runPreflight},
- {"discover", runDiscover},
- {"scaffold", runScaffold},
- {"enrich", runEnrich},
- {"regenerate", runRegenerate},
- {"review", runReview},
- {"ship", runShip},
- }
-
- for _, phase := range phases {
- if checkpoint.Phases[phase.name].Status == "completed" {
- continue // already done (resume mode)
- }
-
- logEvent(checkpoint, "phase_start", phase.name)
- checkpoint.Phases[phase.name] = Phase{Status: "in_progress", StartedAt: time.Now()}
- saveCheckpoint(checkpoint)
-
- var err error
- for attempt := 0; attempt < 3; attempt++ {
- err = phase.fn(checkpoint)
- if err == nil {
- break
- }
- checkpoint.Phases[phase.name] = Phase{Status: "failed", Retries: attempt + 1}
- logEvent(checkpoint, "phase_retry", phase.name, err.Error())
- }
+type SpecOverlay struct {
+ Resources map[string]ResourceOverlay `yaml:"resources,omitempty"`
+}
- if err != nil {
- checkpoint.Errors = append(checkpoint.Errors, fmt.Sprintf("%s: %v", phase.name, err))
- saveCheckpoint(checkpoint)
- writeMorningReport(checkpoint) // partial report
- return fmt.Errorf("pipeline failed at %s: %w", phase.name, err)
- }
+type ResourceOverlay struct {
+ Endpoints map[string]EndpointOverlay `yaml:"endpoints,omitempty"`
+}
- checkpoint.Phases[phase.name] = Phase{Status: "completed", Duration: time.Since(...).String()}
- saveCheckpoint(checkpoint)
- logEvent(checkpoint, "phase_completed", phase.name)
- }
+type EndpointOverlay struct {
+ Description *string `yaml:"description,omitempty"`
+ Params []ParamPatch `yaml:"params,omitempty"`
+}
- writeMorningReport(checkpoint)
- return nil
+type ParamPatch struct {
+ Name string `yaml:"name"`
+ Default *string `yaml:"default,omitempty"`
}
```
-**Test scenarios:**
-- Full pipeline completes for Petstore (simplest spec)
-- Resume skips completed phases
-- Pipeline parks on repeated failure with morning report
-- `--phase` runs only the specified phase
+`MergeOverlay` on APISpec applies the overlay: non-nil fields override originals.
-**Verification:** `go test ./...`, manual end-to-end: `printing-press print petstore`
+**Verification:** `go test ./internal/pipeline/...`, `go test ./internal/spec/...`
---
-### Unit 10: Claude Code Skill - The `print` Skill
+### Unit 6: End-to-End Test
-**Goal:** Update the printing-press Claude Code skill to support the autonomous pipeline. User says "print me a gmail CLI" or `/printing-press gmail` and it runs the full pipeline.
+**Goal:** Run the full pipeline on Petstore to prove it works.
-**Files:**
-- Update: `skills/printing-press/SKILL.md`
+**Files:** No new files - verification only.
**Approach:**
+1. `printing-press print petstore`
+2. Verify pipeline directory created with plan seeds
+3. Manually run ce:work on each plan seed in order
+4. Verify final CLI compiles and works
+5. Verify morning report generated
-Add a new workflow to the existing skill:
-
-**Workflow 0 (updated): Autonomous Pipeline**
-1. Parse API name from user's message
-2. Run `printing-press print <api-name> --output ./<api-name>-cli`
-3. Monitor output for phase completion messages
-4. On completion: present morning report, show example commands
-5. On failure: show error, offer to resume or debug specific phase
-
-For overnight/autonomous mode (when invoked by nightnight-style chaining):
-- Read checkpoint, determine current phase
-- Execute next phase
-- If more phases remain: CronCreate to chain back in 30 seconds
-- If pipeline complete: write morning report, stop chaining
-
-**Test scenarios:**
-- User says "print me a stripe CLI" - full pipeline runs
-- User says "resume gmail" - picks up from checkpoint
-
-**Verification:** Manual test in Claude Code session
+**Verification:** Petstore CLI works, all plan.md files exist, morning report is readable
## Dependencies
```
-Unit 1 (Checkpoint) - foundation, everything depends on this
-Unit 2 (Preflight) - depends on Unit 1
-Unit 3 (Discover) - depends on Unit 1
-Unit 4 (Scaffold) - depends on Unit 1
-Unit 5 (Enrich) - depends on Unit 1
-Unit 6 (Regenerate) - depends on Unit 5
-Unit 7 (Review) - depends on Unit 1
-Unit 8 (Ship) - depends on Unit 1
-Unit 9 (Orchestrator) - depends on Units 1-8
-Unit 10 (Skill) - depends on Unit 9
+Unit 1 (State) - foundation
+Unit 2 (print command) - depends on Unit 1
+Unit 3 (Skill) - depends on Unit 2
+Unit 4 (Discovery) - independent
+Unit 5 (Overlay) - independent
+Unit 6 (E2E test) - depends on all
```
-Units 2-5, 7-8 can be built in parallel after Unit 1.
-Unit 6 needs Unit 5's overlay types.
-Unit 9 wires everything together.
-Unit 10 is the skill layer on top.
+Units 1, 4, 5 can be built in parallel.
+Unit 2 wires Unit 1 into the CLI.
+Unit 3 is the skill layer.
+Unit 6 is verification.
## What "Done" Looks Like
```bash
-# One command, one API name, finished CLI
+# Two words. That's the input.
printing-press print gmail
-# Output:
-# [preflight] Go 1.23 OK, disk OK
-# [discover] Found Gmail spec via apis-guru (79 endpoints, OAuth2)
-# [scaffold] Generated gmail-cli (7/7 gates passed)
-# [enrich] Applied 12 enrichments (userId default=me, 3 upload hints, 8 better descriptions)
-# [regenerate] Re-generated with enrichments (7/7 gates passed)
-# [review] Quality score: 87/100 (2 minor issues)
-# [ship] Initialized git repo, wrote morning report
-#
-# gmail-cli ready at ./gmail-cli/
-# Resources: messages, labels, drafts, threads, history, settings, profile
-# Auth: OAuth2 (run `gmail-cli auth login` to authenticate)
-# Total time: 4m 23s
+# Pipeline creates:
+# docs/plans/gmail-pipeline/
+# 00-preflight-plan.md <- ce:plan writes this with full research
+# 01-scaffold-plan.md <- ce:plan writes this after preflight completes
+# 02-enrich-plan.md <- ce:plan deep-analyzes the spec and API docs
+# 03-regenerate-plan.md <- ce:plan plans the overlay merge
+# 04-review-plan.md <- ce:plan plans the quality review
+# 05-ship-plan.md <- ce:plan plans the finalization
+# state.json <- tracks which phases are done
+# conventions.json <- cached spec analysis
+# overlay.yaml <- enrichments from phase 2
+# report.md <- morning report
+
+# Each plan is a real plan. Research agents. Acceptance criteria. Implementation units.
+# Each plan gets executed by ce:work with task tracking and test verification.
+# Each phase chains to the next via CronCreate. Fresh context every time.
+# Output:
cd gmail-cli && go build -o ./gmail ./cmd/gmail-cli
./gmail auth login --client-id $GOOGLE_CLIENT_ID
-./gmail messages list me --limit 5
-./gmail doctor
+./gmail messages list me --limit 5 # 'me' is the default, detected from spec hints
+./gmail doctor # colored output, all green
```
-That's not a scaffold. That's a finished CLI. From two words.
+That's not a scaffold. That's a finished CLI. From two words. Built by 6 plans, each one meticulous, each one researched, each one executed and verified. The same workflow that produces 70 plan files and 263 commits.
-## Sources & References
+Plan, execute, plan, execute. All the way down.
-### Internal
-- OSC nightnight chaining pattern: `~/.claude/skills/osc-nightnight/SKILL.md` - checkpoint JSON, CronCreate chaining, mechanical budget gates, JSONL events
-- OSC work execution: `~/.claude/skills/osc-work/SKILL.md` - phased CI execution, conventions cache, post-submission monitoring
-- OSC plan discovery: `~/.claude/skills/osc-plan/SKILL.md` - 7-layer discovery pipeline, per-issue scoring
-- Press generator: `internal/generator/generator.go` - 14 templates, 7 quality gates
-- Press parser: `internal/openapi/parser.go` - 1,900 lines, extracts auth/resources/params/pagination
-- Press spec types: `internal/spec/spec.go` - APISpec struct, validation
-- Known specs registry: `skills/printing-press/references/known-specs.md` - 12 verified URLs
+## Sources
-### External
-- apis-guru OpenAPI directory: `https://github.com/APIs-guru/openapi-directory` - 2,000+ pre-converted specs
-- Google Discovery -> OpenAPI conversions at `APIs-guru/openapi-directory/APIs/googleapis.com/`
+- Matt Van Horn, "Every Claude Code Hack I Know (March 2026)" - the plan-first philosophy
+- OSC nightnight: `~/.claude/skills/osc-nightnight/SKILL.md` - session chaining, budget gates, CronCreate
+- OSC work: `~/.claude/skills/osc-work/SKILL.md` - phased execution, conventions cache
+- Compound Engineering ce:plan - parallel research agents, structured plans
+- Press generator: `internal/generator/generator.go` - 14 templates, 7 quality gates
+- Press parser: `internal/openapi/parser.go` - spec extraction
+- apis-guru: `github.com/APIs-guru/openapi-directory` - 2,000+ pre-converted specs
← 6a76cb26 feat(cli): add 'printing-press print' command with plan-per-
·
back to Cli Printing Press
·
feat(skill): add autonomous pipeline workflow with nightnigh eab64edd →