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 ...
Installs into .claude/skills of the current project.
Are you the author of Erpaval?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/laithalsaadoon-erpaval-erpaval)
---
name: erpaval
description: >
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.
---
## 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
```mermaid
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.
1. **Recall first (always).** `uv run ${CLAUDE_PLUGIN_ROOT}/skills/erpaval/tools/erpaval-recall.py bootstrap` surfaces category counts + `INDEX.md` path. Cold repos print `no prior lessons` and proceed. The `SessionStart` hook also emits this via `additionalContext`, but the tool call is the authoritative record — run it.
2. **Decide new vs resume (after `CL-COMPLEXITY` returns multi-module / rebuild).** `CL-RESUME` reads the request, `ls .erpaval/sessions/session-*/` (sorted by mtime), and the top-5 prior `session.yaml` files, 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 `.gitignore` and `INDEX.md`. **Required** — without a `session-<hex>/` dir, the Stop hook's six-gate check never clears and Compound silently no-ops.
- **resume session** — read the prior `session.yaml` + latest `tasks/*.md`, append the new ask to `intake.yaml.raw_request`, continue from the last completed gate. Do not scaffold a new `session-<hex>/`.
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) or `Dependencies: 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 in `CP-RESEARCH` blocks Plan. See
`references/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`.
```text
.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 `SessionStart` hook (`hooks/session_start_bootstrap.py`) emits category counts from `.erpaval/solutions/` as `additionalContext`. Fires once per session; no-ops for projects without `.erpaval/`.
- **Pre-Act** — the orchestrator queries `erpaval-recall.py` per 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`, updates `INDEX.md`, adds the CLAUDE.md pointer if missing, records `sessions/<id>/lessons.yaml`. The `Stop` hook (`hooks/compound_nudge.py`) fires a one-shot `decision: block` when all six gates hold (see Tools and hooks table); once fired, the session-id is written to `.erpaval/sessions/.nudged` and 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 |