devrites 3.0.2 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +1 -1
  3. package/docs/adr/0001-go-engine-as-control-plane.md +43 -0
  4. package/docs/adr/0002-dual-host-harness.md +34 -0
  5. package/docs/adr/0003-gate-model-hitl-pause.md +38 -0
  6. package/docs/adr/0004-state-schema-phases-sections.md +47 -0
  7. package/docs/adr/0005-hooks-as-engine-subcommands.md +39 -0
  8. package/docs/adr/0006-clock-seam-and-engine-ci-gates.md +50 -0
  9. package/docs/adr/0007-canonical-live-workspace-filenames.md +36 -0
  10. package/docs/adr/0008-sanctioned-engine-network-boundary.md +33 -0
  11. package/docs/adr/README.md +58 -0
  12. package/docs/command-map.md +1 -1
  13. package/docs/engine/state-schema.md +18 -14
  14. package/docs/flow.md +1 -1
  15. package/docs/research/go-authoritative-workflow-schema-and-quality-2026-07-20.md +212 -0
  16. package/engine/hooks_workspace.go +7 -7
  17. package/engine/internal/gate/gate.go +4 -4
  18. package/engine/internal/gate/gate_test.go +2 -2
  19. package/engine/internal/lib/cursor_compat_test.go +29 -0
  20. package/engine/internal/lib/preamble.go +1 -1
  21. package/engine/internal/lib/preamble_questions_test.go +10 -0
  22. package/engine/internal/lib/progress.go +59 -20
  23. package/engine/internal/lib/resolve.go +15 -6
  24. package/engine/internal/lib/resolve_remediation_test.go +9 -0
  25. package/engine/internal/lib/tickafk.go +2 -2
  26. package/engine/internal/migrate/migrate.go +18 -44
  27. package/engine/internal/migrate/migrate_test.go +33 -5
  28. package/engine/internal/state/cmd/workflowmanifest/main.go +54 -0
  29. package/engine/internal/state/cursor.go +42 -7
  30. package/engine/internal/state/feature.go +29 -41
  31. package/engine/internal/state/schema.go +155 -28
  32. package/engine/internal/state/snapshot.go +49 -3
  33. package/engine/internal/state/state_test.go +77 -6
  34. package/engine/internal/state/workflow_manifest.json +310 -0
  35. package/engine/internal/workflow/commands.go +0 -36
  36. package/engine/internal/workflow/commands_test.go +0 -17
  37. package/engine/testdata/golden/TestParityProgress/arg=allbuilt.golden +1 -1
  38. package/engine/testdata/golden/TestParityProgress/arg=done.golden +1 -1
  39. package/engine/testdata/golden/TestParityProgress/arg=mid.golden +1 -1
  40. package/engine/testdata/golden/TestParityProgress/arg=nophase.golden +1 -1
  41. package/engine/testdata/golden/TestParityProgress/arg=noslice.golden +1 -1
  42. package/engine/testdata/golden/TestParityProgress/arg=plan.golden +1 -1
  43. package/engine/testdata/golden/TestParityProgress/arg=seal.golden +1 -1
  44. package/engine/tests/adr_0004_required_by_phase_test.go +1 -18
  45. package/engine/tests/budget_test.go +2 -2
  46. package/engine/tests/lib_parity_test.go +1 -1
  47. package/engine/tests/meta_test.go +3 -3
  48. package/engine/tests/migrate_cli_test.go +24 -22
  49. package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +5 -3
  50. package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +5 -3
  51. package/pack/generated/codex/AGENTS.md +1 -1
  52. package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +5 -3
  53. package/package.json +2 -1
  54. package/scripts/codex-generate.sh +1 -1
  55. package/scripts/grade-feature.sh +5 -3
  56. package/scripts/run-outcome-evals.sh +21 -0
  57. package/scripts/validate-workflow-security.py +3 -8
  58. package/scripts/validate-workspace-schema.py +9 -73
  59. package/scripts/validate.sh +10 -0
  60. package/scripts/workflow_schema.py +69 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All notable changes to DevRites are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and DevRites adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Releases are generated automatically by [semantic-release](https://semantic-release.gitbook.io/) from Conventional Commits on `main`.
4
4
 
5
+ ## [3.0.4](https://github.com/ViktorsBaikers/DevRites/compare/v3.0.3...v3.0.4) (2026-07-20)
6
+
7
+ ### Fixed
8
+
9
+ * **ci:** harden supply chain checks ([d902574](https://github.com/ViktorsBaikers/DevRites/commit/d902574a7d30168fcef94aa4a3dae7707191fe8d))
10
+ * **devrites:** normalize canonical workspace files ([e70221f](https://github.com/ViktorsBaikers/DevRites/commit/e70221f5dd9fbda0f3a73c500a493497bc023a91))
11
+
12
+ ## [3.0.3](https://github.com/ViktorsBaikers/DevRites/compare/v3.0.2...v3.0.3) (2026-07-20)
13
+
14
+ ### Fixed
15
+
16
+ * **rite:** centralize workflow schema ([58bd55e](https://github.com/ViktorsBaikers/DevRites/commit/58bd55e8472a98be1073bcfa5fe7593e7bf0c5d1))
17
+
5
18
  ## [3.0.2](https://github.com/ViktorsBaikers/DevRites/compare/v3.0.1...v3.0.2) (2026-07-20)
6
19
 
7
20
  ### Fixed
package/README.md CHANGED
@@ -115,7 +115,7 @@ Full diagram set (lifecycle, polish orchestrator, review fan-out, debug loop,
115
115
  rules carrier, workspace state, namespace map) →
116
116
  [`docs/flow.md`](docs/flow.md).
117
117
 
118
- **Status:** [`v3.0.2`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v3.0.2) — see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
118
+ **Status:** [`v3.0.4`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v3.0.4) — see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
119
119
 
120
120
  ## Contents
121
121
 
@@ -0,0 +1,43 @@
1
+ # ADR-0001: Go engine as deterministic control plane
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-07-08 (backfilled; decision predates the ADR log)
5
+
6
+ > Network scope was narrowed by [ADR-0008](0008-sanctioned-engine-network-boundary.md):
7
+ > deterministic workspace operations remain network-free, while explicit
8
+ > updater/source-cache I/O is isolated in `internal/iohooks`.
9
+
10
+ ## Context
11
+
12
+ DevRites orchestrates an LLM through a spec-driven lifecycle. Two kinds of work
13
+ are entangled: **judgment** (is this spec good? is this code right?) which only
14
+ a model can do, and **bookkeeping** (which phase are we in? are the required
15
+ sections present? what's the next question id?) which must be exact, fast, and
16
+ identical every run. Letting the model do the bookkeeping makes the process
17
+ non-reproducible and burns context on arithmetic.
18
+
19
+ ## Decision
20
+
21
+ Ship a single statically-linked Go binary (`CGO_ENABLED=0`, stdlib-only, zero
22
+ third-party deps in the hot path) as the **control plane**: it owns all
23
+ deterministic state transitions, gates, and derivations over `.devrites/`. It
24
+ makes **no** model or network calls. The filesystem is the data plane; the LLM
25
+ supplies judgment. Commands are a hand-rolled `switch` dispatch, not a CLI
26
+ framework.
27
+
28
+ ## Alternatives considered
29
+
30
+ | Option | Why not |
31
+ |--------|---------|
32
+ | Bookkeeping inside the agent prompt | Non-deterministic, context-hungry, unauditable — the exact failure this system exists to remove. |
33
+ | Node/TS engine (like the reference system GSD Core) | Drags a package tree + supply-chain surface; the pure-Go single binary has none and cross-compiles to every target from one runner. |
34
+ | Cobra / urfave CLI framework | A dependency and a config surface for a switch statement the stdlib already handles. |
35
+
36
+ ## Consequences
37
+
38
+ - Reproducible process: same state in, same verdict out, no wall-clock or
39
+ network variance (the one remaining wall-clock read is now seamed — ADR-0006).
40
+ - Zero-dependency binary: trivial supply chain, `go install`-able, no runtime.
41
+ - Cost: the engine can express only what's deterministic. Anything needing
42
+ judgment must round-trip to the model — by design.
43
+ - The engine is the trust root, so it carries the strictest CI gates (ADR-0006).
@@ -0,0 +1,34 @@
1
+ # ADR-0002: Dual-host harness (Claude + Codex)
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-07-08 (backfilled)
5
+
6
+ ## Context
7
+
8
+ Each AI coding host (Claude Code, Codex, and — in adjacent tools — Cursor,
9
+ Cline, Copilot) speaks its own hook dialect: different stdin shapes, exit-code
10
+ conventions, and settings surfaces. The lifecycle logic (orient, gate, hook
11
+ decisions) is host-independent; only the edge translation differs.
12
+
13
+ ## Decision
14
+
15
+ Support exactly **two** hosts today — `claude` and `codex` — behind a thin
16
+ `internal/harness` adapter that translates each host's hook stdin/exit
17
+ conventions into the shared `orient` + `gate` core. Host support is
18
+ enumerated in code, not open-ended. `harness-matrix --check` keeps
19
+ `docs/harness-compliance.md` in sync with the adapters (drift is a CI failure).
20
+
21
+ ## Alternatives considered
22
+
23
+ | Option | Why not |
24
+ |--------|---------|
25
+ | A generic declarative capability/adapter registry now (the GSD Core model) | Real ceiling-raiser for N hosts, but a large refactor unjustified at N=2. Recorded as a Proposed follow-up, not built. See the adoption study in `docs/research/gsd-core-adoption.md` §3.1. |
26
+ | Claude-only | Codex users are already real; single-host would strand them. |
27
+ | Per-host forks of the logic | Duplicates the lifecycle core across edges — the thing the adapter exists to prevent. |
28
+
29
+ ## Consequences
30
+
31
+ - Adding a host today means editing `harness.go` — acceptable friction at N=2,
32
+ the calcification risk rises with N (hence the Proposed registry follow-up).
33
+ - The shared core is tested once; only edge translation is host-specific.
34
+ - `harness-matrix --check` makes host-support drift visible in CI.
@@ -0,0 +1,38 @@
1
+ # ADR-0003: Gates block as a HITL pause, never a crash
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-07-08 (backfilled)
5
+
6
+ ## Context
7
+
8
+ A gate is a deterministic completeness check — e.g. "does this feature have the
9
+ sections required to leave the current phase?" When a gate is not satisfied the
10
+ engine must stop the agent, but *how* it stops matters. A crash (non-zero,
11
+ stderr stack) reads as a tool failure and invites the agent to retry blindly or
12
+ route around it. The intended meaning is the opposite: **the work is
13
+ incomplete, pause and involve the human.**
14
+
15
+ ## Decision
16
+
17
+ A blocked gate is a structured **human-in-the-loop pause**: a specific
18
+ "missing X" message on stdout and a distinct, reserved **exit code 3** — never a
19
+ crash, never a generic non-zero. Gates are **transition-fired** (they run only
20
+ when explicitly invoked at a phase boundary, not on every tool call). Two
21
+ kinds: `Readiness` (sections needed to leave the current phase) and `Seal` (the
22
+ full seal set). `StopGate` enforces the rest-point invariant: a feature claiming
23
+ completion with empty proof, or with `.red` set, cannot end the turn.
24
+
25
+ ## Alternatives considered
26
+
27
+ | Option | Why not |
28
+ |--------|---------|
29
+ | Exit 1 / crash on an unmet gate | Indistinguishable from a real error; agents retry or route around it instead of pausing for the human. |
30
+ | Run gates on every tool call | Turns a transition check into per-action overhead and noise; gates are boundary events. |
31
+ | Auto-advance past a soft-missing section | Defeats the completeness guarantee the gate exists to provide. |
32
+
33
+ ## Consequences
34
+
35
+ - Exit 3 is a reserved, load-bearing contract — the harness and hooks branch on
36
+ it. Its guard test (`tests/adr_0003_gate_exit_code_test.go`) locks it.
37
+ - Blocks are legible: the agent (and human) see exactly which section is missing.
38
+ - Gate authors must classify a stop as "incomplete" (exit 3) vs a true error.
@@ -0,0 +1,47 @@
1
+ # ADR-0004: Phase-relative section completeness
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-07-08 (backfilled)
5
+
6
+ > Artifact filename direction was amended by
7
+ > [ADR-0007](0007-canonical-live-workspace-filenames.md). Phase-relative section
8
+ > completeness remains unchanged.
9
+
10
+ ## Context
11
+
12
+ A feature's working state must be legible to both humans and the engine, and
13
+ "is it complete?" must be answerable deterministically at each step of the
14
+ lifecycle. A single long document makes completeness opaque and burns context;
15
+ a rigid "all fields required always" model blocks early phases on artifacts
16
+ that don't exist yet (there's no proof during framing).
17
+
18
+ ## Decision
19
+
20
+ Model feature state as **six single-concern sections** — `spec`, `plan`,
21
+ `decisions`, `tasks`, `proof`, `status`. Drive the lifecycle
22
+ through the ordered rite-\* arc:
23
+ `frame → spec → temper → define → plan → vet → build → converge → prove → polish → review → seal → ship → done`.
24
+ Completeness is **phase-relative and additive**: the typed phase registry maps
25
+ each phase to the sections that must have real content to leave it; a section
26
+ not yet required never blocks. `SchemaVersion = 1`; a feature may declare its
27
+ own and the engine refuses anything newer than it understands. Files evolve
28
+ additively.
29
+
30
+ ## Alternatives considered
31
+
32
+ | Option | Why not |
33
+ |--------|---------|
34
+ | One `feature.md` mega-document | Completeness isn't self-evident; every read pays for the whole file. |
35
+ | All sections required in every phase | Blocks framing/spec phases on proof/tasks that legitimately don't exist yet. |
36
+ | Status inferred from git / external tracker | Couples state to a tool outside the workspace; breaks the git-diffable, self-contained record. |
37
+
38
+ ## Consequences
39
+
40
+ - Completeness is a table lookup, not a judgment call — cheap and reproducible.
41
+ - Small files stay context-cheap and make "what's missing" self-evident.
42
+ - `SchemaVersion = 1` is young; migration is single-version. Hardening the
43
+ writer into one pure transition function is a recorded follow-up
44
+ (`docs/research/gsd-core-adoption.md` §3.2).
45
+ - The typed registry in `engine/internal/state/schema.go` is the lifecycle
46
+ authority. Its invariant tests lock order, aliases, commands, requirements,
47
+ and cross-format manifest freshness.
@@ -0,0 +1,39 @@
1
+ # ADR-0005: Hooks are engine subcommands, not shell scripts
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-07-08 (backfilled; see commits porting `reviewer-readonly`,
5
+ `subagent-orient`, and the guard hooks into the Go engine)
6
+
7
+ ## Context
8
+
9
+ Lifecycle hooks (orient on session start, readonly-guard for reviewers,
10
+ stop-gate, statusline, redwatch, …) began as standalone `pack/.claude/hooks/*.sh`
11
+ scripts. Shell hooks drift from the engine's own state logic, are hard to test
12
+ in isolation, behave differently across the two hosts, and duplicate parsing the
13
+ engine already does.
14
+
15
+ ## Decision
16
+
17
+ Hooks are **subcommands of the one Go binary**: `devrites-engine hook <id>`.
18
+ The pack ships only `hooks.json` wiring plus host settings; every hook's logic
19
+ lives in the engine, sharing the `orient`/`gate`/`state` core. A control plane
20
+ selects which hooks fire: `DEVRITES_HOOK_PROFILE` (minimal / standard / strict)
21
+ and `DEVRITES_DISABLED_HOOKS`. Each hook has a golden parity test
22
+ (`tests/parity_*_test.go`) pinning its stdout + exit across both hosts.
23
+
24
+ ## Alternatives considered
25
+
26
+ | Option | Why not |
27
+ |--------|---------|
28
+ | Keep hooks as `.sh` scripts | Drift from engine state logic, per-host divergence, poor testability, duplicated parsing. |
29
+ | One monolithic hook entry point | Loses per-hook enable/disable and per-hook golden tests. |
30
+ | Node hook runtime | Reintroduces a runtime dependency ADR-0001 deliberately avoids. |
31
+
32
+ ## Consequences
33
+
34
+ - Hooks are unit-testable Go with golden parity snapshots, not shell fixtures.
35
+ - One implementation serves both hosts; the harness (ADR-0002) handles edge
36
+ translation.
37
+ - Profiles make the hook surface tunable without editing wiring.
38
+ - The pack's `hooks/*.sh` files are removed; `hooks.json` is the only pack-side
39
+ hook artifact.
@@ -0,0 +1,50 @@
1
+ # ADR-0006: Clock seam + Go static-analysis CI gates
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-07-08
5
+
6
+ ## Context
7
+
8
+ Two gaps surfaced while studying a more mature peer system (GSD Core; see
9
+ `docs/research/gsd-core-adoption.md`):
10
+
11
+ 1. **Unwired static analysis.** `engine/Makefile` defined `staticcheck` and
12
+ `govulncheck` targets, but CI ran only `gofmt` + `go vet`. No `-race`, no
13
+ custom analysis on the trust-root binary.
14
+ 2. **A wall-clock leak.** `resolve next-qid` derived today's date from a raw
15
+ `time.Now()` with no seam, so its golden snapshot was pinned to the date it
16
+ was recorded and failed **every other day** — a latent red the peer system's
17
+ clock-seam lint would have caught at author time.
18
+
19
+ ## Decision
20
+
21
+ - **Clock seam.** Wall-clock reads in the resolve command flow through one
22
+ overridable point, `clockNow()`, honoring `DEVRITES_NOW` (RFC-3339 or bare
23
+ `YYYY-MM-DD`). Date-derived output is deterministic under test; goldens pin the
24
+ clock instead of tracking the real date.
25
+ - **Engine CI gates.** The `engine` CI job installs pinned `staticcheck`
26
+ (2025.1.1) + `govulncheck` and runs both as **blocking** steps, and runs the
27
+ suite with `-race`. `make quality` mirrors this so a green local gate means a
28
+ green pipeline.
29
+ - **Coverage** is measured (`make cover`) but **not** yet a hard floor: the
30
+ number is understated because most behaviour is exercised through CLI-level
31
+ integration tests in `tests/` that don't attribute to per-package coverage.
32
+ A ratchet-only floor is a follow-up once attribution is meaningful.
33
+
34
+ ## Alternatives considered
35
+
36
+ | Option | Why not |
37
+ |--------|---------|
38
+ | Regenerate the date golden and move on | Fixes it for one day; the test rots again at the next date boundary. The seam fixes the class. |
39
+ | Introduce `golangci-lint` | New dependency + config surface; `staticcheck` + `govulncheck` were already defined in the Makefile — wire what exists. |
40
+ | Inject a full `Clock` interface everywhere | Heavier than the one failing path needs; the env seam is the minimal correct fix. A shared clock package is a Proposed generalization. |
41
+ | Hard coverage floor now | Misleading at ~23% aggregate due to integration-test attribution; a floor here would gate on noise. |
42
+
43
+ ## Consequences
44
+
45
+ - The engine suite is deterministic across dates and race-checked; static
46
+ analysis and CVE scanning block on the trust-root binary.
47
+ - `DEVRITES_NOW` is a supported test seam; other date-deriving commands
48
+ (`learnings`, `conventions`, `footprint`, `stuck`) still read `time.Now()`
49
+ directly and can adopt the same seam when they need deterministic output.
50
+ - Guard test `tests/adr_0006_clock_seam_test.go` locks the seam behaviour.
@@ -0,0 +1,36 @@
1
+ # ADR-0007: Canonical live workspace filenames
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-07-20
5
+
6
+ ## Context
7
+
8
+ ADR-0004 established phase-relative `proof` and `status` sections while the
9
+ live workspace later standardized its human-facing artifacts on `README.md`,
10
+ `state.md`, and `evidence.md`. Shipped skills, validators, the typed workflow
11
+ registry, and user documentation already write those names, but migration and
12
+ some engine comments still normalized in the opposite direction.
13
+
14
+ ## Decision
15
+
16
+ Use `README.md`, `state.md`, and `evidence.md` as the canonical live workspace
17
+ map, cursor, and proof log. Continue reading `feature.md`/`index.md`, `status.md`,
18
+ and `proof.md` as compatibility aliases. `devrites-engine migrate` adds missing
19
+ canonical files from aliases without deleting or overwriting either form.
20
+ Internal `proof` and `status` section identifiers remain conceptual completeness
21
+ names, not canonical filename declarations.
22
+
23
+ ## Alternatives considered
24
+
25
+ | Option | Why not |
26
+ |--------|---------|
27
+ | Restore `feature.md`, `status.md`, and `proof.md` as canonical | Would reverse the shipped workspace contract and require coordinated changes across skills, validators, docs, fixtures, and generated hosts. |
28
+ | Treat both directions as equally canonical | Makes migration non-idempotent and leaves writers without one preferred target. |
29
+ | Delete aliases after migration | Risks data loss and breaks existing workspaces and older installed packs. |
30
+
31
+ ## Consequences
32
+
33
+ - Migration direction matches the files produced and required by the live pack.
34
+ - Existing aliases remain losslessly readable and are preserved on disk.
35
+ - Schema version remains `1`; this is an additive filename normalization, not a
36
+ content-schema break.
@@ -0,0 +1,33 @@
1
+ # ADR-0008: Sanctioned engine network boundary
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-07-20
5
+
6
+ ## Context
7
+
8
+ ADR-0001 described the Go control plane as network-free. The binary now also
9
+ owns explicit installation/update and source-cache operations that require HTTP,
10
+ while deterministic workspace bookkeeping still must not depend on network or
11
+ model responses. The implemented boundary already isolates HTTP in one package.
12
+
13
+ ## Decision
14
+
15
+ Keep deterministic workspace state, gate, hook, migration, and derivation logic
16
+ network- and model-free. Permit network access only in `internal/iohooks` for
17
+ explicit updater and source-cache operations. No other first-party package may
18
+ import network clients, and no engine package may call a model API.
19
+
20
+ ## Alternatives considered
21
+
22
+ | Option | Why not |
23
+ |--------|---------|
24
+ | Forbid all network access in the binary | Would remove the verified updater and source-cache refresh behavior users already rely on. |
25
+ | Allow each consumer its own HTTP client | Expands the audit surface and weakens the executable package boundary. |
26
+ | Ship a second updater binary | Adds packaging, release, and cross-platform complexity without improving the existing package isolation. |
27
+
28
+ ## Consequences
29
+
30
+ - Workspace verdicts remain deterministic and offline-capable.
31
+ - Network behavior has one auditable package and one guard test.
32
+ - The binary as a whole is not network-free; documentation must distinguish the
33
+ control-plane core from explicit I/O commands.
@@ -0,0 +1,58 @@
1
+ # Architecture Decision Records
2
+
3
+ An ADR captures **one** load-bearing decision: the context that forced it, the
4
+ decision itself, the alternatives that were rejected and *why*, and the
5
+ consequences accepted. The rejected-alternatives table is the point — it keeps
6
+ the "why not X" from being re-litigated every quarter.
7
+
8
+ `CLAUDE.md` points every agent here (`CONTEXT.md` + `docs/adr/` are the
9
+ single-context domain record). Keep this directory the source of truth for
10
+ architecture; per-feature `decisions.md` files stay scoped to that feature.
11
+
12
+ ## Convention
13
+
14
+ - Filename: `NNNN-kebab-title.md`, zero-padded, monotonic.
15
+ - Frontmatter fields: **Status** (Proposed / Accepted / Superseded by NNNN),
16
+ **Date** (YYYY-MM-DD), **Deciders** (optional).
17
+ - Sections: **Context** → **Decision** → **Alternatives considered** (a table:
18
+ option · why rejected) → **Consequences**.
19
+ - **Guard test:** an accepted ADR that asserts a runtime invariant SHOULD have a
20
+ named regression test — `engine/tests/adr_NNNN_*_test.go` — so the decision
21
+ has an executable proof it still holds. Reference the ADR number in the test's
22
+ doc comment.
23
+
24
+ ## Template
25
+
26
+ ```markdown
27
+ # ADR-NNNN: <title>
28
+
29
+ - **Status:** Accepted
30
+ - **Date:** YYYY-MM-DD
31
+
32
+ ## Context
33
+ <the forces: what problem, what constraints, what was true at the time>
34
+
35
+ ## Decision
36
+ <what we chose, stated as a present-tense rule>
37
+
38
+ ## Alternatives considered
39
+ | Option | Why not |
40
+ |--------|---------|
41
+ | ... | ... |
42
+
43
+ ## Consequences
44
+ <what this makes easy, what it costs, what follow-up it implies>
45
+ ```
46
+
47
+ ## Index
48
+
49
+ | ADR | Title | Status | Guard test |
50
+ |-----|-------|--------|-----------|
51
+ | [0001](0001-go-engine-as-control-plane.md) | Go engine as deterministic control plane | Accepted | — |
52
+ | [0002](0002-dual-host-harness.md) | Dual-host harness (Claude + Codex) | Accepted | `tests/parity_*_test.go` |
53
+ | [0003](0003-gate-model-hitl-pause.md) | Gates block as HITL pause, never crash | Accepted | `tests/adr_0003_gate_exit_code_test.go` |
54
+ | [0004](0004-state-schema-phases-sections.md) | Phase-relative section completeness | Accepted | `tests/adr_0004_required_by_phase_test.go` |
55
+ | [0005](0005-hooks-as-engine-subcommands.md) | Hooks are engine subcommands, not shell scripts | Accepted | `tests/parity_*_test.go` |
56
+ | [0006](0006-clock-seam-and-engine-ci-gates.md) | Clock seam + Go static-analysis CI gates | Accepted | `tests/adr_0006_clock_seam_test.go` |
57
+ | [0007](0007-canonical-live-workspace-filenames.md) | Canonical live workspace filenames | Accepted | `internal/migrate/migrate_test.go`, `tests/migrate_cli_test.go` |
58
+ | [0008](0008-sanctioned-engine-network-boundary.md) | Sanctioned engine network boundary | Accepted | `tests/meta_test.go` |
@@ -167,7 +167,7 @@ when available, falling back to file reads otherwise:
167
167
  See [`flow.md`](flow.md) for the Mermaid diagrams. The text path:
168
168
 
169
169
  ```
170
- /rite-spec → /rite-define → /rite-build ×N → /rite-prove → /rite-polish → /rite-review → /rite-seal → /rite-ship
170
+ /rite-frame → /rite-spec → /rite-temper → /rite-define → /rite-vet → /rite-build ×N → /rite-converge → /rite-prove → /rite-polish → /rite-review → /rite-seal → /rite-ship
171
171
  │ │ │ ▲ │ │ (decide) (execute+close)
172
172
  │ │ │ └ Spec Drift Guard → /rite-plan repair ────┘
173
173
  │ │ └ devrites-frontend-craft / source-driven / doubt
@@ -54,9 +54,10 @@ Backward compatibility: `.devrites/features/<slug>/` remains readable as a legac
54
54
  workspace location. `feature.md` / `index.md` may stand in for `README.md`, and
55
55
  `proof.md` may stand in for `evidence.md`.
56
56
 
57
- ### `feature.md`
57
+ ### Workspace maps
58
58
 
59
- The per-feature index. Its YAML frontmatter carries:
59
+ The canonical per-feature index is `README.md`; `feature.md` and `index.md` are
60
+ readable aliases. A map may carry YAML frontmatter with:
60
61
 
61
62
  | field | meaning |
62
63
  | --------------- | ---------------------------------------------- |
@@ -65,8 +66,9 @@ The per-feature index. Its YAML frontmatter carries:
65
66
  | `phase` | current workflow phase (see below) |
66
67
  | `schemaVersion` | schema version the file was written against |
67
68
 
68
- A feature exists iff its `feature.md` exists. A `feature.md` with no `phase`, or
69
- an unknown `phase`, is an error.
69
+ A feature exists when it has either a live `state.md` ledger or a workspace map.
70
+ The mutable `state.md` cursor is authoritative when both declare a phase; an
71
+ unknown declared phase is an error.
70
72
 
71
73
  ## Sections
72
74
 
@@ -91,16 +93,18 @@ requires only the sections needed to leave it, and the set grows additively down
91
93
  the arc. A section that is not yet required (e.g. `proof` during the `spec`
92
94
  phase) never blocks.
93
95
 
94
- | phase | required sections |
95
- | ------- | ----------------------------------------------------- |
96
- | `frame` | *(none)* |
97
- | `spec` | `spec` |
98
- | `plan` | `spec`, `plan` |
99
- | `build` | `spec`, `plan`, `decisions`, `tasks` |
100
- | `prove` | `spec`, `plan`, `decisions`, `tasks`, `proof` |
101
- | `vet` | `spec`, `plan`, `decisions`, `tasks`, `proof` |
102
- | `seal` | `spec`, `plan`, `decisions`, `tasks`, `proof`, `status` |
103
- | `ship` | `spec`, `plan`, `decisions`, `tasks`, `proof`, `status` |
96
+ | phase | required sections |
97
+ | --- | --- |
98
+ | `frame` | *(none)* |
99
+ | `spec`, `temper` | `spec` |
100
+ | `define`, `plan` | `spec`, `plan` |
101
+ | `vet`, `build`, `converge` | `spec`, `plan`, `decisions`, `tasks` |
102
+ | `prove`, `polish`, `review` | `spec`, `plan`, `decisions`, `tasks`, `proof` |
103
+ | `seal`, `ship`, `done` | `spec`, `plan`, `decisions`, `tasks`, `proof`, `status` |
104
+
105
+ The authoritative typed definitions live in `engine/internal/state/schema.go`.
106
+ `workflow_manifest.json` is a generated derivative for non-Go release tools;
107
+ run `go generate ./internal/state` after editing the registry.
104
108
 
105
109
  ## `devrites-engine status <slug>`
106
110
 
package/docs/flow.md CHANGED
@@ -270,7 +270,7 @@ erDiagram
270
270
  string slug PK ".devrites/work/<slug>/"
271
271
  }
272
272
  state {
273
- string phase "spec | plan | build | prove | polish | review | seal | ship | done"
273
+ string phase "frame | spec | temper | define | plan | vet | build | converge | prove | polish | review | seal | ship | done"
274
274
  string status "running | awaiting_human | blocked | done"
275
275
  string active_slice "N — name"
276
276
  int afk_slices_remaining "from .devrites/AFK max_slices on first AFK build"