Erpaval
Workflow for autonomous software development with Claude Code. Classifiers route scope, complexity, directory state, and spec readiness before committing to Explore / Research / Plan / Act / Validate, then close the loop with a Compound step that persists lessons to `.erpaval/solutions/` for future sessions. Optional HMW reframing and EARS specification add structured rigor — Claude judges when to run them. Each Act subagent edits its own Markdown task packet section-by-section per the write protocol, and the orchestrator monitors with `wc -l`. Use when the user asks to implement a feature autonomously, build with agents, use ERPAVal, plan and execute a coding task, delegate to subagents, do agent-driven development, extract lessons, recall prior lessons, or mentions autonomous coding workflow or compound engineering.From its SKILL.md
npx -y skills add theagenticguy/erpaval --skill erpavalAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
21.2 KB, as published. Nobody here has run it
Contents
| Reference | When to load |
|---|---|
references/flow.md | The graph — intake, build loop, validate/compound, cycles |
references/classifiers.md | Prompt text for each CL-* classifier |
references/fan-out.md | Per-phase subagent counts + the one-message parallel-launch rule |
references/glossary.md | CP-*, CL-*, gates, cycles, zones, placeholder tokens |
${CLAUDE_PLUGIN_ROOT}/skills/product-discovery/references/roles/hmw-framer.md | HMW substep (hard-dep on product-discovery; run when CL-RIGOR asks for HMW) |
${CLAUDE_PLUGIN_ROOT}/skills/product-discovery/references/roles/ears-specifier.md | EARS substep (hard-dep on product-discovery; run when CL-RIGOR asks for EARS) |
references/orchestrator.md | Per-phase runbook — Task-tool lifecycle, Agent patterns |
references/context-packets.md | Per-packet YAML schemas + two-gate review + auto-merge rules |
references/write-protocol.md | Canonical write-protocol block (copied into every Act prompt) |
references/validation-playbook.md | 3-layer validation + closed-loop toolchain |
references/compound.md | Dual-track lesson schema + recall retrieval algorithm |
templates/session/worklog-skeleton.md | Per-task packet skeleton with embedded write protocol |
templates/session/ | YAML schemas the orchestrator seeds into .erpaval/sessions/<id>/ at runtime |
templates/specs/ | EARS spec and task-list skeletons for the Framing substep |
templates/solutions/ | Lesson templates (bug, knowledge) the Compound phase writes from |
templates/brainstorms/ | HMW requirement skeletons for the Framing substep |
templates/INDEX.md | Recall-phase index of lessons by category, read at session start |
ERPAVal — adaptive autonomous software development
A six-phase workflow with two framing substeps and a compounding tail. The orchestrator (main Claude Code session) runs classifiers to decide which phases apply, delegates implementation to subagents, and persists Markdown + YAML packets under .erpaval/ so future sessions start smarter than this one.
The graph at a glance
flowchart LR
IN[Intake + Recall bootstrap] --> SCOPE{Scope?}
SCOPE -->|coding| COMPLEX{Complexity?}
SCOPE -->|non-coding| ROUTE[Upstream skill]
COMPLEX -->|1-file fix| DIRECT[Direct fix]
COMPLEX -->|multi-module or rebuild| RESUME{New or resume?}
RESUME -->|new| NEW[erpaval-new.py]
RESUME -->|resume| PRIOR[Load prior session]
NEW --> DIR{Dir state?}
PRIOR --> DIR
DIR --> RIGOR{Rigor?}
RIGOR -.->|fuzzy| HMW[HMW frame]
RIGOR -.->|contract unclear| EARS[EARS spec]
HMW --> EARS
EARS --> ER[Explore + Research]
RIGOR -->|crisp| ER
ER --> PLAN[Plan]
PLAN --> G1{Gate 1}
G1 -.->|revise| PLAN
G1 -->|approved| ACT[Act · waves]
ACT --> VAL[Validate]
VAL -.->|fail| ACT
VAL -->|pass| G2{Gate 2}
G2 --> MERGE[Merge]
MERGE --> COMP[Compound · extract lessons]
COMP --> DONE([Done])
Full three-view graph with every cycle is in references/flow.md. Dashed edges are named cycles.
Strict phase gating via TaskCreate / TaskUpdate / TaskList
Each phase has a completion gate enforced by the TaskCreate / TaskUpdate / TaskList todo-list tool family (distinct from the Agent subagent-launcher). Every implementation task is wired with addBlockedBy so the task system itself prevents out-of-order execution. No skipping, no parallel execution across gates, no early starts.
The todo-list tools hold authoritative state. YAML packets under .erpaval/sessions/ are read-only hints that inform which tasks to create and what goes in their prompt. Per-task Markdown packets at .erpaval/sessions/<id>/tasks/T-AC-X-Y.md double as subagent work logs — the agent edits them section-by-section per write-protocol.md, and the orchestrator monitors with wc -l. Partial progress on disk survives timeouts and SendMessage interrupts; state held in working memory does not.
See references/orchestrator.md for the per-phase runbook.
Session 0 — mandatory intake scaffolding
Two steps the orchestrator always runs before Explore, so Compound can actually fire at the end of the session.
- Recall first (always).
uv run ${CLAUDE_PLUGIN_ROOT}/skills/erpaval/tools/erpaval-recall.py bootstrapsurfaces category counts +INDEX.mdpath. Cold repos printno prior lessonsand proceed. TheSessionStarthook also emits this viaadditionalContext, but the tool call is the authoritative record — run it. - Decide new vs resume (after
CL-COMPLEXITYreturns multi-module / rebuild).CL-RESUMEreads the request,ls .erpaval/sessions/session-*/(sorted by mtime), and the top-5 priorsession.yamlfiles, then emits one of:- new session — run
uv run ${CLAUDE_PLUGIN_ROOT}/skills/erpaval/tools/erpaval-new.py --request "<raw_request>". Creates.erpaval/sessions/session-<hex>/intake.yaml, ensures.gitignoreandINDEX.md. Required — without asession-<hex>/dir, the Stop hook's six-gate check never clears and Compound silently no-ops. - resume session — read the prior
session.yaml+ latesttasks/*.md, append the new ask tointake.yaml.raw_request, continue from the last completed gate. Do not scaffold a newsession-<hex>/.
- new session — run
For 1-file fixes, CL-COMPLEXITY exits the flow before Session 0 step 2 — recall-only is correct; no session dir needed.
See references/classifiers.md for the CL-RESUME prompt and references/orchestrator.md for the runbook.
Pre-phase classifiers — where adaptation lives
Before Explore starts, the orchestrator runs classifiers to decide which phases to run. Claude judges — the user never picks from a menu.
| Classifier | Question | Skips / routes |
|---|---|---|
| CL-SCOPE | Is this a coding task? | Non-coding → route to /research, /product-discovery, /product-strategy, /working-backwards, /customer-research, etc. |
| CL-COMPLEXITY | 1-file fix · multi-module · rip-and-replace? | 1-file → skip ERPAVal, just fix |
| CL-RESUME | New session or resume a prior one? | new → erpaval-new.py; resume → read prior session-<hex>/ and continue. Runs only when CL-COMPLEXITY is multi-module / rebuild |
| CL-DIR | Empty dir · existing code · rebuild-in-place? | Empty → skip Explore, start at Research |
| CL-RIGOR | Problem crisp, or needs HMW / EARS? | Crisp → skip both; fuzzy → HMW; contract-unclear → EARS; both when needed |
| CL-SPEC | PRD / stack / concept ready? | Missing → loop through /product-discovery, /build-stack (product-discovery covers PRD drafting and design-thinking methodology) |
| CL-VALIDATE | All 3 validation layers green? | Fail → C4 back to Act |
| CL-C2 | Attempt-4 escalation in a stuck subagent? | fix-directly / respawn / missing-prereq (C3) |
| CL-LESSONS | Session produced novel learnings? | Yes → write to .erpaval/solutions/; no → skip |
See references/classifiers.md for each classifier's prompt text.
Optional rigor — HMW + EARS
CL-RIGOR decides whether to run these substeps. Both are well-suited to subagent delegation (bounded creative task, durable file output). erpaval hard-deps on product-discovery for these substeps: the orchestrator seeds brainstorms/NNN-<slug>-requirements.md or specs/NNN-<slug>/spec.md from ${CLAUDE_PLUGIN_ROOT}/skills/product-discovery/templates/hmw-skeleton.md / ears-spec-skeleton.md and spawns one general-purpose Task per substep that reads ${CLAUDE_PLUGIN_ROOT}/skills/product-discovery/references/roles/hmw-framer.md (or ears-specifier.md) as its role prompt.
- HMW (fuzzy problems) — customer-problem template, 3 of 9 d.school strategies, NN/g-validated HMW statements.
- EARS (unclear contracts) — 5 templates (Ubiquitous, Event-driven, State-driven, Optional feature, Unwanted behavior). Each AC carries
[P](parallel-safe) orDependencies: AC-X-Y. Plan derives tasks directly.
Skip both when the ask names a specific user segment, an observable outcome with a metric, and no solution verbs — see ${CLAUDE_PLUGIN_ROOT}/skills/product-discovery/references/frameworks/how-might-we.md (HMW skip test) and ${CLAUDE_PLUGIN_ROOT}/skills/product-discovery/references/frameworks/ears.md (EARS skip test).
Phase summary
| Phase | Purpose | Execution method | Parallelizable with |
|---|---|---|---|
| Explore | Build mental model of the codebase | 4–7 parallel Explore agents (one per perspective) | Research |
| Research | Fetch live API docs, versions, patterns | Parallel researcher agents — one per domain | Explore |
| Plan | Derive tasks from EARS spec + deps | Orchestrator + TaskCreate/TaskUpdate | None (needs E+R) |
| Act | Implement via parallel Agent calls | All wave tasks in one message, run_in_background | Per dependency graph |
| Validate | Verify correctness, quality, security | 4–8 parallel Opus dimension agents + static tools | Partially |
| Compound | Extract lessons from session | Orchestrator + compound.md procedure | None (post-merge) |
Subagent counts per phase live in references/fan-out.md. Every phase except
Plan and Compound fans out to multiple parallel Agent calls launched in one
message — current Claude models under-delegate by default, so running a
fan-out phase as a single agent (or inline in the orchestrator thread) is a bug,
not a shortcut.
Fan-out and grounding are the default, not the exception
Two standing rules govern every session. Both counteract failure modes the orchestrator falls into when left to its own defaults.
- Fan out wide, every phase. Explore, Research, Act waves, and Validate all
launch multiple subagents in parallel in a single message. The targets and the
one-message launch discipline are in
references/fan-out.md. The orchestrator coordinates; the subagents do the work. - Ground before you build. No code is written against a library, API, or
version that the Research phase hasn't grounded in current docs first —
Context7 (
resolve-library-id→query-docs) for library work, then the search MCP fleet per${CLAUDE_PLUGIN_ROOT}/skills/research/references/search-strategies.md. An un-grounded version pin or API surface inCP-RESEARCHblocks Plan. Seereferences/orchestrator.md§ Research for the mandate.
When to use ERPAVal
CL-COMPLEXITY decides before committing to the full flow.
| Scenario | Classifier verdict |
|---|---|
| Feature touching multiple modules | multi-module → full flow |
| Bug fix in a single file | 1-file-fix → skip ERPAVal |
| Greenfield project setup | multi-module + CL-DIR=empty → skip E |
| Rip-and-replace rebuild | rebuild → full E+R + destructive Wave 1 |
| Refactoring with behavioral preservation | multi-module → full flow |
| Integrating a new dependency or API | multi-module → heavy Research phase |
| Quick script or one-off tool | 1-file-fix → skip ERPAVal |
.erpaval/ directory — two-zone layout
Placeholder tokens (NNN, <hex>, <slug>, <domain>, T-AC-X-Y) are defined in references/glossary.md.
.erpaval/
INDEX.md committed — pointer from CLAUDE.md
solutions/ committed — dual-track lessons
<category>/ one folder per entry in
references/solution-categories.yaml
brainstorms/ committed — HMW outputs
NNN-<slug>-requirements.md
specs/ committed — EARS specs + derived tasks.md
NNN-<slug>/
spec.md
tasks.md
sessions/ gitignored — orchestrator-coupled, ephemeral
.nudged persistent ledger of session-ids already
nudged by compound_nudge.py (one line per id)
session-<hex>/
intake.yaml
recall.yaml
explore.yaml
research-<domain>.yaml
tasks/T-AC-X-Y.md
validation.yaml
lessons.yaml
session.yaml
Single .gitignore line: .erpaval/sessions/. The durables compound across team. Session state is orchestrator-coupled (subagent types, tool IDs, task schema) and a secrets surface — archive to object storage if audit is needed.
Recall + Compound — the compounding loop
Every session starts by reading prior lessons and ends by writing new ones:
- Session start — the plugin
SessionStarthook (hooks/session_start_bootstrap.py) emits category counts from.erpaval/solutions/asadditionalContext. Fires once per session; no-ops for projects without.erpaval/. - Pre-Act — the orchestrator queries
erpaval-recall.pyper task during Plan → Act, populating each packet's Prior Lessons section via tag / module scoring. - Mid-session — Claude invokes recall ad-hoc when a new sub-problem emerges that prior sessions may have hit.
- Post-merge — Compound runs as the sixth phase. CL-LESSONS filters candidates by novelty + reusability. Writes to
solutions/<category>/<slug>.md, updatesINDEX.md, adds the CLAUDE.md pointer if missing, recordssessions/<id>/lessons.yaml. TheStophook (hooks/compound_nudge.py) fires a one-shotdecision: blockwhen all six gates hold (see Tools and hooks table); once fired, the session-id is written to.erpaval/sessions/.nudgedand won't re-fire.
Compound can also run ad-hoc when the user wants to force-extract lessons mid-session. See references/compound.md for the dual-track schema, scoring formula, and operating sequence.
Ecosystem integration
Upstream skills (run before ERPAVal)
| Skill | When to use first |
|---|---|
Product Discovery (/product-discovery) | Define what to build before planning how (PRD drafting, HMW, EARS, user stories, JTBD) |
Tech Stack Builder (/build-stack) | Select technologies for greenfield projects |
Product Strategy (/product-strategy) | Business strategy frameworks (Rumelt, Wardley, Minto, Working Backwards) |
CL-SPEC loops through these automatically if any are missing.
Phase-level agent mapping
| Phase | Agent used |
|---|---|
| Explore | 4–7 parallel built-in Explore subagents, one per perspective |
| Research | Parallel plugin researcher agents, one per library/domain |
| Act | general-purpose subagents (haiku/sonnet/opus per task), all wave tasks in parallel |
| Validate | 4–8 parallel opus subagents, one per quality/security dimension |
| Compound | Orchestrator + compound.md procedure (invokes opus for CL-LESSONS) |
Tools and hooks
Hooks live at hooks/ and are UV-shebang Python scripts built on framework.py. All three hooks are fail-open via framework.run_hook — any uncaught exception logs to stderr and exits 0, so a broken hook cannot wedge a session.
| Hook | Event | Role |
|---|---|---|
session_start_bootstrap.py | SessionStart | Emit .erpaval/solutions/ category counts via additionalContext. Fires once per session and only when a sessions/session-<hex>/ dir was modified in the last 24h — cold repos stay silent. |
validate_packet.py | PostToolUse | Pydantic schema-check writes under .erpaval/. Early-exits on non-erpaval paths. Also drops /tmp/claude-erpaval-active-<session_id> as a cross-hook "this Claude session touched ERPAVal" marker. |
compound_nudge.py | Stop | One-shot decision: block when Compound is pending. Six gates: erpaval-active marker, session-<hex> name, fresh validation.yaml (<2h), no lessons.yaml, not nudged this session (HookState), not in .erpaval/sessions/.nudged persistent ledger. |
Imperative tools under tools/ — PEP 723 scripts invoked via uv run by the orchestrator:
| Tool | Purpose | Invoked by |
|---|---|---|
erpaval-new.py | Scaffold .erpaval/sessions/session-<hex>/ + seed intake.yaml | Orchestrator at session start |
erpaval-recall.py | Tag-scored grep over .erpaval/solutions/**.md | Orchestrator per Act task |
erpaval-validate.py | Pydantic schema check on YAML packet writes (CLI version) | Manual / CI — hook is primary |