devrites 3.0.3 → 3.0.5

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 (59) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +55 -43
  3. package/SECURITY.md +72 -58
  4. package/docs/adr/0001-go-engine-as-control-plane.md +43 -0
  5. package/docs/adr/0002-dual-host-harness.md +34 -0
  6. package/docs/adr/0003-gate-model-hitl-pause.md +38 -0
  7. package/docs/adr/0004-state-schema-phases-sections.md +6 -3
  8. package/docs/adr/0005-hooks-as-engine-subcommands.md +39 -0
  9. package/docs/adr/0006-clock-seam-and-engine-ci-gates.md +50 -0
  10. package/docs/adr/0007-canonical-live-workspace-filenames.md +36 -0
  11. package/docs/adr/0008-sanctioned-engine-network-boundary.md +33 -0
  12. package/docs/adr/README.md +58 -0
  13. package/docs/agents/issue-driven-rites.md +5 -5
  14. package/docs/architecture.md +61 -45
  15. package/docs/capability-surface-selection.md +3 -1
  16. package/docs/cli.md +9 -2
  17. package/docs/command-map.md +6 -2
  18. package/docs/engine/agent-contract.md +5 -3
  19. package/docs/engine/commands.md +27 -14
  20. package/docs/engine/state-schema.md +14 -9
  21. package/docs/engine/workspace-schema.md +5 -4
  22. package/docs/flow.md +18 -7
  23. package/docs/porting-to-a-new-harness.md +6 -2
  24. package/docs/release.md +10 -9
  25. package/docs/skills.md +1 -1
  26. package/docs/templates/CRITIC_REVIEW_PACKET_TEMPLATE.md +35 -0
  27. package/docs/usage.md +26 -16
  28. package/engine/internal/lib/packageexistence.go +729 -52
  29. package/engine/internal/lib/packageexistence_test.go +343 -0
  30. package/engine/internal/lib/util.go +1 -1
  31. package/engine/internal/migrate/migrate.go +16 -11
  32. package/engine/internal/migrate/migrate_test.go +26 -4
  33. package/engine/internal/state/feature.go +28 -14
  34. package/engine/internal/state/schema.go +20 -8
  35. package/engine/internal/state/state_test.go +6 -6
  36. package/engine/tests/budget_test.go +2 -2
  37. package/engine/tests/meta_test.go +3 -3
  38. package/engine/tests/migrate_cli_test.go +24 -22
  39. package/pack/.claude/skills/devrites-lib/SKILL.md +7 -9
  40. package/pack/.claude/skills/devrites-lib/reference/reply-contract.md +11 -3
  41. package/pack/.claude/skills/devrites-lib/reference/standards/development-workflow.md +2 -3
  42. package/pack/.claude/skills/rite/SKILL.md +6 -7
  43. package/pack/.claude/skills/rite/reference/menu.md +5 -5
  44. package/pack/.claude/skills/rite-adopt/SKILL.md +2 -3
  45. package/pack/generated/claude/skills/devrites-lib/SKILL.md +7 -9
  46. package/pack/generated/claude/skills/devrites-lib/reference/reply-contract.md +11 -3
  47. package/pack/generated/claude/skills/devrites-lib/reference/standards/development-workflow.md +2 -3
  48. package/pack/generated/claude/skills/rite/SKILL.md +6 -7
  49. package/pack/generated/claude/skills/rite/reference/menu.md +5 -5
  50. package/pack/generated/claude/skills/rite-adopt/SKILL.md +2 -3
  51. package/pack/generated/codex/skills/devrites-lib/SKILL.md +7 -9
  52. package/pack/generated/codex/skills/devrites-lib/reference/reply-contract.md +11 -3
  53. package/pack/generated/codex/skills/devrites-lib/reference/standards/development-workflow.md +2 -3
  54. package/pack/generated/codex/skills/rite/SKILL.md +6 -7
  55. package/pack/generated/codex/skills/rite/reference/menu.md +5 -5
  56. package/pack/generated/codex/skills/rite-adopt/SKILL.md +2 -3
  57. package/package.json +2 -1
  58. package/scripts/skills-inventory.mjs +18 -0
  59. package/scripts/validate-workflow-security.py +3 -8
