The HVE-Core substrate
HVE-Core gives the engineering pipeline durable memory (
state.json), recovery after interruption, and transitions gated by verdicts.
Why a substrate
The pipeline driven by skraft-orchestrator needs one source of truth: where
engineering stands, what verdict was issued, and how many retries happened. Without
it, every agent would improvise state and recovery after an interruption would be
impossible. DISCOVER, DISCUSS, and Brownfield roots remain standalone workflows.
They do not mutate this state.
state.json — the pipeline memory
State persists as JSON at
.copilot-tracking/skraft-plans/{project-slug}/state.json. Its contract is the JSON Schema
plugins/skraft-framework/src/domain/state.schema.json. Key fields:
{
"currentPhase": "RESEARCH | DESIGN | DISTILL | DELIVER | DONE",
"phaseArtifacts": { "DESIGN": ["adrs/ADR-001-...md"], "...": [] },
"verdicts": { "DESIGN": "APPROVED | CHANGES_REQUESTED | null" },
"retryCount": { "DESIGN": 0 },
"userPreferences": { "maxRetriesPerPhase": 2 },
"adrRatification": { "checkpointStatus": "none | awaiting_human | resolved", "pending": [], "ratified": [] }
}
currentPhaseadvances only on anAPPROVEDverdict.phaseArtifacts,verdicts,retryCounttrace what each phase produced and how it was judged.maxRetriesPerPhase(default 2) bounds retries before human escalation.adrRatificationholds DESIGN until a human ratifies every proposed ADR.
The state CLI enforces that schema on every read and write. A field the schema does not
declare, or a value outside its shape, makes the state invalid: no older format is
migrated. A pipeline started with an earlier version therefore stops with
INVALID_STATE; state.mjs diagnose names the next command, and after reset the
orchestrator rebuilds the state from the artefacts on disk, with your confirmation.
The state carries no quality dial. Mutation and coverage thresholds, the four
adversarial review lenses, the Gherkin gate and the Outside-In double-loop TDD variant
are fixed once and for all by the skraft-quality-bar skill; they are the same on every
run, and nothing written into state.json can lower them.
The write-through model
state.json is a safety snapshot, not a block reread on every turn:
- Rehydrate — read and validate the snapshot once at session start.
- Execute — decide from the last state the CLI printed, then dispatch an agent or request a human decision.
- Record — apply each mutation through the deterministic
state.mjsCLI, which prints the updated state.
How the phases articulate
skraft-orchestrator is selected with a refined story. It sequences only
RESEARCH → DESIGN → DISTILL → DELIVER. RESEARCH may be skipped when a confirmed
upstream HVE handoff proves it already satisfied; it has no declared phase reviewer. The next three phases advance
according to verdicts from their dedicated reviewers.
flowchart TD
O([skraft-orchestrator]) -->|READ / WRITE| S[(state.json)]
O --> D1[RESEARCH when needed]
D1 --> D3[DESIGN]
D3 --> R3{reviewer}
R3 -->|APPROVED| D4[DISTILL]
R3 -->|CHANGES_REQUESTED| D3
D4 --> R4{reviewer}
R4 -->|APPROVED| D5[DELIVER]
R4 -->|CHANGES_REQUESTED| D4
D5 --> R5{reviewer}
R5 -->|APPROVED| DONE([DONE])
R5 -->|CHANGES_REQUESTED| D5
On CHANGES_REQUESTED, the same phase is re-dispatched, retryCount increases,
and currentPhase does not move. When the retry budget is reached without
APPROVED, the orchestrator escalates to the user.