A provider-neutral TypeScript CLI and portable Agent Skills package for planning, validating, building, and documenting engineering programs.
# 1. One-step setup: adds the devDependency and installs the workflow skills
# (defaults to all targets: cursor, claude, openclaw, codex, gemini;
# narrow with --targets). Commit the generated files so every dev gets
# the workflows on git pull.
npx @wildorder/program-pipeline setup
# 2. In your agent, run the guided setup
# /init-project/init-project interviews you for the project details, runs the deterministic
init scaffolding under the hood, and finishes by pointing you at
/plan-program to plan your first program. From there the flow is:
plan → author workstreams → validate → review → build → update as-built.
Published on the public npm registry as
@wildorder/program-pipeline —
no tokens, private registry configuration, or repository credentials required:
npm install --save-dev @wildorder/program-pipelineRun the local executable with npx:
npx program-pipeline --helpOne-step onboarding for a project: adds @wildorder/program-pipeline as a
devDependency (skipped with a warning when no package.json exists) and then
runs the skills installer. Accepts the same --targets and --force options
as install.
The devDependency is added with the project's own package manager, detected
from the packageManager field in package.json and then from the lockfile
(pnpm-lock.yaml, yarn.lock, bun.lockb/bun.lock, package-lock.json),
walking up from --cwd so workspace packages resolve to the repo root's
manager. Falls back to npm; override detection with --pm <npm|pnpm|yarn|bun>.
At a pnpm workspace root the dependency is added with pnpm add -D -w.
Re-running setup is also the update path: it bumps the dependency to the
latest published version and refreshes all unmodified package-generated
skills to match, leaving hand-edited skills untouched (reported as
conflicts). Commit the resulting diff. Teams pinned to an older version
should instead use npm update plus npm exec program-pipeline -- install.
npx @wildorder/program-pipeline setup
npx @wildorder/program-pipeline setup --targets claude
npx @wildorder/program-pipeline setup --pm pnpmCreate the standard program-pipeline structure in a new project, or adopt an existing one. Existing files are never overwritten.
npm exec program-pipeline -- init --cwd .
npm exec program-pipeline -- init --cwd . --name "Acme Dashboard" --stack "TypeScript/Node" --description "Operations dashboards for growing teams."All identity flags are optional: --name and --description default to the
package.json values, and --stack defaults to a summary detected from the
repository (package manifests, tsconfig, pyproject, go.mod, Cargo.toml). The
dependency table in AGENTS.md is prefilled from package.json.
Brownfield behavior: when AGENTS.md already exists, init merges rather
than skips — it adds or refreshes only the marked BEGIN/END UNIVERSAL
directives block and leaves every other line untouched. Existing markdown
documentation (root-level *.md and docs/**) is recorded as contextDocs
in pipeline.config.json, which the planning and validation workflows read.
The universal directives block is resolved in this order: an explicit
--directives <path> override, then
~/.program-pipeline/universal-directives.md, then the directives template
packaged with this package.
Install all packaged workflow skills for one or more supported agents. The
default target set is cursor,claude,openclaw,codex,gemini.
npm exec program-pipeline -- install --cwd .
npm exec program-pipeline -- install --cwd . --targets "cursor,claude"Skills are installed at:
- Cursor:
.cursor/skills/<skill-name>/SKILL.md - Claude Code:
.claude/skills/<skill-name>/SKILL.md - OpenClaw:
skills/<skill-name>/SKILL.md - Codex:
.agents/skills/<skill-name>/SKILL.md - Gemini CLI:
.gemini/skills/<skill-name>/SKILL.md
Note that .agents/skills is the cross-tool shared directory — some other
agents (Cursor among them) also read it, so targeting codex alongside
cursor can surface the same skill twice in tools that scan both locations.
Before writing, the installer scans matching project and user-level command and
skill directories for every targeted agent. Alternate definitions
produce detailed warnings but remain untouched. A user-authored or edited file
at an installation destination is a blocking conflict: the entire installation
aborts before writing anything. Identical skills are skipped and unmodified
package-generated skills update safely. Use --force only when you explicitly
want packaged content to replace destination conflicts.
Execute a program's workstreams in dependency order with the configured agent.
The runner verifies every workstream itself by running the verify commands
from pipeline.config.json, writes workstream status back to the manifest
(in_progress, complete, failed), commits each verified workstream,
resumes by skipping workstreams already marked complete, and appends
structured JSON events to
build-logs/{program-id}-build-{timestamp}.jsonl.
npm exec program-pipeline -- build phase-1 --cwd . --dry-run
npm exec program-pipeline -- build phase-1 --cwd . --yes
npm exec program-pipeline -- build phase-1 --cwd . --yes --start-from WS-03
npm exec program-pipeline -- build phase-1 --cwd . --yes --no-commitConfigure the runner in pipeline.config.json:
{
"agent": { "command": "claude", "args": ["-p", "--model", "sonnet"], "promptMode": "stdin" },
"authorAgent": { "command": "claude", "args": ["-p", "--model", "opus"], "promptMode": "stdin" },
"validatorAgent": { "command": "codex", "args": ["exec"] },
"models": { "author": "claude-code/opus", "validator": "gpt-sol" },
"verify": { "build": "npm run build", "test": "npm test" },
"build": { "maxRecoveryAttempts": 1, "verifyRetries": 1, "logDir": "build-logs", "commit": true, "critiqueTests": false },
"validate": { "rounds": 2, "strict": false, "scopeDownAfterRound": 2 }
}build.maxRecoveryAttempts bounds recovery agents per workstream, and
build.verifyRetries (default 1) re-runs a failed verify command before the
failure counts against the attempt — absorbing flaky tests instead of
spending a recovery agent on them. The runner also fingerprints the working
tree before each workstream's first attempt (persisted to
build-logs/{program-id}-baselines.json): an agent that changes nothing on
an untouched workstream is failed as a no-op, but once earlier attempts have
left work in the tree, a no-op attempt proceeds to verification instead — so
a resumed build cannot dead-end on already-implemented work. A nonzero agent
exit moments after spawn with an unchanged tree stops the build as an agent
environment failure (usage limit, credentials, startup problem) rather than
burning recovery attempts on instant repeats of the same error.
Test critique. Independent verification proves only that the
implementation and its tests agree — and the same agent wrote both. With
build.critiqueTests enabled, the runner hands each workstream's diff and
spec to the validatorAgent after verification passes and before the commit,
asking whether a plausible wrong implementation would pass, whether every
acceptance criterion has a test that could fail, whether failure paths are
reached, and whether any test was weakened or deleted to make the suite green.
It annotates and never blocks: the findings land in the events log as
test-critique and in the build result, but a verified commit still lands.
Commits. The runner owns commits; workstream agents are instructed never
to commit. With build.commit enabled (the default), each workstream is
committed as build({program-id}): {ws-id} {name} immediately after it passes
independent verification and its manifest status is written — so every
runner-authored commit is green, and a failed build leaves exactly the work
that did not pass in the working tree. --no-commit overrides the config for
one run, and commits are skipped automatically outside a git repository.
Because those commits must not absorb unrelated work, a dirty working tree
aborts the build before it starts, listing the offending paths: commit or
stash them, or re-run with --no-commit. The single exception is the
uncommitted work a previous failed run of the same program left behind
(fingerprinted in build-logs/{program-id}-uncommitted.json), which is
accepted so resuming after a failure needs no cleanup. A commit that git
itself refuses — a rejecting hook, an unset user.email — is reported as
commit failed and leaves the verified changes in the tree; it never fails
the workstream, and the runner never bypasses hooks to force one through.
npm exec program-pipeline -- converge phase-1
npm exec program-pipeline -- converge phase-1 --rounds 3 --strictEach round pairs one critic, which reports findings and never edits, with
one writer, which applies fixes and may decline any finding it believes is
wrong. The roles alternate between the authorAgent and validatorAgent
blocks, so neither model ever grades its own writing — a critic allowed to fix
tends to stop finding, converging on its own taste rather than on quality.
Note that the loop runs authorAgent, not agent. Building a workstream
and judging a spec are different jobs: agent is frequently set to a cheaper
model on purpose, and that model has no business critiquing and rewriting
specs a stronger one authored. With no authorAgent configured the loop falls
back to the build agent and says so loudly in its output — treat that warning
as a configuration bug, not a note.
The loop names both resolved agents before it spends anything, so an unintended model shows up in the first line of output.
The runner composes both briefs itself. That is the point of putting the loop in the package rather than in a skill: when an orchestrating agent assembled the external validator's prompt, it could fold in its own framing ("ignore length, ignore file counts") and quietly narrow the gate before the critique began. There is no longer a seam to do that through.
Rounds 1 and 2 always cover the whole program; scoping to changed workstreams is allowed only from round 3. Scoping earlier would use the declared dependency graph to choose what to re-check, but finding undeclared dependencies is part of the job — a workstream that silently consumes another's output is not in the producer's neighbor set.
The loop ends as converged (a round produced no new blocker or major findings), cap-reached (the round cap ran out, a normal outcome given how subjective majors are), requires-replan (a structural defect no spec edit can fix — the loop stops immediately rather than polishing a workstream that should be split), or aborted. How the loop stopped and whether the gate passed are decided separately: the gate comes from the deterministic validator over the final tree.
Findings the writer declined and the critic then re-raised are reported as open disagreements for a human to settle, rather than resolved by whoever edits last.
Severity is decided by policy, not by prompt. A finding keeps its severity
only if it cites a locatable cause — a file and line range, or a named
concern. One supported solely by a measurement (line count, file count) is
downgraded to advisory and drops out of the gate. This is the opposite of
suppression: the critic may argue a spec is too long as forcefully as the
evidence warrants, it just has to say why. "WS-04 is 800 lines" is set aside;
"WS-04 bundles auth and telemetry, split at step 12" and "lines 210-340
restate the program doc verbatim" keep full severity and stay actionable.
Model roles are explicit, not implicit. Three separate blocks, because three separate jobs:
| Block | Job | Used by |
|---|---|---|
agent |
Implements workstreams. A cheaper model is usually the right call. | build |
authorAgent |
Reasons about specs — critic and writer in the loop. | converge |
validatorAgent |
The independent second opinion. | converge, test critique |
Each block declares an invocation mechanism — command, base args, prompt mode — and the runner passes the args verbatim. A model flag for that CLI belongs there, spelled the way the CLI expects.
Test critique stays on validatorAgent deliberately: it reviews code the
build agent wrote, so the independent reviewer is the point.
models is a different mechanism and does not reach the runner. It declares
host-neutral intent for workflows that switch models in-host (the
authoring skill, for example). The runner spawns processes and needs a
concrete command, so models.author: opus-5 has no effect on converge —
that is what authorAgent is for.
Model names. The pipeline has no model registry; every name belongs to
the namespace of the tool that consumes it. Args in agent and
validatorAgent are whatever that CLI accepts — prefer stable aliases over
dated snapshot IDs where the CLI supports them (for example --model opus
rather than a dated Opus ID), since aliases track the current model and do
not go stale; pin an exact ID only when you need reproducibility across a
long program. Names in models are host-neutral intent, not host picker slugs — write
the stable family/tier shorthand (for example opus-5, sol), and each
host resolves that intent to its own concrete model at run time, stating the
mapping. Host-specific slugs (Cursor variant names and the like) must never
be written into models — they are meaningless to other hosts and rot the
fastest. When any configured name genuinely goes stale,
pipeline.config.json is the single place to fix it — the workflow skills
are instructed to propose and apply that config fix (with your approval)
rather than patching skill files or working around it.
The agent receives each workstream prompt on stdin by default — keep that
default whenever the agent CLI supports it. Set "promptMode": "argument"
only for agents that require the prompt as a positional argument; in that
mode the runner always spawns the command directly (no shell), because a
shell — cmd.exe on Windows in particular — mangles multiline prompt
arguments. Consequence on Windows: argument mode cannot launch .cmd shims
(npm-installed CLI wrappers); point command at a real executable or use
stdin mode. PROGRAM_PIPELINE_AGENT_COMMAND is honored as a fallback agent
command. requireApprovalBeforeBuild is the only approval gate — projects
initialized by this package default it to false, so invoking the build
workflow starts the build; set it to true when you want every build to stop
for confirmation first (execution then requires --yes). Use --dry-run to
inspect the plan without running anything. A workstream passes only
when the agent exits successfully and every verify command exits
successfully — verification alone never rubber-stamps a crashed agent, and an
agent's success claim is never trusted without verification. --start-from
is rejected when it would skip a dependency that is not already complete.
Exit codes: 0 success or planned, 1 failed or aborted, 2 approval
required (blocked by requireApprovalBeforeBuild without --yes).
Workstream agents start as clean headless sessions: the runner strips
inherited agent-session environment markers (CLAUDECODE, CLAUDE_CODE_*,
CURSOR_AGENT, CURSOR_TRACE_*) before spawning, so a build launched from
inside Claude Code or Cursor cannot make the child CLI think it is attached
to the orchestrating session.
No-op guard. A workstream is only complete when the agent exited
successfully, the git working tree actually changed during the attempt,
every file the spec declares (NEW) exists afterward, and all verify
commands pass. An idle agent on an already-green repository fails the
attempt instead of being falsely completed. The tree check needs a git
repository (a tree-guard-disabled event is emitted without one; the
declared-files check still applies), and deliberately re-running an
already-implemented workstream via --start-from will fail as a no-op —
that is the guard working as intended.
Run deterministic validation for a program's manifest and workstream specs.
npm exec program-pipeline -- validate phase-1 --cwd .
npm exec program-pipeline -- validate phase-1 --cwd . --strict
npm exec program-pipeline -- validate phase-1 --cwd . --jsonVerify that the installed package contains every required skill, template, and schema.
npm exec program-pipeline -- doctorAfter running program-pipeline install, invoke the skills from your agent's
command interface in this order as needed:
/init-project— bootstrap the project structure and templates./plan-program— turn the vision and current as-built state into a program plan and manifest./author-workstreams— create self-contained implementation specs and run the validation gate./validate-workstreams— run the critic/writer convergence loop over the specs, checking coverage, dependencies, traceability, test quality, and build readiness./review-program— perform a read-only architecture and integration review./build-program— execute manifest workstreams through the build pipeline./update-as-built— snapshot the system that was actually built.
The same skill names and workflow semantics are packaged for Cursor, Claude Code, OpenClaw, Codex, and Gemini CLI; only their installation roots differ.
Requires Node.js 20 or newer.
npm ci
npm run build
npm run typecheck
npm test
npm run lint
npm pack --dry-runMIT © 2026 Wing It Labs