package/CHANGELOG.md CHANGED
@@ -2,6 +2,37 @@
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.5](https://github.com/ViktorsBaikers/DevRites/compare/v3.0.4...v3.0.5) (2026-07-21)
6
+
7
+ ### Fixed
8
+
9
+ * **deps:** update fast-uri ([1e14101](https://github.com/ViktorsBaikers/DevRites/commit/1e14101284496277f56d4560d5a59d87297f7daf))
10
+ * **devrites:** normalize Git root centrally ([a89ec40](https://github.com/ViktorsBaikers/DevRites/commit/a89ec408b6133629db3547dcb7960f29bec6a723))
11
+ * **devrites:** normalize Git root path ([38dccf0](https://github.com/ViktorsBaikers/DevRites/commit/38dccf0bac0bdf58f5fdcf171cac231c296af171))
12
+ * **devrites:** resolve packages by source ([ae21d9b](https://github.com/ViktorsBaikers/DevRites/commit/ae21d9b50b0b631fb4352e5820f1176213614b78))
13
+ * **release:** reconnect v3.0.4 lineage ([7b6f853](https://github.com/ViktorsBaikers/DevRites/commit/7b6f853a73bcd3bc6ea72fd4b6b10c024c69a468))
14
+ * **skills:** format human gate decisions clearly ([0781d99](https://github.com/ViktorsBaikers/DevRites/commit/0781d99ce081f76f5e69237396e99e78e1b027f9))
15
+
16
+ ### Documentation
17
+
18
+ * **repo:** sync current behavior ([9555fbb](https://github.com/ViktorsBaikers/DevRites/commit/9555fbbe26ce896a5c99723e46a8c04b7fba06f4))
19
+
20
+ ## [3.0.4](https://github.com/ViktorsBaikers/DevRites/compare/v3.0.3...v3.0.4) (2026-07-21)
21
+
22
+ ### Fixed
23
+
24
+ * **ci:** harden supply chain checks ([d902574](https://github.com/ViktorsBaikers/DevRites/commit/d902574a7d30168fcef94aa4a3dae7707191fe8d))
25
+ * **deps:** update fast-uri ([1e14101](https://github.com/ViktorsBaikers/DevRites/commit/1e14101284496277f56d4560d5a59d87297f7daf))
26
+ * **devrites:** normalize canonical workspace files ([e70221f](https://github.com/ViktorsBaikers/DevRites/commit/e70221f5dd9fbda0f3a73c500a493497bc023a91))
27
+ * **devrites:** normalize Git root centrally ([a89ec40](https://github.com/ViktorsBaikers/DevRites/commit/a89ec408b6133629db3547dcb7960f29bec6a723))
28
+ * **devrites:** normalize Git root path ([38dccf0](https://github.com/ViktorsBaikers/DevRites/commit/38dccf0bac0bdf58f5fdcf171cac231c296af171))
29
+ * **devrites:** resolve packages by source ([ae21d9b](https://github.com/ViktorsBaikers/DevRites/commit/ae21d9b50b0b631fb4352e5820f1176213614b78))
30
+ * **skills:** format human gate decisions clearly ([0781d99](https://github.com/ViktorsBaikers/DevRites/commit/0781d99ce081f76f5e69237396e99e78e1b027f9))
31
+
32
+ ### Documentation
33
+
34
+ * **repo:** sync current behavior ([9555fbb](https://github.com/ViktorsBaikers/DevRites/commit/9555fbbe26ce896a5c99723e46a8c04b7fba06f4))
35
+
5
36
  ## [3.0.3](https://github.com/ViktorsBaikers/DevRites/compare/v3.0.2...v3.0.3) (2026-07-20)
6
37
 
7
38
  ### Fixed
package/README.md CHANGED
@@ -67,9 +67,9 @@ memory). Both hit the same skill — `/rite spec foo` ≡ `/rite-spec foo`.
67
67
  | # | Phase | Menu form | Direct shortcut | Does |
68
68
  |---|---|---|---|---|
69
69
  | 1 | SPEC | `/rite spec` | [`/rite-spec`](pack/.claude/skills/rite-spec/SKILL.md) | investigate + write spec.md |
70
- | — | TEMPER | `/rite temper` | [`/rite-temper`](pack/.claude/skills/rite-temper/SKILL.md) | _optional, big features_ — strategic review: scope mode + pre-mortem, hardens the spec (mandatory in autocomplete) |
70
+ | — | TEMPER | `/rite temper` | [`/rite-temper`](pack/.claude/skills/rite-temper/SKILL.md) | _optional, big features_ — strategic review: scope mode + pre-mortem, hardens the spec (always run by autocomplete) |
71
71
  | 2 | PLAN | `/rite define` | [`/rite-define`](pack/.claude/skills/rite-define/SKILL.md) | spec → plan + slices (each tagged AFK \| HITL + gate) |
72
- | — | VET | `/rite vet` | [`/rite-vet`](pack/.claude/skills/rite-vet/SKILL.md) | _recommended, every feature_ — engineering plan review: scope · architecture · tests · perf, hardens the plan + writes `test-plan.md`; depth scales to stakes, never skipped (always in autocomplete) |
72
+ | — | VET | `/rite vet` | [`/rite-vet`](pack/.claude/skills/rite-vet/SKILL.md) | _mandatory, every plan_ — engineering review: scope · architecture · tests · perf, hardens the plan + writes `test-plan.md`; depth scales from light to full |
73
73
  | 3 | BUILD ×N | `/rite build` | [`/rite-build`](pack/.claude/skills/rite-build/SKILL.md) | one slice, then stop (HITL slices pause pre-code) |
74
74
  | — | CONVERGE | `/rite converge` | [`/rite-converge`](pack/.claude/skills/rite-converge/SKILL.md) | _recovery_ — assess live code vs intent, append the remaining work as new slices (resumed / adopted / stalled feature) |
75
75
  | 4 | PROVE | `/rite prove` | [`/rite-prove`](pack/.claude/skills/rite-prove/SKILL.md) | tests + browser proof |
@@ -95,27 +95,27 @@ before resuming.
95
95
 
96
96
  ```mermaid
97
97
  flowchart LR
98
- S[/rite-spec/] --> D[/rite-define/] --> B[/rite-build ×N/] --> P[/rite-prove/] --> Po[/rite-polish/] --> R[/rite-review/] --> Sl[/rite-seal/]
98
+ S[/rite-spec/] --> D[/rite-define/] --> V[/rite-vet/] --> B[/rite-build ×N/] --> P[/rite-prove/] --> Po[/rite-polish/] --> R[/rite-review/] --> Sl[/rite-seal/]
99
99
  S -.->|big feature| T[/rite-temper/] -.-> D
100
- D -.->|every feature| V[/rite-vet/] -.-> B
101
100
  Sl -->|GO| Sh[/rite-ship/]
102
101
  Sh -->|type-GO| Ship([ship: commit · push · tag])
102
+ B -.->|resumed · adopted · stalled| C[/rite-converge/] -.-> B
103
103
  B -.->|Spec Drift Guard| Re[/rite-plan repair/]
104
104
  Re --> B
105
105
 
106
106
  classDef phase fill:#1f2937,stroke:#60a5fa,color:#f9fafb
107
107
  classDef ship fill:#064e3b,stroke:#34d399,color:#ecfdf5
108
108
  classDef repair fill:#4c1d95,stroke:#a78bfa,color:#f5f3ff
109
- class S,D,B,P,Po,R,Sl,Sh,T phase
109
+ class S,D,V,B,P,Po,R,Sl,Sh,T phase
110
110
  class Ship ship
111
- class Re repair
111
+ class C,Re repair
112
112
  ```
113
113
 
114
114
  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.3`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v3.0.3) — see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
118
+ **Status:** [`v3.0.5`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v3.0.5) — see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
119
119
 
120
120
  ## Contents
121
121
 
@@ -151,17 +151,19 @@ specialists (`devrites-*`) that fire on triggers.
151
151
  **Naming:** the `devrites-` prefix is a **namespace** for collision avoidance against
152
152
  bundled Claude Code skill names (`prototype`, `handoff`, `triage`, `diagnose`, …) —
153
153
  it does not signal "internal." Visibility is governed by each skill's
154
- `user-invocable:` flag, not by the prefix. See
154
+ `user-invocable:` flag, while `disable-model-invocation` independently controls
155
+ automatic loading. See
155
156
  [`docs/flow.md` § Public vs internal namespace](docs/flow.md#8-public-vs-internal-namespace).
156
157
 
157
158
  Full rationale: [`docs/architecture.md`](docs/architecture.md).
158
159
 
159
160
  ## Install
160
161
 
161
- DevRites installs **into a project** (project-local only — it never writes to
162
- `~/.claude` or `~/.codex`). Install with `npx` (recommended) or the `curl | bash`
163
- one-liner both run the same installer and ship Claude Code skills, Codex skills,
164
- agents, **rules**, and aliases.
162
+ DevRites installs its host artifacts **into a project** — it never writes skills,
163
+ agents, or hooks to `~/.claude` or `~/.codex`. Install with `npx` (recommended)
164
+ or the `curl | bash` bootstrap. Both delegate to the same engine-owned install
165
+ semantics and ship Claude Code/Codex skills, agents, standards, hooks, and aliases;
166
+ the optional shared engine binary is the only global artifact.
165
167
 
166
168
  ### Installing
167
169
 
@@ -180,11 +182,14 @@ npx devrites@latest update
180
182
  npx devrites@latest uninstall
181
183
  ```
182
184
 
183
- `npx devrites` is a thin wrapper over the same installer below — the pack is bundled in the
184
- package, so the install runs **offline** and is **pinned** to the version you request
185
- (`@latest`, `@1.18.0`, ). It accepts every flag the bash installer does and is still
186
- project-local (it never writes to `~/.claude` or `~/.codex`). Requires `bash` built in on macOS/Linux;
187
- on Windows run it inside Git Bash or WSL, or use the `curl | bash` one-liner below.
185
+ `npx devrites` is a native Node 18+ shim over the engine-owned installer. The host
186
+ payload is bundled and pinned to the package version you request (`@latest` or
187
+ an exact published version). To launch the engine, the shim first tries the matching checksummed
188
+ release binary, then a local Go build, then an existing `devrites-engine`. It does
189
+ not invoke `install.sh` and does not require Bash. Installed Claude/Codex artifacts
190
+ stay in the target project; unless `--no-binary` is set, the installer may also
191
+ place the shared engine binary in the configured user/system bin directory.
192
+ Prebuilt binaries ship for macOS arm64/amd64, Linux arm64/amd64, and Windows amd64.
188
193
 
189
194
  **One-liner over the network** — no `git clone` or Node required:
190
195
 
@@ -199,7 +204,7 @@ curl -fsSL https://raw.githubusercontent.com/ViktorsBaikers/DevRites/main/instal
199
204
  curl -fsSL https://raw.githubusercontent.com/ViktorsBaikers/DevRites/main/install.sh | bash -s -- --dry-run
200
205
 
201
206
  # Pin to a specific release
202
- curl -fsSL https://raw.githubusercontent.com/ViktorsBaikers/DevRites/main/install.sh | DEVRITES_REF=v0.1.0 bash
207
+ curl -fsSL https://raw.githubusercontent.com/ViktorsBaikers/DevRites/main/install.sh | DEVRITES_REF=vX.Y.Z bash
203
208
  ```
204
209
 
205
210
  The script is self-bootstrapping: when piped through `bash` it auto-downloads the latest
@@ -261,16 +266,16 @@ From a local checkout:
261
266
  ./update.sh # upgrade install in current directory
262
267
  ./update.sh --target /path/to/proj # upgrade install elsewhere
263
268
  ./update.sh --check # report installed vs latest, change nothing
264
- ./update.sh --to v0.2.0 # pin to a specific tag
269
+ ./update.sh --to vX.Y.Z # pin to a specific release tag
265
270
  ./update.sh --pre # allow pre-release tags
266
271
  ./update.sh --force # reinstall even when already current
267
272
  ```
268
273
 
269
- `update.sh` reads the installed version + original flags from
270
- `.claude/devrites.manifest`, asks the GitHub API for the latest release tag,
271
- downloads the release tarball, and re-runs the bundled `install.sh` with the
272
- same flags + `--force`. `.devrites/` (active feature, work) is preserved
273
- because the installer only touches manifest-tracked paths.
274
+ `update.sh` resolves the requested/latest release during bootstrap, acquires its
275
+ bundle and engine, then delegates to `devrites-engine update`. The engine replays
276
+ the original flags from `.claude/devrites.manifest` with force semantics.
277
+ `.devrites/` (active feature and work) is preserved because update only manages
278
+ the installed artifact set.
274
279
 
275
280
  ### Uninstalling
276
281
 
@@ -315,7 +320,7 @@ the npm `devrites` shim owns install/update/uninstall and proxies engine subcomm
315
320
  authoritative. Workspace-operating lifecycle skills read `core.md` in step 0 and disclose
316
321
  phase rules on demand; compact utilities keep their narrower contract local.
317
322
 
318
- **Claude Code invocation.** Every user-invocable skill responds to **both** `/rite <verb>` (menu form — type `/rite` to discover) and `/rite-<verb>` (direct shortcut — muscle memory). The forms are equivalent: `/rite build slice-2` ≡ `/rite-build slice-2`. Use whichever reads more naturally. Installation merges DevRites event hooks into an existing `.claude/settings.json` without replacing user entries; an existing non-DevRites `statusLine` is preserved with a warning because Claude exposes one status-line slot.
323
+ **Claude Code invocation.** Every public `rite-*` workflow responds to **both** `/rite <verb>` (through the `rite` menu/router) and `/rite-<verb>` (direct shortcut). The forms are equivalent: `/rite build slice-2` ≡ `/rite-build slice-2`. Use whichever reads more naturally. Installation merges DevRites event hooks into an existing `.claude/settings.json` without replacing user entries; an existing non-DevRites `statusLine` is preserved with a warning because Claude exposes one status-line slot.
319
324
 
320
325
  **Codex invocation.** The installer mirrors the same skills to `.agents/skills/`, mirrors DevRites rules to `.agents/skills/devrites-lib/reference/standards/`, injects a Codex compatibility block after each skill's front matter, generates project custom agents in `.codex/agents/`, installs Codex hooks in `.codex/hooks.json`, and creates or merges the needed Codex guidance into `AGENTS.md`. If `AGENTS.md` already exists, DevRites adds a marked block instead of replacing your guidance. In Codex, invoke DevRites via `$rite`, `$rite-spec`, or `/skills`; if you prefer a Claude-only footprint, install with `--no-codex`. Codex must trust the project `.codex/` layer and review the hooks via `/hooks` before non-managed hooks run.
321
326
 
@@ -337,16 +342,17 @@ Pinned aliases live at `.claude/skills/<alias>/SKILL.md` and mirror to `.agents/
337
342
 
338
343
  ### Full skill + agent inventory
339
344
 
340
- **Public `rite-*` skills (29)** — slash-command surface:
345
+ **Public command skills (30: `rite` + 29 `rite-*`)** — slash-command surface:
341
346
 
342
347
  | Group | Skills |
343
348
  |---|---|
344
- | Lifecycle (8) | `rite-spec` · `rite-define` · `rite-build` · `rite-prove` · `rite-polish` · `rite-review` · `rite-seal` · `rite-ship` |
349
+ | Core lifecycle (8) | `rite-spec` · `rite-define` · `rite-build` · `rite-prove` · `rite-polish` · `rite-review` · `rite-seal` · `rite-ship` |
345
350
  | On-ramp (optional) | `rite-adopt` — onboard an existing codebase: reverse-derive `spec.md`, seed the conventions ledger + propose project principles, then hand off to the lifecycle |
346
351
  | Strategic (optional) | `rite-temper` — strategic spec review between spec and define; mandatory in `rite-autocomplete` |
347
352
  | Engineering (every feature) | `rite-vet` — engineering plan review between define and build; depth scales to stakes, never skipped; always in `rite-autocomplete` |
348
- | Resume / replan | `rite-resolve` · `rite-plan` |
349
- | Utility | `rite-status` · `rite-doctor` · `rite-customize` · `rite-pov` · `rite-dogfood` · `rite-pr-feedback` · `rite-zoom-out` · `rite-prototype` · `rite-handoff` · `rite-pressure-test` · `rite-autocomplete` |
353
+ | Recovery / replan | `rite-resolve` · `rite-plan` · `rite-converge` |
354
+ | Express / pre-flight | `rite-quick` · `rite-frame` |
355
+ | Utility | `rite-status` · `rite-doctor` · `rite-customize` · `rite-explain` · `rite-pov` · `rite-dogfood` · `rite-pr-feedback` · `rite-zoom-out` · `rite-prototype` · `rite-handoff` · `rite-pressure-test` · `rite-autocomplete` |
350
356
  | Learning (optional) | `rite-learn` — cross-feature learning loop: mine shipped features for recurring mistakes + dismissed-finding classes, propose project-local lessons into `.devrites/learnings.md`, and promote recurring invariants to `.devrites/principles.md` |
351
357
  | Menu | `rite` |
352
358
 
@@ -445,6 +451,7 @@ drop the sentinel for the bulk stretch. Always cap iterations. Full contract:
445
451
  # start a feature
446
452
  /rite-spec add-csv-export # investigate deeply → spec.md (asks you; gathers design refs)
447
453
  /rite-define # spec → plan.md + tasks.md + state.md
454
+ /rite-vet # mandatory plan review; light or full based on stakes
448
455
 
449
456
  # build loop — one slice at a time
450
457
  /rite-build # slice 1, stops with evidence
@@ -507,7 +514,7 @@ turns the request + any references (screenshots, Figma, video) into a feature-le
507
514
  **`design-brief.md`** — design direction (color strategy · scene sentence · named anchor
508
515
  references), key states, interaction model, and an optional Figma/image **visual-direction
509
516
  probe** — and pauses for you to confirm the direction (HITL) or asserts a best guess (AFK).
510
- That brief is the **build target**, woven into spec → define → build, not a separate phase.
517
+ That brief is the **build target**, woven into spec → define → vet → build, not a separate phase.
511
518
 
512
519
  Then `devrites-frontend-craft` builds **to** the brief: detect the surface register (brand
513
520
  vs product), refine the brief per slice (all states — default / loading / empty / error /
@@ -520,7 +527,9 @@ real UI state, and **prove both layers** (contract tests + browser proof).
520
527
 
521
528
  ## Safety & scope
522
529
 
523
- - **Project-local only.** Never writes to `~/.claude` or `~/.codex`. Manifest-managed install/uninstall.
530
+ - **Project-local host artifacts.** Never writes skills, agents, or hook settings to
531
+ `~/.claude` or `~/.codex`. Install/uninstall is manifest-managed; the shared
532
+ `devrites-engine` binary is the sole optional global artifact (`--no-binary` skips it).
524
533
  - **Feature scope only.** Review/simplify/polish/security stay within the active feature
525
534
  and touched files — no project-wide refactors, no drive-by cleanup.
526
535
  - **One slice at a time.** `/rite-build` stops after a single verified slice.
@@ -533,7 +542,7 @@ real UI state, and **prove both layers** (contract tests + browser proof).
533
542
  ```
534
543
  devrites/
535
544
  bin/ # devrites.mjs — npx CLI entry point (acquires/proxies devrites-engine)
536
- .github/ # workflows/ (ci, release, dependabot-auto-merge) + dependabot.yml
545
+ .github/ # ci (including release job) · evals · commitlint · Dependabot automation
537
546
  .husky/ # commit-msg hook (Conventional Commits via commitlint)
538
547
  .releaserc.json # semantic-release config (CHANGELOG, version sync, tarball, GitHub Release)
539
548
  install.sh uninstall.sh update.sh # self-contained bundle/binary bootstrap shims
@@ -546,10 +555,9 @@ devrites/
546
555
  # (standards live inside skills/devrites-lib/reference/standards/)
547
556
  installed projects # .claude/ runtime assets; .agents/skills + .codex/agents
548
557
  # + .codex/hooks.json + AGENTS.md for Codex
549
- evals/ # trigger evals (20/skill) + golden/ outcome-eval fixtures
550
- docs/ # architecture · skills · command-map · usage · flow · release · cli
551
- internal/ # research, development notes (gitignored)
552
- tests/ # install/uninstall smoke · install fixture · pack validation
558
+ evals/ # branch-shaped routing corpora + behavioral/ + golden/ outcome fixtures
559
+ docs/ # user guides + engine/ contracts + agents/ process + adr/ + dated research/
560
+ tests/ # auto-discovered repository shell suite (install, runtime, pack, release)
553
561
  dist/ # release tarballs built by semantic-release (gitignored)
554
562
  CHANGELOG.md SECURITY.md CODE_OF_CONDUCT.md CODEOWNERS NOTICE.md LICENSE
555
563
  package.json commitlint.config.js # husky/commitlint/semantic-release toolchain
@@ -568,13 +576,15 @@ Cross-links: [architecture](docs/architecture.md) ·
568
576
 
569
577
  DevRites is auditable Markdown + a small engine binary. The complete security
570
578
  policy, including private vulnerability reporting and recommended managed-deployment
571
- settings, lives in [`SECURITY.md`](SECURITY.md). Highlights: **project-local only**
572
- (installer refuses global Claude/Codex agent homes); **bounded installer network access**
579
+ settings, lives in [`SECURITY.md`](SECURITY.md). Highlights: **project-local host artifacts**
580
+ (installer refuses global Claude/Codex agent homes; only the shared engine binary may be global);
581
+ **bounded installer network access**
573
582
  for the release tarball and verified `devrites-engine` asset, with `--no-binary` /
574
- `DEVRITES_NO_BINARY=1` available for fully project-file-only installs; **no network
575
- access in skills**; **`!` shell injection removed** from `/rite` and `/rite-status`
583
+ `DEVRITES_NO_BINARY=1` available for fully project-file-only installs; **no hidden
584
+ skill-side networking** (external research goes through explicit host tools);
585
+ **`!` shell injection removed** from `/rite` and `/rite-status`
576
586
  (state loaded via read-only engine subcommands over DevRites' own state under
577
- `.devrites/`); **auto-trigger** is a deliberate design choice mitigated by body
587
+ `.devrites/`); **model invocation is per-skill frontmatter** and bounded by body
578
588
  discipline + readiness gates + the interactive `type-GO` confirmation in `/rite-ship`
579
589
  before irreversible git actions; **no `defaultMode: bypassPermissions`** is shipped or
580
590
  written by the installer (cf. CVE-2026-33068).
@@ -583,9 +593,11 @@ written by the installer (cf. CVE-2026-33068).
583
593
 
584
594
  - **Changelog:** [`CHANGELOG.md`](CHANGELOG.md) — Keep-a-Changelog + SemVer, regenerated by semantic-release on every release.
585
595
  - **Code of conduct:** [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) (Contributor Covenant 2.1).
586
- - **Code owners:** [`CODEOWNERS`](CODEOWNERS) — review required on `pack/`, `scripts/`, `install.sh`, `uninstall.sh`, `bin/`.
596
+ - **Code owners:** [`CODEOWNERS`](CODEOWNERS) — maintainer review covers all tracked paths.
587
597
  - **Notices:** [`NOTICE.md`](NOTICE.md).
588
- - **CI:** GitHub Actions runs `scripts/validate.sh`, install/uninstall smoke, fixture install, commitlint, and the eval suite on every PR.
598
+ - **CI:** GitHub Actions runs validation, the full shell suite, routing evals,
599
+ commitlint, strict Go quality/security checks, Windows tests, and release-target
600
+ cross-compilation on every PR.
589
601
  - **Commits:** Conventional Commits enforced via husky + commitlint.
590
602
  - **Release pipeline:** semantic-release on every push to `main` — full details in [`docs/release.md`](docs/release.md).
591
603
 
package/SECURITY.md CHANGED
@@ -23,25 +23,19 @@ the acknowledgement unless a shorter or longer window is mutually agreed.
23
23
 
24
24
  ## Supported versions
25
25
 
26
- DevRites is pre-1.0. Only the latest minor release line receives security
27
- updates.
28
-
29
- | Version | Supported |
30
- |---|---|
31
- | `0.1.x` | yes |
32
- | earlier | no |
33
-
34
- Once a `1.0` release ships, the latest two minor lines will be supported.
26
+ Only the latest published DevRites release receives security fixes. Older
27
+ releases are unsupported; upgrade before reporting a version-specific finding
28
+ unless the issue also reproduces on the latest release.
35
29
 
36
30
  ## DevRites security model
37
31
 
38
32
  ### Scope
39
33
 
40
34
  DevRites is a skills pack plus the local `devrites-engine` control-plane binary:
41
- Markdown skill files, helper scripts, a bash installer, and a thin `npx` CLI
42
- wrapper (`bin/devrites.mjs`) that bootstraps or proxies the engine. It ships no
43
- network service. The attack surface is the content of the skill files, the
44
- installer, generated host artifacts, hooks, and the local engine binary.
35
+ Markdown skill files, helper scripts, Bash bootstrap shims, and a native Node
36
+ `npx` shim (`bin/devrites.mjs`) that acquires and proxies the engine. It ships no
37
+ network service. The attack surface is the content of the skill files, bootstrap
38
+ and install paths, generated host artifacts, hooks, and the local engine binary.
45
39
 
46
40
  ### Supply-chain self-scan (shipped pack)
47
41
 
@@ -65,10 +59,11 @@ reviewable; never suppress a hidden-unicode finding you can't explain.
65
59
 
66
60
  ### State loading (engine subcommands, no `!` injection)
67
61
 
68
- `/rite`, `/rite-status`, and every workspace-operating skill load state by running
69
- a **read-only `devrites-engine` subcommand via the `Bash` tool** — *not* Claude Code's
62
+ `/rite-status` and workspace-operating skills load state by running a **read-only
63
+ `devrites-engine` subcommand via the `Bash` tool** — *not* Claude Code's
70
64
  preprocessing-only `` !`<command>` `` dynamic-context injection, which DevRites
71
- **removed** for cross-harness portability:
65
+ **removed** for cross-harness portability. The no-argument `/rite` menu runs
66
+ `devrites-engine first-task` instead; a routed verb hands control to its owning skill.
72
67
 
73
68
  ```bash
74
69
  command -v devrites-engine >/dev/null 2>&1 && devrites-engine preamble || echo "(unavailable — read state.md directly)"
@@ -77,20 +72,23 @@ command -v devrites-engine >/dev/null 2>&1 && devrites-engine preamble || echo "
77
72
  `devrites-engine preamble` is a project-local read of DevRites' own `.devrites/`
78
73
  state: no user input is concatenated into a command, no network access, no write
79
74
  side effects. The gate subcommands (`build-readiness`, `evidence-fresh`,
80
- `check-acceptance`) are likewise read-only; only explicit mutators (`resolve`,
81
- `tick-afk`, `close-out`, and the MCP `use` helper) write, and only under
82
- `.devrites/`.
75
+ `check-acceptance`) are likewise read-only. Mutating commands are explicit and
76
+ scoped: for example, `resolve`, `tick-afk`, and `close-out` write only DevRites
77
+ state, while `/rite use <slug>` deliberately repoints `.devrites/ACTIVE` inline.
83
78
 
84
- If your environment disallows skill-initiated shell execution, the scripts simply
79
+ If your environment disallows skill-initiated shell execution, the commands simply
85
80
  don't run — each skill degrades gracefully to reading `state.md` directly (the
86
81
  `|| echo "(… unavailable …)"` fallback above), and the rest of the pack is
87
82
  unaffected.
88
83
 
89
- ### Auto-trigger is deliberate
84
+ ### Model invocation is per skill
90
85
 
91
- All `rite-*` skills are **auto-invocable** by Claude when their descriptions
92
- match the user's intent. This is a conscious DevRites design choice (see
93
- `DECISIONS.md` Q3). The safety nets are:
86
+ Public skills are always user-invocable, but model invocation is set per skill.
87
+ Skills without `disable-model-invocation: true` may be selected when their
88
+ descriptions match the user's intent; explicit utilities carry that frontmatter
89
+ flag and load only when the user invokes them. The checked-in frontmatter and
90
+ [`docs/command-map.md`](docs/command-map.md) are the source of truth. The safety
91
+ nets for model-invocable rites are:
94
92
 
95
93
  - **Body discipline**: every skill stops at its phase boundary. `rite-build`
96
94
  stops after one slice, `rite-prove` runs proofs only when all slices are
@@ -100,31 +98,39 @@ match the user's intent. This is a conscious DevRites design choice (see
100
98
  - **Spec Drift Guard**: any deviation from the spec halts and routes to
101
99
  `rite-plan`.
102
100
  - **Interactive type-GO confirmation** in `rite-ship` before irreversible
103
- git actions (commit, push, tag) — present even with auto-trigger; `rite-seal`
101
+ git actions (commit, push, tag) — present even after model invocation; `rite-seal`
104
102
  only decides GO/NO-GO.
105
103
 
106
- If you prefer explicit-only invocation in a given project, add a Claude Code
107
- `permissions` rule disabling `Skill(rite-*)` auto-invocation in that
108
- project's `.claude/settings.json`.
104
+ Claude documents the invocation controls in its official
105
+ [skills reference](https://code.claude.com/docs/en/slash-commands). DevRites uses
106
+ `disable-model-invocation: true` rather than an undocumented settings key.
109
107
 
110
108
  ### Installer safety
111
109
 
112
- The bash installer (`install.sh`) refuses any target under `~/.claude`
113
- (`GUARD:no-global` block) and writes only to a manifest-tracked file list.
114
- `./uninstall.sh` removes exactly the manifested files. The
110
+ The Bash installer (`install.sh`) refuses any target under `~/.claude`
111
+ (`GUARD:no-global` block). Project host files are manifest-tracked;
112
+ `./uninstall.sh` removes exactly those managed files. The
115
113
  `.devrites/` runtime state in the target project is preserved across
116
114
  uninstall.
117
115
 
118
- The installer touches no global state. It does not invoke `sudo`, modify
119
- shell rc files, fetch remote code, or alter Claude Code settings.
116
+ Skills, agents, standards, and hook configuration stay in the target project.
117
+ The installer merges DevRites entries into project-local `.claude/settings.json`
118
+ and `.codex/hooks.json` without replacing unrelated user settings. Its only
119
+ sanctioned global artifact is the shared `devrites-engine` executable, installed
120
+ to `DEVRITES_BIN_DIR`, a writable `~/.local/bin`, or a writable
121
+ `/usr/local/bin`; `--no-binary` / `DEVRITES_NO_BINARY=1` skips it. The bootstrap
122
+ path may fetch the release bundle and checksummed engine assets. It never invokes
123
+ `sudo` or edits shell startup files.
120
124
 
121
125
  ### npx install path
122
126
 
123
127
  When installed via `npx devrites@latest`, the CLI (`bin/devrites.mjs`) is a thin
124
- shim that runs the **bundled** `install.sh` against the pack shipped inside the npm
125
- package no remote code is fetched at install time, and the install is pinned to
126
- the requested package version. It has no runtime npm dependencies and makes no
127
- global writes; the same project-local guarantees as the bash installer apply.
128
+ Node shim that delegates directly to `devrites-engine`; it does not execute
129
+ `install.sh`. The host payload is bundled and pinned to the requested npm package
130
+ version. To start the engine, the shim tries the matching release binary plus its
131
+ SHA-256 sidecar, then a local Go build, then an existing engine. It has no runtime
132
+ npm dependencies. Project-artifact and optional shared-binary boundaries are the
133
+ same as the Bash path.
128
134
 
129
135
  ### Recommended Claude Code permissions for managed deployments
130
136
 
@@ -133,44 +139,50 @@ For organizations evaluating DevRites under a managed Claude Code policy:
133
139
  ```jsonc
134
140
  {
135
141
  "permissions": {
136
- "Skill(rite-seal)": "ask",
137
- "Bash(git push *)": "ask",
138
- "Bash(git tag *)": "ask"
139
- },
140
- "disableSkillShellExecution": true
142
+ "ask": [
143
+ "Bash(git commit *)",
144
+ "Bash(git push *)",
145
+ "Bash(git tag *)"
146
+ ]
147
+ }
141
148
  }
142
149
  ```
143
150
 
144
- The first three lines surface a confirmation prompt before any irreversible
145
- git action; the last disables the `/rite` and `/rite-status` dynamic-state
146
- read described above (DevRites still works).
151
+ This follows the current
152
+ [Claude Code permissions schema](https://code.claude.com/docs/en/permissions)
153
+ and surfaces a host confirmation before the git mutation ladder. DevRites'
154
+ separate type-`GO` workflow gate still applies.
147
155
 
148
156
  ### Hooks (approval, orientation, and local guards)
149
157
 
150
- DevRites ships JSON-configured hooks installed by the npm flow into the
158
+ DevRites ships JSON-configured hooks installed by the engine-owned flow into the
151
159
  project-local host artifacts (`.claude/settings.json` for Claude Code and
152
160
  `.codex/hooks.json` for Codex). They call `devrites-engine` behind an inline
153
161
  fail-open guard:
154
162
 
155
163
  - **`allow` (PreToolUse/Bash)** — auto-approves *only* the read-only engine
156
- orientation/gate subcommands (`preamble`, `progress`, `readiness`,
157
- `evidence-fresh`, `check-acceptance`) so they stop prompting on every skill run.
164
+ orientation/gate subcommands (`check-acceptance`, `doubt-coverage`,
165
+ `evidence-fresh`, `preamble`, `progress`, `readiness`, `review-integrity`),
166
+ `footprint render|roster`, `ledger diff|validate|list|show`, and
167
+ `reviewer-stats report`, so they stop prompting on every skill run.
158
168
  It never denies, and it emits `allow` only when the parsed command is one of those
159
169
  subcommands and contains no dangerous/exfiltration tokens (`rm`, redirects,
160
170
  `curl`/`wget`, `sudo`, `chmod`, command substitution, `eval`, package managers,
161
171
  `git push/commit/reset`, etc.). Mutating subcommands (`resolve`, `tick-afk`,
162
172
  `close-out`) are deliberately excluded and still prompt.
163
- - **Read-only context hooks** — `orient`, `cursor`, and `subagent-orient` inject
164
- active-workspace context and stay silent when no `.devrites/` workspace is active.
165
- - **Local guard hooks** `a1-guard`, `redwatch`, `stop-gate`, `source-cache-*`,
166
- and `refresh-indexes` run through the engine and are fail-open by default. New
167
- blocking guards are observe-first unless explicitly enforced with the documented
168
- `DEVRITES_*` environment switches.
173
+ - **Context and continuity hooks** — `orient`, `cursor`, `subagent-orient`,
174
+ `statusline`, and `handoff-snapshot` inject bounded workspace context; `event`
175
+ and `auq` append lifecycle/HITL events. They stay silent when no workspace is active.
176
+ - **Local guards and caches** `a1-guard`, `wright-scope`,
177
+ `reviewer-readonly`, `redwatch`, `stop-gate`, `source-cache-*`, and
178
+ `refresh-indexes` run through the engine. Guard hooks are fail-open or
179
+ observe-first unless explicitly enforced with the documented `DEVRITES_*`
180
+ controls; source-cache network I/O is the bounded exception in ADR-0008.
169
181
 
170
182
  Delete the project-local hook file (`.claude/settings.json` for Claude Code, or
171
183
  the DevRites-managed entries in `.codex/hooks.json` for Codex) to remove hooks.
172
- The seeded settings file is never overwritten on update, so your own permission
173
- rules are safe.
184
+ Updates merge DevRites entries rather than replacing unrelated project settings,
185
+ so user permission rules remain intact.
174
186
 
175
187
  ### Third-party trust
176
188
 
@@ -206,10 +218,12 @@ visibly justified.
206
218
 
207
219
  ### Known non-issues
208
220
 
209
- - **`!` injection in `/rite`** — local read of own state; safe. See above.
221
+ - **Historical `!` injection in `/rite`** — no longer present; current state
222
+ orientation uses structurally bounded, read-only engine commands.
210
223
  - **`Write` / `Edit` tool allowance in `rite-*` skills** — required to
211
224
  author `.devrites/` and project files. No skill grants `Bash(*)`.
212
- - **Auto-trigger** — deliberate design choice; mitigated as above.
225
+ - **Per-skill model invocation** — deliberate and frontmatter-controlled;
226
+ model-invocable rites remain bounded by the gates above.
213
227
 
214
228
  ### CVE relevance
215
229
 
@@ -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.