Auto plan
Autonomous software delivery for AI agents. 18 skills that turn the lifecycle into bounded, self-correcting, checkpoint-resumable phases with deterministic enforcement hooks and a self-improving learn/map loop. For Claude Code and Codex.
npx -y skills add ulpi-io/autonomous-engineering --skill auto-planAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Turn a spec into a self-reviewed DAG of atomic build tasks: each task gets acceptance criteria, a disjoint write scope (≤3 files), and a slice-scoped validate; dependencies are wired and layered topologically so nothing builds on a missing base. Adversarial critics then attack the graph (cycles, phantom paths, coverage vs spec, task independence) until it is clean. Writes .ulpi/plans/<name>.json. Use when a spec needs an implementable, ordered breakdown before building.
SKILL.md
17.5 KB, as published. Nobody here has run it
Auto Plan
Overview
Decompose a spec into the smallest set of build tasks that can each be implemented, tested, and committed on their own, wired into a dependency DAG and layered so the build walks it safely and parallelizes where the graph allows. The plan is self-reviewed to catch the defects (cycles, mis-ordering, fat tasks, phantom paths) that would otherwise surface as build failures.
Phase 0: Require and read the spec; ground in the repo
- Resolve the spec (
$specpath, or the newest.ulpi/spec/*). If none, or if it's vague/untestable, STOP and route back toauto-spec— a plan inherits the spec's groundedness. - Require the independent, write-once intake snapshot and read its Binding selected scope checklist.
The plan's
selectedScope[]is an exact copy, not its own authority. If the spec or plan omitted, changed, or added an id/title/source, keep the mismatch visible and route it back for correction. - Read the repo to ground the plan: existing structure, modules, build/test commands, the workspace validate, and the load-bearing invariants.
- Honor the prior-run lessons already in your loaded context —
auto-learnwrites plan-shape lessons into CLAUDE.md and.claude/rules(which Claude Code loads automatically), so a task pattern that blocked last run is a BINDING input here: decompose it differently, don't re-attempt it verbatim. - Open a
checkpoint-resumerun.
Success criteria: a testable spec is loaded; the repo's structure + validate commands are known.
Phase 1: Decompose into atomic tasks
Break the spec's acceptance criteria into tasks. Each task carries:
id+ a one-line title;- acceptance criteria — from the spec, the subset this task satisfies (testable);
- scope mapping —
scopeItems[], the selected-scope ids this task covers (technical support tasks may map none, but every selected id must map to at least one task); - write scope — the files/dirs it may modify (disjoint from sibling tasks in the same layer);
- validate — the slice-scoped command that proves it (greenable once this slice + deps integrate; never a whole-suite e2e that only passes at end-state);
- specialist routing —
agent/skill/reviewerchosen for this task (see below; null when nothing fits and the build should run generic); - notes / patterns to follow.
Assign a specialist per task (match the INSTALLED set by description, not by name)
For each task, pick the best-fit specialist FROM WHAT IS ACTUALLY INSTALLED — the subagent types in
your options and the domain skills in your available-skills list. Match on the agent's/skill's own
description of what it does and when to use it, never on its name: a user's Next.js specialist might
be called frontend-wizard and their Rust one crab, so read what each is FOR and route the task to
the one whose description fits the work (a Next.js page task → the agent/skill for React/SSR; a
migration → the DB/framework specialist; a UI/design task → the design skill; and so on). Record on the
task: agent (the installed subagent to build it), skill (the installed domain/design skill the
engineer should invoke for correct patterns), and reviewer (the installed specialist to review it) —
each the real installed name, or null when nothing genuinely fits (the build then runs a general
engineer). Never invent an agent/skill that isn't installed, and never route on a guessed name.
Keep tasks thin: a task should be a single vertical slice with at most 3 write-scope entries (files or dirs) — split anything bigger; MERGE two that can't validate independently. Four planning failure modes to design out per task:
- Capability providers — a task claiming a side effect (persistence, network I/O, registration, queueing) must STATE where that capability comes from (an existing module, or the task that provides it as a dependency). A capability from nowhere is a phantom.
- Export/registration ownership — every NEW file needs a named owner for its export/barrel/registry/ router wiring: this task or a specific dependent. Unowned wiring is how "done" tasks ship dead code.
- Semantic-hardening splits — if a task could be "completed" with placeholders or dead wiring, split the semantic hardening into an explicit follow-up task; never let structure-only pass as behavior.
- No vague contract language — "graceful degradation", "eventually consistent", "internal update" are banned unless the task defines owner, concrete behavior, and recovery path.
And make each validate genuinely slice-scoped in COMMAND FORM, not just intent: scope it to the task's
own test files (e.g. pnpm --filter <pkg> exec vitest run <file> — NOT pnpm --filter <pkg> test -- <file>, where the -- makes vitest ignore the positional and run the whole package, leaking unrelated
failures into this task's gate). Every test file the command runs must be in this task's writeScope or
guaranteed green by an integrated dependency.
Success criteria: a set of atomic tasks, each with criteria, disjoint write scope, and a slice-scoped validate.
Phase 2: Wire the DAG and layer it
- For each task, set
dependsOn= the tasks whose OUTPUT it needs (a migration it reads, a route it extends, a symbol it imports, a test another task grows). - Compute
layers: a topological order where every task appears strictly after all it depends on. Tasks within a layer must be independent (disjoint write scope) so the build can run them in parallel. - Verify the graph is acyclic.
Write ONE canonical artifact: .ulpi/plans/<name>.json, including top-level selectedScope[], task-level
scopeItems[], and top-level scopeDrops[]. A drop record is valid only after the user separately
acknowledges that exact id and the record contains acknowledgedByUser: true plus the acknowledgement
evidence; general plan approval is not evidence. There is deliberately NO stored markdown
twin — a second artifact is a drift class (the copies diverge and the validator only gates one). The
human view is DERIVED on demand:
node <skill-dir>/scripts/validate-plan.mjs <plan.json> --intake <absolute-snapshot.json> --render
prints the layered, checklisted markdown — use its OUTPUT in-conversation when presenting the plan
(e.g. the approval gate); it can never disagree with what the build will execute. NEVER write the
rendering to a file unless the user explicitly asks for one — an unrequested .md on disk is exactly
the drift-prone twin this design deletes.
Success criteria: a complete {tasks[], layers[][]} graph — acyclic, topologically ordered,
intra-layer independent.
Phase 2.5: Run the structural gate — it is CODE
node <skill-dir>/scripts/validate-plan.mjs .ulpi/plans/<name>.json --intake <absolute-snapshot.json>
The DAG's safety properties are deterministic, so they are enforced by script, not prose: acyclicity,
topological layer order (nothing builds on a missing base), intra-layer write-scope disjointness
(prefix-aware), the ≤3-entry atomicity cap, ≥2 acceptance criteria per task, and BLOCKING on whole-suite
e2e validates (a bare playwright test/cypress run). The ambiguous <runner> test -- <file> form is a
non-blocking WARNING — it is the vitest footgun but ALSO canonical for Jest, and the gate can't know the
runner, so it advises an explicit runner rather than blocking a correct plan. Exit 1 = fix the graph and
re-run until 0. The critics below argue SEMANTICS; this script owns STRUCTURE.
It also owns intake fidelity plus binding-scope coverage for executable plans: --intake is mandatory;
plan selectedScope[] must exactly match the snapshot's ids/titles/sources; task.scopeItems[] and
scopeDrops[] may reference only snapshot ids; duplicates fail; and every intake id must be task-mapped
or separately user-acknowledged in scopeDrops[]. Missing/changed intake ids and unacknowledged drops exit 1.
Executable plans (coordinator-run) get HARDENED checks
A plan is executable when a coordinator will actually construct a git worktree/branch from each
task's id and execute its validate — i.e. auto-build's per-task contract
(git worktree add <path> -b task/<id> <workingBranch>) or the Codex-native pipeline coordinator. The
gate treats a plan as executable when it opts in EITHER explicitly ("executable": true, or "mode" one
of executable/expansion/codex) OR implicitly by any task carrying a nonempty validateCommand
(the execution-native, provider-neutral command field). A purely descriptive Claude-Code plan (tasks
carry only the legacy validate, never reach git/exec) is NOT executable and these extra checks skip it.
For an executable plan, the gate additionally enforces (each failure carries task-specific evidence):
- Safe task ids (path/shell-inert). An executable
idis constructed intogit worktree add -b task/<id>and a worktree filesystem path, so it must match the safe charset^[A-Za-z0-9][A-Za-z0-9_-]*$— only[A-Za-z0-9_-], and it MUST start with an alphanumeric. Canonical form:TASK-<n>(e.g.TASK-001). This bars path traversal (../), shell metacharacters (spaces,;,$, backticks), and a leading-(which git would read as a flag) from ever reaching worktree/branch construction. An unsafe id is a BLOCKING violation — rename the task. - Provider-neutral validate (normalized). Both the execution-native
validateCommandand the legacyvalidateare accepted and normalized to ONE trimmed nonempty slice command (validateCommandpreferred). A task with neither fails; the end-state/footgun form-checks judge the normalized command, so an executable plan need only supplyvalidateCommand(no legacyvalidaterequired). - Required execution fields present. Every executable task must carry the fields the coordinator
needs to run it: a nonempty
writeScope[], ≥2 acceptance criteria (acceptance/acceptanceCriteria), and one nonempty slice validate command. A missing field is a BLOCKING violation. - End-state-only validate is refused. Beyond the bare-e2e block above, an executable task's validate
that is a bare whole-suite runner with NO task slice (e.g.
pnpm -w test,npm test,jest,vitest run,go test ./...,pytest) only greens at end-state, so the slice always looks red mid-build — BLOCKING. A compound command that references a slice file/path (e.g.node scripts/validate-skills.mjs && bash scripts/test-plan-validate.sh) is correctly NOT flagged.
Phase 3: Adversarial self-review (converge until clean)
Run converge-loop with adversarial-verify critics attacking the plan each round:
- acyclicity + topological order — any task ordered before a dependency? any cycle?
- phantom paths — any write scope / validate referencing something that doesn't (and won't) exist?
- task independence — do two same-layer tasks share write scope (a race)? does a task secretly need
another's output without a
dependsOn? - atomicity — is a task actually two changes? Can each task's validate really go green at its slice? If two can't validate independently, MERGE them.
- coverage — does the union of
task.scopeItems[]cover the entire intakeselectedScope[], even if the spec under-covered it? Flag every id with no task asUNCOVERED. Also check spec criteria, but never use spec coverage as a substitute for intake coverage.
Fix findings in the JSON (the only artifact); re-review; exit clean or report the remaining defects.
Success criteria: the graph passes every check, or the loop reports the specific unresolved defects.
Phase 4: Finalize
Close the checkpoint; report the plan location, task count, layer count, and the parallelism the graph
allows (widest layer). This plan is the input to auto-build.
Success criteria: a clean, self-reviewed plan is written and ready to build.
Common Rationalizations
| Rationalization | Reality |
|---|---|
| "This task is a bit big but splitting is annoying." | A fat task can't be verified or rolled back cleanly. Split it, or the build inherits the mess. |
| "These two touch the same file but should be fine in parallel." | Same write scope in one layer is a race. Separate layers or merge them — don't hope. |
| "I'll let the build figure out the order at runtime." | Order is a plan property. A runtime retry building on a missing base is not ordering. |
| "The validate can be the full e2e suite." | A whole-suite validate only greens at end-state, so every slice looks broken. Make validate slice-scoped. |
| "The self-review found nothing, one pass is enough." | Cycles and phantom paths hide. Loop until a review pass is genuinely clean. |
| "Two tasks that can't validate alone is fine, they're logically separate." | If neither is independently greenable, they are one unit of work. Merge them. |
| "The plan covers the whole spec, so scope is covered." | The spec or plan can be the thing that shrank. Compare both to the independent intake snapshot; every missing/changed id is blocking. |
Red Flags
- A task's write scope or validate points at a path nothing creates.
- Two tasks in the same layer writing the same file.
- A task ordered before something it depends on (or a cycle).
- A validate command that's the full test suite rather than a slice.
- Spec acceptance criteria with no task covering them.
- A selected-scope id with no
task.scopeItems[]mapping, or a drop inferred from general plan approval. - The self-review loop ran once.
Guardrails
- Never emit phantom paths or ungrounded validate commands.
- Never create a task touching more than 3 files, claiming an unsourced capability, leaving a new file's export/registration unowned, or hiding placeholder-completable work without a hardening follow-up.
- Never put dependent or write-scope-overlapping tasks in the same layer.
- Never order a task before its dependencies; never ship a cyclic graph.
- Never leave a spec criterion uncovered by some task.
- Never leave a selected-scope id uncovered. A drop requires a separate per-id user acknowledgement; approving the plan never implies one.
- Never sign off a plan the self-review couldn't make clean — report the defects.
When To Load References
scripts/validate-plan.mjs— the deterministic structural gate (Phase 2.5), CI-tested byscripts/test-plan-validate.sh. auto-build's preflight and the pipeline preflight run it too — a plan that fails it never builds.adversarial-verify(skill) — the plan critics in Phase 3.converge-loop(skill) — the until-clean review loop.checkpoint-resume(skill) — durable plan-run state.
Output Contract
Report:
- plan path (
.ulpi/plans/<name>.json— single canonical artifact), independent intake snapshot path/hash, task count, layer count - the DAG shape — dependency edges and the widest parallel layer
- SCOPE COVERAGE: N of M selected-scope items covered, with covered ids, explicit per-id drops, and
every
UNCOVEREDid; then spec-coverage confirmation - self-review outcome (rounds to clean, or the remaining defects)
- specialist routing — which installed agents/skills tasks were matched to (and the tasks left generic)