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.
- package/CHANGELOG.md +13 -0
- package/README.md +1 -1
- package/docs/adr/0001-go-engine-as-control-plane.md +43 -0
- package/docs/adr/0002-dual-host-harness.md +34 -0
- package/docs/adr/0003-gate-model-hitl-pause.md +38 -0
- package/docs/adr/0004-state-schema-phases-sections.md +47 -0
- package/docs/adr/0005-hooks-as-engine-subcommands.md +39 -0
- package/docs/adr/0006-clock-seam-and-engine-ci-gates.md +50 -0
- package/docs/adr/0007-canonical-live-workspace-filenames.md +36 -0
- package/docs/adr/0008-sanctioned-engine-network-boundary.md +33 -0
- package/docs/adr/README.md +58 -0
- package/docs/command-map.md +1 -1
- package/docs/engine/state-schema.md +18 -14
- package/docs/flow.md +1 -1
- package/docs/research/go-authoritative-workflow-schema-and-quality-2026-07-20.md +212 -0
- package/engine/hooks_workspace.go +7 -7
- package/engine/internal/gate/gate.go +4 -4
- package/engine/internal/gate/gate_test.go +2 -2
- package/engine/internal/lib/cursor_compat_test.go +29 -0
- package/engine/internal/lib/preamble.go +1 -1
- package/engine/internal/lib/preamble_questions_test.go +10 -0
- package/engine/internal/lib/progress.go +59 -20
- package/engine/internal/lib/resolve.go +15 -6
- package/engine/internal/lib/resolve_remediation_test.go +9 -0
- package/engine/internal/lib/tickafk.go +2 -2
- package/engine/internal/migrate/migrate.go +18 -44
- package/engine/internal/migrate/migrate_test.go +33 -5
- package/engine/internal/state/cmd/workflowmanifest/main.go +54 -0
- package/engine/internal/state/cursor.go +42 -7
- package/engine/internal/state/feature.go +29 -41
- package/engine/internal/state/schema.go +155 -28
- package/engine/internal/state/snapshot.go +49 -3
- package/engine/internal/state/state_test.go +77 -6
- package/engine/internal/state/workflow_manifest.json +310 -0
- package/engine/internal/workflow/commands.go +0 -36
- package/engine/internal/workflow/commands_test.go +0 -17
- package/engine/testdata/golden/TestParityProgress/arg=allbuilt.golden +1 -1
- package/engine/testdata/golden/TestParityProgress/arg=done.golden +1 -1
- package/engine/testdata/golden/TestParityProgress/arg=mid.golden +1 -1
- package/engine/testdata/golden/TestParityProgress/arg=nophase.golden +1 -1
- package/engine/testdata/golden/TestParityProgress/arg=noslice.golden +1 -1
- package/engine/testdata/golden/TestParityProgress/arg=plan.golden +1 -1
- package/engine/testdata/golden/TestParityProgress/arg=seal.golden +1 -1
- package/engine/tests/adr_0004_required_by_phase_test.go +1 -18
- package/engine/tests/budget_test.go +2 -2
- package/engine/tests/lib_parity_test.go +1 -1
- package/engine/tests/meta_test.go +3 -3
- package/engine/tests/migrate_cli_test.go +24 -22
- package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +5 -3
- package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +5 -3
- package/pack/generated/codex/AGENTS.md +1 -1
- package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +5 -3
- package/package.json +2 -1
- package/scripts/codex-generate.sh +1 -1
- package/scripts/grade-feature.sh +5 -3
- package/scripts/run-outcome-evals.sh +21 -0
- package/scripts/validate-workflow-security.py +3 -8
- package/scripts/validate-workspace-schema.py +9 -73
- package/scripts/validate.sh +10 -0
- 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.
|
|
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` |
|
package/docs/command-map.md
CHANGED
|
@@ -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
|
-
###
|
|
57
|
+
### Workspace maps
|
|
58
58
|
|
|
59
|
-
The per-feature index.
|
|
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
|
|
69
|
-
|
|
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
|
|
95
|
-
|
|
|
96
|
-
| `frame` | *(none)*
|
|
97
|
-
| `spec`
|
|
98
|
-
| `plan`
|
|
99
|
-
| `build` | `spec`, `plan`, `decisions`, `tasks`
|
|
100
|
-
| `prove` | `spec`, `plan`, `decisions`, `tasks`, `proof`
|
|
101
|
-
| `
|
|
102
|
-
|
|
103
|
-
|
|
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"
|