devrites 5.0.0 → 5.2.0

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 (46) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/engine/internal/parallel/lease.go +12 -2
  4. package/engine/internal/parallel/ops.go +3 -3
  5. package/engine/internal/parallel/parallel_test.go +104 -0
  6. package/pack/.claude/agents/devrites-slice-wright.md +5 -1
  7. package/pack/.claude/skills/rite-build/SKILL.md +11 -7
  8. package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +8 -5
  9. package/pack/.claude/skills/rite-build/reference/parallel-batch.md +14 -7
  10. package/pack/.claude/skills/rite-build/reference/phase-contract.md +1 -0
  11. package/pack/.claude/skills/rite-build/reference/spec-drift-guard.md +22 -3
  12. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +5 -2
  13. package/pack/.claude/skills/rite-plan/SKILL.md +14 -2
  14. package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +10 -3
  15. package/pack/.claude/skills/rite-vet/SKILL.md +22 -13
  16. package/pack/generated/claude/agents/devrites-slice-wright.md +5 -1
  17. package/pack/generated/claude/skills/rite-build/SKILL.md +11 -7
  18. package/pack/generated/claude/skills/rite-build/reference/one-slice-cycle.md +8 -5
  19. package/pack/generated/claude/skills/rite-build/reference/parallel-batch.md +14 -7
  20. package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +1 -0
  21. package/pack/generated/claude/skills/rite-build/reference/spec-drift-guard.md +22 -3
  22. package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +5 -2
  23. package/pack/generated/claude/skills/rite-plan/SKILL.md +14 -2
  24. package/pack/generated/claude/skills/rite-plan/reference/replan-and-repair.md +10 -3
  25. package/pack/generated/claude/skills/rite-vet/SKILL.md +22 -13
  26. package/pack/generated/codex/agents/devrites-slice-wright.toml +5 -1
  27. package/pack/generated/codex/skills/rite-build/SKILL.md +11 -7
  28. package/pack/generated/codex/skills/rite-build/reference/one-slice-cycle.md +8 -5
  29. package/pack/generated/codex/skills/rite-build/reference/parallel-batch.md +14 -7
  30. package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +1 -0
  31. package/pack/generated/codex/skills/rite-build/reference/spec-drift-guard.md +22 -3
  32. package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +5 -2
  33. package/pack/generated/codex/skills/rite-plan/SKILL.md +14 -2
  34. package/pack/generated/codex/skills/rite-plan/reference/replan-and-repair.md +10 -3
  35. package/pack/generated/codex/skills/rite-vet/SKILL.md +22 -13
  36. package/pack/generated/omp/agents/devrites-slice-wright.md +5 -1
  37. package/pack/generated/omp/skills/rite-build/SKILL.md +11 -7
  38. package/pack/generated/omp/skills/rite-build/reference/one-slice-cycle.md +8 -5
  39. package/pack/generated/omp/skills/rite-build/reference/parallel-batch.md +14 -7
  40. package/pack/generated/omp/skills/rite-build/reference/phase-contract.md +1 -0
  41. package/pack/generated/omp/skills/rite-build/reference/spec-drift-guard.md +22 -3
  42. package/pack/generated/omp/skills/rite-build/reference/wright-dispatch.md +5 -2
  43. package/pack/generated/omp/skills/rite-plan/SKILL.md +14 -2
  44. package/pack/generated/omp/skills/rite-plan/reference/replan-and-repair.md +10 -3
  45. package/pack/generated/omp/skills/rite-vet/SKILL.md +22 -13
  46. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
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
+ ## [5.2.0](https://github.com/ViktorsBaikers/DevRites/compare/v5.1.0...v5.2.0) (2026-09-11)
6
+
7
+ ### Added
8
+
9
+ * **skills:** batch build-time gap repair and auto-chain plan/vet ([#61](https://github.com/ViktorsBaikers/DevRites/issues/61)) ([a668270](https://github.com/ViktorsBaikers/DevRites/commit/a668270b4a278ffb81a1b73bf962d13da2097e5a))
10
+
11
+ ## [5.1.0](https://github.com/ViktorsBaikers/DevRites/compare/v5.0.0...v5.1.0) (2026-09-10)
12
+
13
+ ### Added
14
+
15
+ * **skills:** raise /rite-build --parallel cap from 3 to 10 ([#60](https://github.com/ViktorsBaikers/DevRites/issues/60)) ([d88afa0](https://github.com/ViktorsBaikers/DevRites/commit/d88afa0af31eed421a1a5fdbff8eaf3f61b02bff))
16
+
5
17
  ## [5.0.0](https://github.com/ViktorsBaikers/DevRites/compare/v4.7.0...v5.0.0) (2026-09-06)
6
18
 
7
19
  ### ⚠ BREAKING CHANGES
package/README.md CHANGED
@@ -33,7 +33,7 @@ project-conventional push, tag, or PR action, and archive the workspace.
33
33
  Unattended runs may create local WIP checkpoint commits along the way, but they
34
34
  remain local unless Ship's disclosed plan includes an approved remote action.
35
35
 
36
- **Status:** [`v5.0.0`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v5.0.0): see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
36
+ **Status:** [`v5.2.0`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v5.2.0): see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
37
37
 
38
38
  This is the latest published release; `main` may contain unreleased work.
39
39
 
@@ -20,6 +20,9 @@ const (
20
20
  WrightGreen = "green"
21
21
  WrightRed = "red"
22
22
  WrightGap = "gap"
23
+
24
+ MinParallelSlices = 2
25
+ MaxParallelSlices = 10
23
26
  )
24
27
 
25
28
  var (
@@ -95,6 +98,13 @@ func validateSliceID(id string) error {
95
98
  return nil
96
99
  }
97
100
 
101
+ func checkParallelSliceCount(n int) error {
102
+ if n < MinParallelSlices || n > MaxParallelSlices {
103
+ return fmt.Errorf("parallel requires %d-%d slices (got %d)", MinParallelSlices, MaxParallelSlices, n)
104
+ }
105
+ return nil
106
+ }
107
+
98
108
  func ValidateLease(lease *Lease) error {
99
109
  if lease == nil {
100
110
  return fmt.Errorf("lease is nil")
@@ -113,8 +123,8 @@ func ValidateLease(lease *Lease) error {
113
123
  default:
114
124
  return fmt.Errorf("invalid lease status %q", lease.Status)
115
125
  }
116
- if len(lease.Slices) < 2 || len(lease.Slices) > 3 {
117
- return fmt.Errorf("lease must have 2 or 3 slices (got %d)", len(lease.Slices))
126
+ if err := checkParallelSliceCount(len(lease.Slices)); err != nil {
127
+ return err
118
128
  }
119
129
  if lease.N != len(lease.Slices) {
120
130
  return fmt.Errorf("lease n=%d does not match slices=%d", lease.N, len(lease.Slices))
@@ -29,7 +29,7 @@ type CreateOpts struct {
29
29
  Slices []SlicePaths
30
30
  }
31
31
 
32
- // Create path-disjoint-gates, creates <=3 worktrees from base, and writes a running lease.
32
+ // Create path-disjoint-gates, creates 2-10 worktrees from base, and writes a running lease.
33
33
  func Create(opts CreateOpts) (*Lease, error) {
34
34
  if err := validateSlug(opts.Slug); err != nil {
35
35
  return nil, err
@@ -37,8 +37,8 @@ func Create(opts CreateOpts) (*Lease, error) {
37
37
  if err := validateBatchID(opts.BatchID); err != nil {
38
38
  return nil, err
39
39
  }
40
- if len(opts.Slices) < 2 || len(opts.Slices) > 3 {
41
- return nil, fmt.Errorf("create requires 2 or 3 slices (got %d)", len(opts.Slices))
40
+ if err := checkParallelSliceCount(len(opts.Slices)); err != nil {
41
+ return nil, err
42
42
  }
43
43
  if _, err := CheckPathDisjoint(opts.Slices, opts.Root); err != nil {
44
44
  return nil, err
@@ -1,6 +1,7 @@
1
1
  package parallel
2
2
 
3
3
  import (
4
+ "fmt"
4
5
  "os"
5
6
  "os/exec"
6
7
  "path/filepath"
@@ -146,6 +147,109 @@ func TestCreateAbortCleanup(t *testing.T) {
146
147
  }
147
148
  }
148
149
 
150
+ func TestCreateAcceptsFourSlices(t *testing.T) {
151
+ t.Parallel()
152
+ repo, _ := setupRepo(t)
153
+ for _, name := range []string{"c.go", "d.go"} {
154
+ if err := os.WriteFile(filepath.Join(repo, "src", name), []byte("package main\n"), 0o644); err != nil {
155
+ t.Fatal(err)
156
+ }
157
+ }
158
+ gitOk(t, repo, "add", ".")
159
+ gitOk(t, repo, "commit", "-m", "more files")
160
+ base := gitOk(t, repo, "rev-parse", "HEAD")
161
+ lease, err := Create(CreateOpts{
162
+ Root: repo,
163
+ Slug: "demo-four",
164
+ BatchID: "batch4",
165
+ BaseSHA: base,
166
+ Slices: []SlicePaths{
167
+ {ID: "slice-a", Paths: []string{"src/a.go"}},
168
+ {ID: "slice-b", Paths: []string{"src/b.go"}},
169
+ {ID: "slice-c", Paths: []string{"src/c.go"}},
170
+ {ID: "slice-d", Paths: []string{"src/d.go"}},
171
+ },
172
+ })
173
+ if err != nil {
174
+ t.Fatal(err)
175
+ }
176
+ if lease.N != 4 || len(lease.Slices) != 4 {
177
+ t.Fatalf("want 4 slices, got n=%d slices=%d", lease.N, len(lease.Slices))
178
+ }
179
+ }
180
+
181
+ func TestCreateRefusesCountOutsideBounds(t *testing.T) {
182
+ t.Parallel()
183
+ repo, base := setupRepo(t)
184
+ _, err := Create(CreateOpts{
185
+ Root: repo,
186
+ Slug: "demo-one",
187
+ BatchID: "batch1",
188
+ BaseSHA: base,
189
+ Slices: []SlicePaths{{ID: "slice-a", Paths: []string{"src/a.go"}}},
190
+ })
191
+ if err == nil || !strings.Contains(err.Error(), "2-10 slices") {
192
+ t.Fatalf("expected 2-10 bound for N=1, got %v", err)
193
+ }
194
+
195
+ slices := make([]SlicePaths, MaxParallelSlices+1)
196
+ for i := range slices {
197
+ name := fmt.Sprintf("src/x%d.go", i)
198
+ if err := os.WriteFile(filepath.Join(repo, name), []byte("package main\n"), 0o644); err != nil {
199
+ t.Fatal(err)
200
+ }
201
+ slices[i] = SlicePaths{ID: fmt.Sprintf("s%d", i), Paths: []string{name}}
202
+ }
203
+ gitOk(t, repo, "add", ".")
204
+ gitOk(t, repo, "commit", "-m", "eleven")
205
+ base = gitOk(t, repo, "rev-parse", "HEAD")
206
+ _, err = Create(CreateOpts{
207
+ Root: repo,
208
+ Slug: "demo-eleven",
209
+ BatchID: "batch11",
210
+ BaseSHA: base,
211
+ Slices: slices,
212
+ })
213
+ if err == nil || !strings.Contains(err.Error(), "2-10 slices") {
214
+ t.Fatalf("expected 2-10 bound for N=11, got %v", err)
215
+ }
216
+ }
217
+
218
+ func TestValidateLeaseBounds(t *testing.T) {
219
+ t.Parallel()
220
+ ok := validTestLease(MaxParallelSlices)
221
+ if err := ValidateLease(ok); err != nil {
222
+ t.Fatalf("N=%d should validate: %v", MaxParallelSlices, err)
223
+ }
224
+ tooMany := validTestLease(MaxParallelSlices + 1)
225
+ if err := ValidateLease(tooMany); err == nil || !strings.Contains(err.Error(), "2-10 slices") {
226
+ t.Fatalf("N=%d should refuse, got %v", MaxParallelSlices+1, err)
227
+ }
228
+ }
229
+
230
+ func validTestLease(n int) *Lease {
231
+ slices := make([]LeaseSlice, n)
232
+ for i := range slices {
233
+ id := fmt.Sprintf("s%d", i)
234
+ slices[i] = LeaseSlice{
235
+ ID: id,
236
+ Paths: []string{fmt.Sprintf("src/%s.go", id)},
237
+ WorktreePath: "/tmp/" + id,
238
+ Branch: "devrites/parallel/x/batch/" + id,
239
+ WrightStatus: WrightPending,
240
+ }
241
+ }
242
+ return &Lease{
243
+ BatchID: "batch1",
244
+ CreatedAt: "2026-08-23T00:00:00Z",
245
+ BaseSHA: "abcdef1",
246
+ N: n,
247
+ Status: StatusRunning,
248
+ ControlPIDOrSession: "test",
249
+ Slices: slices,
250
+ }
251
+ }
252
+
149
253
  func TestCreateRefusesOverlap(t *testing.T) {
150
254
  repo, base := setupRepo(t)
151
255
  _, err := Create(CreateOpts{
@@ -140,6 +140,10 @@ return an `Escalation`** when:
140
140
  scoped exception or the approach must change. Report the principle and conflict
141
141
  in `Escalation`.
142
142
 
143
+ A plan-gap or underspecification escalation populates `assumptions` with every
144
+ contract assumption already checked (verified|falsified); the orchestrator's
145
+ batch sweep covers only the unchecked remainder. Never a bare "plan is wrong".
146
+
143
147
  If an answer would change scope or acceptance, do **not** fold it into the slice.
144
148
  Return it in `Escalation` so the orchestrator can route it through the Spec Drift
145
149
  Guard (`/rite-plan repair`). Respect any AFK budget in the contract.
@@ -174,7 +178,7 @@ reuse: []
174
178
  conventions: []
175
179
  principles: []
176
180
  sources: []
177
- assumptions: []
181
+ assumptions: [] # plan-gap escalation: every checked contract assumption, verified|falsified
178
182
  decisions_stood: [] # irreversible-risk items go to escalation
179
183
  dead_ends: []
180
184
  escalation: <none | gate + crisp question + proposed answer>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: rite-build
3
- description: Build the next approved vertical slice with evidence. HITL one-slice default; AFK may chain serially; opt-in `--parallel N` (2≤N≤3) for path-disjoint worktrees.
3
+ description: Build the next approved vertical slice with evidence. HITL one-slice default; AFK may chain serially; opt-in `--parallel N` (2≤N≤10) for path-disjoint worktrees.
4
4
  argument-hint: "[--parallel N] [slice number or name]"
5
5
  user-invocable: true
6
6
  ---
@@ -10,7 +10,7 @@ user-invocable: true
10
10
  Build and prove one slice. HITL stops; a later user invocation starts the next.
11
11
  Explicit `.devrites/AFK` alone lets the controlling root chain pending slices
12
12
  serially under green proof, caps, and pause rules. Every wright returns after one slice.
13
- **Opt-in:** `/rite-build --parallel N` (2≤N≤3; N=1≡serial) follows
13
+ **Opt-in:** `/rite-build --parallel N` (2≤N≤10; N=1≡serial) follows
14
14
  [`reference/parallel-batch.md`](reference/parallel-batch.md)
15
15
  ([`one-slice-cycle.md`](reference/one-slice-cycle.md)).
16
16
 
@@ -38,8 +38,10 @@ Wright applies anti-slop; root verifies returns and never patches source.
38
38
  single-slice isolation when `wright-dispatch.md` preflight + reconcile hold.
39
39
  - Exact feature scope only; reject out-of-allowlist diffs; record adjacent issues.
40
40
  - Never rerun an unchanged check; re-prove after edits.
41
- - Unplanned dependency/design-system/gap/repair → Vet/Spec Drift Guard. Ask only
42
- for licensing/cost/security/product or explicit architecture-policy decisions.
41
+ - Unplanned dependency/design-system/gap/repair → Vet/Spec Drift Guard batch
42
+ sweep: every contract-assumption violation recorded before one folded
43
+ repair+vet. Ask only for licensing/cost/security/product or explicit
44
+ architecture-policy decisions.
43
45
  - Root never edits product source/tests (`.devrites/` + Workflow Artifact only).
44
46
  Wright is sole product writer; extras in returned paths/`git diff --name-only` hard-stop.
45
47
  - Principles bind; irreversible conflict needs human exception or stop.
@@ -55,9 +57,11 @@ Wright applies anti-slop; root verifies returns and never patches source.
55
57
  <!-- workflow-artifact-adapter: {"module":"devrites-lib/reference/standards/workflow-artifacts.md","entry":"Vet-ready admitted bytes require root authorship outside product wright","action":"ROOT_TRANSACTION; root writes only admitted .devrites/** targets","return":"saved Build slice cursor; wright product allowlist unchanged"} -->
56
58
  ## `--parallel N` (opt-in)
57
59
 
58
- Omitted/`1` ≡ serial; `2`/`3` → path-disjoint fan-out when eligible; else hard refuse.
59
- All-green serial integrate; one red/gap aborts. AFK charges after integrate only.
60
- Running lease blocks another `/rite-build`. Details: `parallel-batch.md`.
60
+ Omitted/`1` ≡ serial; `2`–`10` → path-disjoint fan-out when eligible; else hard refuse.
61
+ All-green serial integrate; one red/gap aborts. Abort with agent-owned plan
62
+ gaps continues via Spec Drift Guard (batch sweep, one folded plan repair + one
63
+ vet recheck inline); do not emit a human `Fix`. AFK charges after integrate only. Running lease blocks another
64
+ `/rite-build`. Details: `parallel-batch.md`.
61
65
 
62
66
  ## Execute and reply
63
67
 
@@ -3,7 +3,7 @@
3
3
  One wright dispatch builds one thin, proven slice. HITL stops; only explicit
4
4
  `.devrites/AFK` lets the controlling root chain another pending slice under the
5
5
  green-proof, cap, and pause rules. Each wright returns after exactly one slice.
6
- Opt-in fan-out: [`parallel-batch.md`](parallel-batch.md) (`--parallel N`); this is default.
6
+ This serial cycle is the default `/rite-build`. Opt-in fan-out: [`parallel-batch.md`](parallel-batch.md) (`--parallel N`).
7
7
 
8
8
  ## The cycle
9
9
 
@@ -38,8 +38,11 @@ you check yourself against: anything outside it is scope creep or a drift event.
38
38
 
39
39
  ## When the slice can't be completed cleanly
40
40
 
41
- - Discovered the plan is wrong → **Spec Drift Guard** (stop, record, classify, maybe
42
- ask, `/rite-plan` repair).
43
- - Slice is bigger than one cycle → stop and `/rite-plan reslice`.
44
- - Blocked on a failing dependencyrecord in `state.md`, `/rite-plan unblock`.
41
+ - Discovered the plan is wrong → **Spec Drift Guard** (record, classify;
42
+ sweep every remaining contract assumption, then one folded repair+vet inline;
43
+ ask only for product/policy/irreversible-risk).
44
+ - Slice is bigger than one cycle → `/rite-plan reslice` inline when AC is
45
+ preserved; do not emit a human Fix.
46
+ - Blocked on a failing dependency → record in `state.md`, `/rite-plan unblock`
47
+ inline when the reroute is technical.
45
48
  Never power through by guessing.
@@ -7,12 +7,13 @@ Opt-in only. Default `/rite-build` stays [`one-slice-cycle.md`](one-slice-cycle.
7
7
  | Input | Behavior |
8
8
  | --- | --- |
9
9
  | omitted / `--parallel 1` | Serial one-slice |
10
- | `--parallel N` (**2≤N≤3**) | Parallel when eligible + host pass |
11
- | non-integer / `N≤0` / `N>3` | Hard refuse (no silent clamp) |
10
+ | `--parallel N` (**2≤N≤10**) | Parallel when eligible + host pass |
11
+ | non-integer / `N≤0` / `N>10` | Hard refuse (no silent clamp) |
12
12
 
13
13
  AFK caps `N` by remaining budget. Charge **only after successful integrate**
14
- (once per integrated green sibling). Abort / integrate-failed → **0**. Running
15
- lease blocks another `/rite-build`.
14
+ (once per integrated green sibling). Abort / integrate-failed → **0**. A
15
+ `running` lease blocks another `/rite-build`. Any present lease blocks
16
+ `parallel create` until cleanup.
16
17
 
17
18
  ## Path-disjoint
18
19
 
@@ -40,14 +41,20 @@ Lease: `batch_id`, `created_at`, `base_sha`, `n`,
40
41
 
41
42
  1. Orient/gate; parse N; select ≤N path-disjoint pending slices.
42
43
  2. Write lease; freeze `B=HEAD`; `parallel create` worktrees.
43
- 3. Dispatch ≤3 wrights in parallel (cwd=worktree; allowlist; prove `HEAD==B`).
44
- 4. Inspect + fail-on-red → `green|red|gap`.
44
+ 3. Dispatch ≤10 wrights in parallel (cwd=worktree; allowlist; prove `HEAD==B`).
45
+ 4. Inspect + fail-on-red → `green|red|gap`. Independent-review Critical is `gap`
46
+ even when targeted tests are green.
45
47
  5. Any red/gap → **abort** (no partial integrate). All green → serial integrate.
46
48
  6. Integrate: `transfer_commit` descends from `B`; `` `<base>..<transfer>` ``
47
49
  path-exact; apply in plan order. Conflict → reset to `B`, `integrate-failed`.
48
50
  7. Success: FF control; union `touched-files.md`; update state/evidence; AFK +1
49
51
  per integrated sibling; optional `check candidate`.
50
- 8. Cleanup: success removes worktrees/branches; abort keeps until acknowledged.
52
+ 8. Cleanup: success removes worktrees/branches. Abort keeps them as repair
53
+ inputs until the root consumes them: agent-owned plan gaps (AC unchanged)
54
+ follow [`spec-drift-guard.md`](spec-drift-guard.md) — batch-sweep all
55
+ siblings' contract assumptions, one folded `/rite-plan repair` + one
56
+ `/rite-vet` recheck inline, then cleanup and resume Build. Do not emit
57
+ `Fix: /rite-plan repair`. Product/policy/irreversible-risk still stops.
51
58
 
52
59
  ## Engine verbs
53
60
 
@@ -3,6 +3,7 @@
3
3
  See [`one-slice-cycle.md`](one-slice-cycle.md); candidate lifecycle is
4
4
  [`candidate-integrity.md`](../../devrites-lib/reference/candidate-integrity.md).
5
5
  Opt-in `--parallel N` uses [`parallel-batch.md`](parallel-batch.md) instead of steps 2–8.
6
+ Spec Drift Guard still applies on abort or plan-gap.
6
7
 
7
8
  1. **Orient and gate.** Read core, `.devrites/ACTIVE`, `state.md`, and required
8
9
  slice artifacts. Require `Implementation readiness: READY`, its current
@@ -24,13 +24,31 @@ other phases reference it here.
24
24
  YES, active-slice technical/tool failure → log it and use Build's bounded debug
25
25
  recovery. Do not ask for retry authorization and do not re-plan unless the
26
26
  durable remaining-work instructions are wrong.
27
- YES, durable plan is wrong → log it, save the caller's return cursor, then
28
- invoke `/rite-plan repair` and `/rite-vet` inline without a question and resume.
27
+ YES, durable plan is wrong → run the batch sweep below, log every
28
+ violation, save the caller's return cursor, then invoke `/rite-plan repair` and `/rite-vet` inline
29
+ without a question — ONE folded repair for all open entries, ONE
30
+ recheck for every open fingerprint — and resume.
29
31
  NO, product/policy/irreversible-risk decision → ask the user (format below).
30
32
  5. Never continue on a known-wrong durable plan. A repaired active-slice implementation
31
33
  may continue only after bounded recovery, returned-diff review, and proof gates pass.
32
34
  ```
33
35
 
36
+ ## Batch sweep (before repair)
37
+
38
+ A durable-plan drift abort never repairs the first gap alone:
39
+
40
+ 1. Verify every remaining statically-checkable contract assumption against the
41
+ live repo — named paths, symbols/APIs/signatures, routes, commands, dependency
42
+ versions, contract artifacts. The wright's return names what it falsified;
43
+ check the rest yourself — existence checks are deterministic, no dispatch.
44
+ 2. Record each violation as its own `drift.md` entry/fingerprint; one folded
45
+ repair + one batched recheck resolves the set.
46
+ 3. A recheck-surfaced gap is a new fingerprint with its own budget — loop
47
+ internally, never hand an intermediate command to the human.
48
+ 4. Nothing skips or defers silently: every entry ends resolved, human-escalated,
49
+ or fingerprint-exhausted. Execution-only gaps (tests, UX, evidence) get the
50
+ identical path when they surface.
51
+
34
52
  ## User question format
35
53
  ```
36
54
  I hit spec drift:
@@ -50,7 +68,8 @@ human permission question. Re-plan only when the durable plan changed.
50
68
 
51
69
  ## Inline return contract
52
70
 
53
- The phase that detected agent-owned drift owns the whole backtrack. Preserve it
71
+ The phase that detected agent-owned drift owns the whole backtrack, batch sweep
72
+ included. Preserve it
54
73
  as `return_phase`/`return_next_action`; consume Plan and Vet's nested `STOP`
55
74
  boundaries internally; follow any vetted remediation required by the settled
56
75
  acceptance; then restore the cursor and resume the failed step. Do not hand an
@@ -36,7 +36,7 @@ Conflict, extra/missing commit, moved base, or cleanup failure is `gap`/STOP:
36
36
  preserve the worktree and commit. Without explicit reconciliation, use same-worktree serial.
37
37
  Parallel isolated-writer worktrees remain forbidden until this serial pilot measures
38
38
  transfer, conflict, proof, and review outcomes on both hosts; opt-in `/rite-build --parallel N`
39
- (2≤N≤3) path-disjoint fan-out is the only sanctioned parallel mode. Same-worktree multi-writer / root-emulated
39
+ (2≤N≤10) path-disjoint fan-out is the only sanctioned parallel mode. Same-worktree multi-writer / root-emulated
40
40
  worktrees stay forbidden.
41
41
 
42
42
  ## Prepare
@@ -83,4 +83,7 @@ Opt-in `/rite-build --parallel N` fans out only under [`parallel-batch.md`](para
83
83
  attempts is the limit; persist each and never dispatch a fourth related try.
84
84
  5. Reconcile returned reuse, conventions, principles, sources, assumptions,
85
85
  decisions, dead ends, follow-ups, gates, and touched files. Persist the
86
- relevant facts in canonical artifacts, not the wholesale report.
86
+ relevant facts in canonical artifacts, not the wholesale report. A plan-gap
87
+ escalation without the checked-assumption list (verified|falsified) is
88
+ malformed; root sweeps the unchecked remainder per
89
+ [`spec-drift-guard.md`](spec-drift-guard.md) before repair.
@@ -79,6 +79,9 @@ Before classifying any Reslice, read `.claude/skills/devrites-lib/reference/stan
79
79
  require the drafter to apply `one-shot-actions.md` and return the bounded
80
80
  diagnostic-amplification design, injective boundary map, per-seam fixtures, and
81
81
  collision mutant. Past evidence loss is not terminal. The drafter supplies no bodies.
82
+ A repair candidate carries a delta self-check: touched invariants re-verified
83
+ (acyclic deps, bidirectional traceability, shared contract proof, sizing), no
84
+ correction-created regression.
82
85
  Bind exact active `.devrites/work/<slug>/` targets and executable contract; after Vet READY, root
83
86
  materializes the exact vetted workflow-artifact paths under
84
87
  [`workflow-artifacts.md`](../devrites-lib/reference/standards/workflow-artifacts.md)
@@ -115,8 +118,9 @@ Before classifying any Reslice, read `.claude/skills/devrites-lib/reference/stan
115
118
  material assumption, or open blocking/escalating question routes `/rite-clarify`/HITL.
116
119
  Restore `CLEAR` only from current evidence.
117
120
  7. **Done when:** every slice is sized (builds + proves in one cycle; no slice scoring >3
118
- left unjustified), the dependency order is acyclic, every `drift.md` entry you stopped for
119
- is marked resolved, revised artifacts agree with each other, no source files changed in
121
+ left unjustified), the dependency order is acyclic, every open `drift.md` entry
122
+ was folded in one pass and marked resolved, the delta self-check is recorded,
123
+ revised artifacts agree with each other, no source files changed in
120
124
  `revise` mode, the marked action is complete, and every changed
121
125
  plan ends at `/rite-vet` rather than returning directly to build; horizon IDs stay stable,
122
126
  reclassifications cite evidence, and no unresolved item vanished. The `Shared contract proof`
@@ -128,5 +132,13 @@ to that caller so it can invoke Vet immediately. The phase boundary is not a
128
132
  user-facing stop unless a genuine HITL, safety/access, or exhausted-recovery
129
133
  condition was recorded.
130
134
 
135
+ When invoked directly with no controlling caller and a planning artifact
136
+ changed, become the caller for the mandated next step: record the return
137
+ cursor, invoke `/rite-vet` inline, and consume its results — `NEEDS REPLAN`
138
+ re-enters repair internally under the fingerprint caps; `NEEDS CLARIFICATION`
139
+ and human-owned gates still reach the user. Stop only at Vet's boundary (READY
140
+ readback; next step `/rite-build`). An unchanged plan keeps its recorded next
141
+ step.
142
+
131
143
  > **Mid-flight discipline.** Do not change product behavior without confirmation or
132
144
  > absorb drift silently. See [`anti-patterns`](reference/anti-patterns.md).
@@ -26,12 +26,19 @@ dependency edges.
26
26
 
27
27
  A drift event stopped the build. Steps:
28
28
 
29
- 1. Read the `drift.md` entry and its classification.
29
+ 1. Read the `drift.md` entries and their classifications. Fold EVERY open entry
30
+ and accepted finding for the affected artifacts in ONE pass, never serially.
30
31
  2. If the user answered a drift question, encode that decision in `decisions.md`.
31
32
  3. Update `spec.md` (only the affected sections) and `plan.md`/`tasks.md` to match
32
33
  reality. Adjust acceptance criteria if they were wrong.
33
- 4. Mark the `drift.md` entry **resolved** with the resolution + date.
34
- 5. Resume at the corrected slice.
34
+ 4. Mark each `drift.md` entry **resolved** with the resolution + date.
35
+ 5. **Self-check the repaired candidate on the delta before handoff** — re-verify
36
+ every invariant the correction touched (acyclic dependency graph,
37
+ bidirectional traceability, Shared contract proof vs boundary set, sizing,
38
+ no correction-created regression) and record the evidence in the Plan
39
+ checkpoint; Vet's recheck verifies it rather than rediscovering the defect a
40
+ loop later.
41
+ 6. Resume at the corrected slice.
35
42
  Never quietly delete a requirement; use the marked action before contract edits.
36
43
 
37
44
  ## reorder
@@ -52,10 +52,14 @@ plan declares a root-authored executable workflow file, read
52
52
  - Use the lowest axis band; never average or round thin to ready. Search before
53
53
  asking and resolve reversible technical choices. Ask only human-owned choices.
54
54
  - Preserve a valid technical return cursor. Agent-owned `NEEDS REPLAN` returns
55
- internally to its caller, not to the human.
56
- - **Recovery recheck is bounded.** A valid cursor plus open fingerprint enters
57
- Recovery recheck; it does not start another Full Vet or repeat unaffected
58
- axes/reviewers.
55
+ internally to its caller, not to the human; on a direct invocation there is
56
+ no caller, so Vet becomes it record the cursor and invoke `/rite-plan`
57
+ repair inline under the same fingerprint caps.
58
+ - **Recovery recheck is bounded and batched.** A valid cursor plus open
59
+ fingerprints enters Recovery recheck; it does not start another Full Vet or
60
+ repeat unaffected axes/reviewers. One dispatch covers every open fingerprint
61
+ of the fold — each checked individually — with a mandatory correction-created
62
+ regression audit.
59
63
  <!-- workflow-artifact-adapter: {"module":"devrites-lib/reference/standards/workflow-artifacts.md","entry":"plan declares root-authored executable workflow file","action":"emit exact admission; stale/missing authority uses PLAN_VET_REPAIR","return":"Vet READY cursor or exact technical replan"} -->
60
64
  ## Workflow
61
65
 
@@ -73,10 +77,13 @@ plan declares a root-authored executable workflow file, read
73
77
  required account blocks.
74
78
  1b. **Recovery recheck.** Require valid return cursor, accepted prior finding,
75
79
  exact fingerprint/reproduction, repaired candidate identity, changed
76
- paths/criteria, and affected drift/evidence. Freeze that packet and dispatch
77
- each exact owning reviewer once, fresh/read-only, limited to it. Do not rerun
78
- broad inventory or unaffected reviewers. Close the prior fingerprint only
79
- with discriminating evidence. Otherwise record one no-progress outcome. A
80
+ paths/criteria, affected drift/evidence, and the recorded delta self-check.
81
+ Freeze that packet and dispatch each exact owning reviewer once,
82
+ fresh/read-only, limited to it all its open fingerprints in that dispatch.
83
+ Do not rerun broad inventory or unaffected reviewers. Close the prior
84
+ fingerprint only with discriminating evidence plus an explicit
85
+ correction-created regression verdict on the touched invariants (acyclic
86
+ deps, traceability, contract proof, sizing). Otherwise record one no-progress outcome. A
80
87
  different Critical/Important invariant needs exact evidence and a new
81
88
  fingerprint; a Suggestion, Nit, or FYI cannot keep recovery open. Reconcile
82
89
  shared artifact/readiness gates and return to caller or next repair.
@@ -119,11 +126,13 @@ plan declares a root-authored executable workflow file, read
119
126
  criterion needs positive, discriminating proof; every slice must be one-pass
120
127
  implementable; developer plans need a predicted scorecard. Durable commands
121
128
  are portable repository commands, not host wrappers.
122
- 7. **Narrow recheck after edits.** Dispatch exact plan reviewer once per
123
- correction/fingerprint (`per correction/fingerprint`) with accepted findings,
124
- changed paths/criteria, and new
125
- identity. Within one correction, no broad third loop. If it changes plan,
126
- fold again. A closed input plus a distinct Critical/Important invariant returns
129
+ 7. **Narrow recheck after edits.** Dispatch the exact plan reviewer once per
130
+ fold one dispatch covering every open fingerprint, preserving
131
+ per correction/fingerprint accounting (each checked individually with its
132
+ accepted findings, changed paths/criteria, new identity, and recorded delta
133
+ self-check); it must return an explicit correction-created regression
134
+ verdict, not only fingerprint closure. Within one correction, no broad
135
+ third loop. If it changes plan, fold again. A closed input plus a distinct Critical/Important invariant returns
127
136
  that new fingerprint as progress. Then close matrix and rerun ID/meaning audit.
128
137
  8. **Build readback and readiness.** Add a cited five-line readback to
129
138
  `eng-review.md` (artifacts.md §7 rows 1–5): outcome/ACs; IN/OUT/must-NOT; UI direction and architecture/
@@ -140,6 +140,10 @@ return an `Escalation`** when:
140
140
  scoped exception or the approach must change. Report the principle and conflict
141
141
  in `Escalation`.
142
142
 
143
+ A plan-gap or underspecification escalation populates `assumptions` with every
144
+ contract assumption already checked (verified|falsified); the orchestrator's
145
+ batch sweep covers only the unchecked remainder. Never a bare "plan is wrong".
146
+
143
147
  If an answer would change scope or acceptance, do **not** fold it into the slice.
144
148
  Return it in `Escalation` so the orchestrator can route it through the Spec Drift
145
149
  Guard (`/rite-plan repair`). Respect any AFK budget in the contract.
@@ -174,7 +178,7 @@ reuse: []
174
178
  conventions: []
175
179
  principles: []
176
180
  sources: []
177
- assumptions: []
181
+ assumptions: [] # plan-gap escalation: every checked contract assumption, verified|falsified
178
182
  decisions_stood: [] # irreversible-risk items go to escalation
179
183
  dead_ends: []
180
184
  escalation: <none | gate + crisp question + proposed answer>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: rite-build
3
- description: Build the next approved vertical slice with evidence. HITL one-slice default; AFK may chain serially; opt-in `--parallel N` (2≤N≤3) for path-disjoint worktrees.
3
+ description: Build the next approved vertical slice with evidence. HITL one-slice default; AFK may chain serially; opt-in `--parallel N` (2≤N≤10) for path-disjoint worktrees.
4
4
  argument-hint: "[--parallel N] [slice number or name]"
5
5
  user-invocable: true
6
6
  ---
@@ -10,7 +10,7 @@ user-invocable: true
10
10
  Build and prove one slice. HITL stops; a later user invocation starts the next.
11
11
  Explicit `.devrites/AFK` alone lets the controlling root chain pending slices
12
12
  serially under green proof, caps, and pause rules. Every wright returns after one slice.
13
- **Opt-in:** `/rite-build --parallel N` (2≤N≤3; N=1≡serial) follows
13
+ **Opt-in:** `/rite-build --parallel N` (2≤N≤10; N=1≡serial) follows
14
14
  [`reference/parallel-batch.md`](reference/parallel-batch.md)
15
15
  ([`one-slice-cycle.md`](reference/one-slice-cycle.md)).
16
16
 
@@ -38,8 +38,10 @@ Wright applies anti-slop; root verifies returns and never patches source.
38
38
  single-slice isolation when `wright-dispatch.md` preflight + reconcile hold.
39
39
  - Exact feature scope only; reject out-of-allowlist diffs; record adjacent issues.
40
40
  - Never rerun an unchanged check; re-prove after edits.
41
- - Unplanned dependency/design-system/gap/repair → Vet/Spec Drift Guard. Ask only
42
- for licensing/cost/security/product or explicit architecture-policy decisions.
41
+ - Unplanned dependency/design-system/gap/repair → Vet/Spec Drift Guard batch
42
+ sweep: every contract-assumption violation recorded before one folded
43
+ repair+vet. Ask only for licensing/cost/security/product or explicit
44
+ architecture-policy decisions.
43
45
  - Root never edits product source/tests (`.devrites/` + Workflow Artifact only).
44
46
  Wright is sole product writer; extras in returned paths/`git diff --name-only` hard-stop.
45
47
  - Principles bind; irreversible conflict needs human exception or stop.
@@ -55,9 +57,11 @@ Wright applies anti-slop; root verifies returns and never patches source.
55
57
  <!-- workflow-artifact-adapter: {"module":"devrites-lib/reference/standards/workflow-artifacts.md","entry":"Vet-ready admitted bytes require root authorship outside product wright","action":"ROOT_TRANSACTION; root writes only admitted .devrites/** targets","return":"saved Build slice cursor; wright product allowlist unchanged"} -->
56
58
  ## `--parallel N` (opt-in)
57
59
 
58
- Omitted/`1` ≡ serial; `2`/`3` → path-disjoint fan-out when eligible; else hard refuse.
59
- All-green serial integrate; one red/gap aborts. AFK charges after integrate only.
60
- Running lease blocks another `/rite-build`. Details: `parallel-batch.md`.
60
+ Omitted/`1` ≡ serial; `2`–`10` → path-disjoint fan-out when eligible; else hard refuse.
61
+ All-green serial integrate; one red/gap aborts. Abort with agent-owned plan
62
+ gaps continues via Spec Drift Guard (batch sweep, one folded plan repair + one
63
+ vet recheck inline); do not emit a human `Fix`. AFK charges after integrate only. Running lease blocks another
64
+ `/rite-build`. Details: `parallel-batch.md`.
61
65
 
62
66
  ## Execute and reply
63
67
 
@@ -3,7 +3,7 @@
3
3
  One wright dispatch builds one thin, proven slice. HITL stops; only explicit
4
4
  `.devrites/AFK` lets the controlling root chain another pending slice under the
5
5
  green-proof, cap, and pause rules. Each wright returns after exactly one slice.
6
- Opt-in fan-out: [`parallel-batch.md`](parallel-batch.md) (`--parallel N`); this is default.
6
+ This serial cycle is the default `/rite-build`. Opt-in fan-out: [`parallel-batch.md`](parallel-batch.md) (`--parallel N`).
7
7
 
8
8
  ## The cycle
9
9
 
@@ -38,8 +38,11 @@ you check yourself against: anything outside it is scope creep or a drift event.
38
38
 
39
39
  ## When the slice can't be completed cleanly
40
40
 
41
- - Discovered the plan is wrong → **Spec Drift Guard** (stop, record, classify, maybe
42
- ask, `/rite-plan` repair).
43
- - Slice is bigger than one cycle → stop and `/rite-plan reslice`.
44
- - Blocked on a failing dependencyrecord in `state.md`, `/rite-plan unblock`.
41
+ - Discovered the plan is wrong → **Spec Drift Guard** (record, classify;
42
+ sweep every remaining contract assumption, then one folded repair+vet inline;
43
+ ask only for product/policy/irreversible-risk).
44
+ - Slice is bigger than one cycle → `/rite-plan reslice` inline when AC is
45
+ preserved; do not emit a human Fix.
46
+ - Blocked on a failing dependency → record in `state.md`, `/rite-plan unblock`
47
+ inline when the reroute is technical.
45
48
  Never power through by guessing.