Skip to content

Repository files navigation

@wildorder/program-pipeline

A provider-neutral TypeScript CLI and portable Agent Skills package for planning, validating, building, and documenting engineering programs.

Get started

# 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.

Install

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-pipeline

Run the local executable with npx:

npx program-pipeline --help

CLI

setup

One-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 pnpm

init

Create 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

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.

build

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-commit

Configure 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.

Spec validation: the convergence loop

npm exec program-pipeline -- converge phase-1
npm exec program-pipeline -- converge phase-1 --rounds 3 --strict

Each 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.

The three agent roles

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.

validate

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 . --json

doctor

Verify that the installed package contains every required skill, template, and schema.

npm exec program-pipeline -- doctor

Installed workflow skills

After running program-pipeline install, invoke the skills from your agent's command interface in this order as needed:

  1. /init-project — bootstrap the project structure and templates.
  2. /plan-program — turn the vision and current as-built state into a program plan and manifest.
  3. /author-workstreams — create self-contained implementation specs and run the validation gate.
  4. /validate-workstreams — run the critic/writer convergence loop over the specs, checking coverage, dependencies, traceability, test quality, and build readiness.
  5. /review-program — perform a read-only architecture and integration review.
  6. /build-program — execute manifest workstreams through the build pipeline.
  7. /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.

Development

Requires Node.js 20 or newer.

npm ci
npm run build
npm run typecheck
npm test
npm run lint
npm pack --dry-run

License

MIT © 2026 Wing It Labs

About

Provider-neutral program planning and agentic delivery workflows

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages