devrites 3.0.2 → 3.0.3

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 (48) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +1 -1
  3. package/docs/adr/0004-state-schema-phases-sections.md +44 -0
  4. package/docs/command-map.md +1 -1
  5. package/docs/engine/state-schema.md +15 -12
  6. package/docs/flow.md +1 -1
  7. package/docs/research/go-authoritative-workflow-schema-and-quality-2026-07-20.md +212 -0
  8. package/engine/hooks_workspace.go +7 -7
  9. package/engine/internal/gate/gate.go +4 -4
  10. package/engine/internal/gate/gate_test.go +2 -2
  11. package/engine/internal/lib/cursor_compat_test.go +29 -0
  12. package/engine/internal/lib/preamble.go +1 -1
  13. package/engine/internal/lib/preamble_questions_test.go +10 -0
  14. package/engine/internal/lib/progress.go +59 -20
  15. package/engine/internal/lib/resolve.go +15 -6
  16. package/engine/internal/lib/resolve_remediation_test.go +9 -0
  17. package/engine/internal/lib/tickafk.go +2 -2
  18. package/engine/internal/migrate/migrate.go +2 -33
  19. package/engine/internal/migrate/migrate_test.go +7 -1
  20. package/engine/internal/state/cmd/workflowmanifest/main.go +54 -0
  21. package/engine/internal/state/cursor.go +42 -7
  22. package/engine/internal/state/feature.go +1 -27
  23. package/engine/internal/state/schema.go +135 -20
  24. package/engine/internal/state/snapshot.go +49 -3
  25. package/engine/internal/state/state_test.go +71 -0
  26. package/engine/internal/state/workflow_manifest.json +310 -0
  27. package/engine/internal/workflow/commands.go +0 -36
  28. package/engine/internal/workflow/commands_test.go +0 -17
  29. package/engine/testdata/golden/TestParityProgress/arg=allbuilt.golden +1 -1
  30. package/engine/testdata/golden/TestParityProgress/arg=done.golden +1 -1
  31. package/engine/testdata/golden/TestParityProgress/arg=mid.golden +1 -1
  32. package/engine/testdata/golden/TestParityProgress/arg=nophase.golden +1 -1
  33. package/engine/testdata/golden/TestParityProgress/arg=noslice.golden +1 -1
  34. package/engine/testdata/golden/TestParityProgress/arg=plan.golden +1 -1
  35. package/engine/testdata/golden/TestParityProgress/arg=seal.golden +1 -1
  36. package/engine/tests/adr_0004_required_by_phase_test.go +1 -18
  37. package/engine/tests/lib_parity_test.go +1 -1
  38. package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +5 -3
  39. package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +5 -3
  40. package/pack/generated/codex/AGENTS.md +1 -1
  41. package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +5 -3
  42. package/package.json +1 -1
  43. package/scripts/codex-generate.sh +1 -1
  44. package/scripts/grade-feature.sh +5 -3
  45. package/scripts/run-outcome-evals.sh +21 -0
  46. package/scripts/validate-workspace-schema.py +9 -73
  47. package/scripts/validate.sh +10 -0
  48. package/scripts/workflow_schema.py +69 -0
@@ -0,0 +1,310 @@
1
+ {
2
+ "generatedBy": "go generate ./internal/state; DO NOT EDIT",
3
+ "schemaVersion": 1,
4
+ "phases": [
5
+ {
6
+ "id": "frame",
7
+ "resumeVerb": "frame",
8
+ "workspaceRequired": [
9
+ "state.md"
10
+ ]
11
+ },
12
+ {
13
+ "id": "spec",
14
+ "resumeVerb": "spec",
15
+ "aliases": [
16
+ "specced",
17
+ "specifying"
18
+ ],
19
+ "workspaceRequired": [
20
+ "brief.md",
21
+ "spec.md",
22
+ "state.md",
23
+ "decisions.md",
24
+ "assumptions.md",
25
+ "questions.md"
26
+ ]
27
+ },
28
+ {
29
+ "id": "temper",
30
+ "resumeVerb": "temper",
31
+ "aliases": [
32
+ "tempered",
33
+ "tempering"
34
+ ],
35
+ "workspaceRequired": [
36
+ "brief.md",
37
+ "spec.md",
38
+ "state.md",
39
+ "decisions.md",
40
+ "assumptions.md",
41
+ "questions.md"
42
+ ]
43
+ },
44
+ {
45
+ "id": "define",
46
+ "resumeVerb": "define",
47
+ "aliases": [
48
+ "defined",
49
+ "defining"
50
+ ],
51
+ "workspaceRequired": [
52
+ "brief.md",
53
+ "spec.md",
54
+ "architecture.md",
55
+ "plan.md",
56
+ "tasks.md",
57
+ "traceability.md",
58
+ "state.md",
59
+ "decisions.md",
60
+ "assumptions.md",
61
+ "questions.md"
62
+ ],
63
+ "blocksOpenQuestions": true
64
+ },
65
+ {
66
+ "id": "plan",
67
+ "resumeVerb": "define",
68
+ "aliases": [
69
+ "planned",
70
+ "planning"
71
+ ],
72
+ "workspaceRequired": [
73
+ "brief.md",
74
+ "spec.md",
75
+ "architecture.md",
76
+ "plan.md",
77
+ "tasks.md",
78
+ "traceability.md",
79
+ "state.md",
80
+ "decisions.md",
81
+ "assumptions.md",
82
+ "questions.md"
83
+ ],
84
+ "blocksOpenQuestions": true
85
+ },
86
+ {
87
+ "id": "vet",
88
+ "resumeVerb": "vet",
89
+ "aliases": [
90
+ "vetted",
91
+ "vetting"
92
+ ],
93
+ "workspaceRequired": [
94
+ "brief.md",
95
+ "spec.md",
96
+ "architecture.md",
97
+ "plan.md",
98
+ "tasks.md",
99
+ "traceability.md",
100
+ "state.md",
101
+ "decisions.md",
102
+ "assumptions.md",
103
+ "questions.md"
104
+ ],
105
+ "blocksOpenQuestions": true
106
+ },
107
+ {
108
+ "id": "build",
109
+ "resumeVerb": "build",
110
+ "aliases": [
111
+ "building",
112
+ "wip",
113
+ "in",
114
+ "in-progress"
115
+ ],
116
+ "workspaceRequired": [
117
+ "brief.md",
118
+ "spec.md",
119
+ "architecture.md",
120
+ "plan.md",
121
+ "tasks.md",
122
+ "traceability.md",
123
+ "state.md",
124
+ "decisions.md",
125
+ "assumptions.md",
126
+ "questions.md"
127
+ ],
128
+ "blocksOpenQuestions": true
129
+ },
130
+ {
131
+ "id": "converge",
132
+ "resumeVerb": "converge",
133
+ "aliases": [
134
+ "converged",
135
+ "converging"
136
+ ],
137
+ "workspaceRequired": [
138
+ "brief.md",
139
+ "spec.md",
140
+ "architecture.md",
141
+ "plan.md",
142
+ "tasks.md",
143
+ "traceability.md",
144
+ "state.md",
145
+ "decisions.md",
146
+ "assumptions.md",
147
+ "questions.md"
148
+ ],
149
+ "blocksOpenQuestions": true
150
+ },
151
+ {
152
+ "id": "prove",
153
+ "resumeVerb": "prove",
154
+ "aliases": [
155
+ "proving",
156
+ "proven",
157
+ "testing"
158
+ ],
159
+ "workspaceRequired": [
160
+ "brief.md",
161
+ "spec.md",
162
+ "architecture.md",
163
+ "plan.md",
164
+ "tasks.md",
165
+ "traceability.md",
166
+ "state.md",
167
+ "decisions.md",
168
+ "assumptions.md",
169
+ "questions.md",
170
+ "evidence.md",
171
+ "touched-files.md"
172
+ ],
173
+ "proofRequired": true,
174
+ "blocksOpenQuestions": true
175
+ },
176
+ {
177
+ "id": "polish",
178
+ "resumeVerb": "polish",
179
+ "aliases": [
180
+ "polished",
181
+ "polishing"
182
+ ],
183
+ "workspaceRequired": [
184
+ "brief.md",
185
+ "spec.md",
186
+ "architecture.md",
187
+ "plan.md",
188
+ "tasks.md",
189
+ "traceability.md",
190
+ "state.md",
191
+ "decisions.md",
192
+ "assumptions.md",
193
+ "questions.md",
194
+ "evidence.md",
195
+ "touched-files.md"
196
+ ],
197
+ "proofRequired": true,
198
+ "blocksOpenQuestions": true
199
+ },
200
+ {
201
+ "id": "review",
202
+ "resumeVerb": "review",
203
+ "aliases": [
204
+ "reviewed",
205
+ "reviewing"
206
+ ],
207
+ "workspaceRequired": [
208
+ "brief.md",
209
+ "spec.md",
210
+ "architecture.md",
211
+ "plan.md",
212
+ "tasks.md",
213
+ "traceability.md",
214
+ "state.md",
215
+ "decisions.md",
216
+ "assumptions.md",
217
+ "questions.md",
218
+ "evidence.md",
219
+ "touched-files.md"
220
+ ],
221
+ "proofRequired": true,
222
+ "blocksOpenQuestions": true
223
+ },
224
+ {
225
+ "id": "seal",
226
+ "resumeVerb": "seal",
227
+ "aliases": [
228
+ "sealed",
229
+ "sealing"
230
+ ],
231
+ "workspaceRequired": [
232
+ "brief.md",
233
+ "spec.md",
234
+ "architecture.md",
235
+ "plan.md",
236
+ "tasks.md",
237
+ "traceability.md",
238
+ "state.md",
239
+ "decisions.md",
240
+ "assumptions.md",
241
+ "questions.md",
242
+ "evidence.md",
243
+ "touched-files.md"
244
+ ],
245
+ "proofRequired": true,
246
+ "blocksOpenQuestions": true,
247
+ "shippable": true
248
+ },
249
+ {
250
+ "id": "ship",
251
+ "resumeVerb": "ship",
252
+ "aliases": [
253
+ "shipped",
254
+ "shipping"
255
+ ],
256
+ "workspaceRequired": [
257
+ "brief.md",
258
+ "spec.md",
259
+ "architecture.md",
260
+ "plan.md",
261
+ "tasks.md",
262
+ "traceability.md",
263
+ "state.md",
264
+ "decisions.md",
265
+ "assumptions.md",
266
+ "questions.md",
267
+ "evidence.md",
268
+ "touched-files.md"
269
+ ],
270
+ "proofRequired": true,
271
+ "blocksOpenQuestions": true,
272
+ "shippable": true
273
+ },
274
+ {
275
+ "id": "done",
276
+ "aliases": [
277
+ "closed",
278
+ "complete",
279
+ "completed"
280
+ ],
281
+ "workspaceRequired": [
282
+ "brief.md",
283
+ "spec.md",
284
+ "architecture.md",
285
+ "plan.md",
286
+ "tasks.md",
287
+ "traceability.md",
288
+ "state.md",
289
+ "decisions.md",
290
+ "assumptions.md",
291
+ "questions.md",
292
+ "evidence.md",
293
+ "touched-files.md"
294
+ ],
295
+ "proofRequired": true,
296
+ "blocksOpenQuestions": true,
297
+ "shippable": true
298
+ }
299
+ ],
300
+ "cursorKeyAliases": [
301
+ {
302
+ "alias": "nextstep",
303
+ "canonical": "next_action"
304
+ },
305
+ {
306
+ "alias": "qid",
307
+ "canonical": "question_id"
308
+ }
309
+ ]
310
+ }
@@ -12,22 +12,6 @@ type Command struct {
12
12
  Codex string
13
13
  }
14
14
 
15
- var phaseToVerb = map[string]string{
16
- "frame": "frame",
17
- "spec": "spec",
18
- "temper": "temper",
19
- "define": "define",
20
- "plan": "define", // plan is the artifact state produced by rite-define.
21
- "vet": "vet",
22
- "build": "build",
23
- "converge": "converge",
24
- "prove": "prove",
25
- "polish": "polish",
26
- "review": "review",
27
- "seal": "seal",
28
- "ship": "ship",
29
- }
30
-
31
15
  // ForVerb returns the Claude and Codex forms for a public rite verb. The empty
32
16
  // verb returns an empty command so callers can omit suggestions safely.
33
17
  func ForVerb(verb string) Command {
@@ -52,12 +36,6 @@ func ForAction(action string) Command {
52
36
  return Command{}
53
37
  }
54
38
 
55
- // ForPhase returns the next public command for a workflow phase.
56
- func ForPhase(phase string) Command {
57
- verb := phaseToVerb[strings.TrimSpace(strings.ToLower(phase))]
58
- return ForVerb(verb)
59
- }
60
-
61
39
  // Both renders a command in host-neutral prose for engine stderr/stdout messages.
62
40
  func (c Command) Both() string {
63
41
  if c.Verb == "" {
@@ -65,17 +43,3 @@ func (c Command) Both() string {
65
43
  }
66
44
  return c.Claude + " (Claude) / " + c.Codex + " (Codex)"
67
45
  }
68
-
69
- // ClaudeOrCodex returns the command for a known harness. Empty/unknown harnesses
70
- // deliberately get the host-neutral rendering so CLI output remains safe when the
71
- // engine is run outside a hook.
72
- func (c Command) ClaudeOrCodex(harness string) string {
73
- switch strings.ToLower(strings.TrimSpace(harness)) {
74
- case "claude", "claude-code", "claudecode":
75
- return c.Claude
76
- case "codex":
77
- return c.Codex
78
- default:
79
- return c.Both()
80
- }
81
- }
@@ -16,20 +16,3 @@ func TestForActionExtractsCanonicalInvocation(t *testing.T) {
16
16
  }
17
17
  }
18
18
  }
19
-
20
- func TestForPhaseCoversCurrentLifecycle(t *testing.T) {
21
- for _, phase := range []string{
22
- "frame", "spec", "temper", "define", "vet", "build", "converge",
23
- "prove", "polish", "review", "seal", "ship",
24
- } {
25
- if got := ForPhase(phase).Verb; got != phase {
26
- t.Fatalf("ForPhase(%q).Verb=%q, want %q", phase, got, phase)
27
- }
28
- }
29
- if got := ForPhase("plan").Verb; got != "define" {
30
- t.Fatalf("ForPhase(plan).Verb=%q, want define compatibility route", got)
31
- }
32
- if got := ForPhase("done").Verb; got != "" {
33
- t.Fatalf("ForPhase(done).Verb=%q, want empty", got)
34
- }
35
- }
@@ -1,4 +1,4 @@
1
1
  exit 0
2
2
  ── rite-build ─────────
3
3
  Slices 2/2 ██████████ ✅ ALL BUILT
4
- Flow spec ✓ define ✓ build ◉ prove ○ polish ○ review ○ seal ○ ship ○
4
+ Flow spec ✓ define ✓ plan ✓ build ◉ prove ○ polish ○ review ○ seal ○ ship ○
@@ -1,3 +1,3 @@
1
1
  exit 0
2
2
  ── rite-done ─────────
3
- Flow spec ✓ define ✓ build ✓ prove ✓ polish ✓ review ✓ seal ✓ ship ✓
3
+ Flow spec ✓ define ✓ plan ✓ build ✓ prove ✓ polish ✓ review ✓ seal ✓ ship ✓
@@ -1,4 +1,4 @@
1
1
  exit 0
2
2
  ── rite-build ─────────
3
3
  Slice 2/3 ███████░░░ detail ✓
4
- Flow spec ✓ temper ✓ define ✓ vet ✓ build ◉ prove ○ polish ○ review ○ seal ○ ship ○
4
+ Flow spec ✓ temper ✓ define ✓ plan ✓ vet ✓ build ◉ prove ○ polish ○ review ○ seal ○ ship ○
@@ -1,3 +1,3 @@
1
1
  exit 0
2
2
  ── rite-spec ─────────
3
- Flow spec ◉ define ○ build ○ prove ○ polish ○ review ○ seal ○ ship ○
3
+ Flow spec ◉ define ○ plan ○ build ○ prove ○ polish ○ review ○ seal ○ ship ○
@@ -1,3 +1,3 @@
1
1
  exit 0
2
2
  ── rite-spec ─────────
3
- Flow spec ◉ define ○ build ○ prove ○ polish ○ review ○ seal ○ ship ○
3
+ Flow spec ◉ define ○ plan ○ build ○ prove ○ polish ○ review ○ seal ○ ship ○
@@ -1,4 +1,4 @@
1
1
  exit 0
2
2
  ── rite-plan ─────────
3
3
  Slice 2/3 ███████░░░ detail ✓
4
- Flow spec ✓ define ✓ build ◉ prove ○ polish ○ review ○ seal ○ ship ○
4
+ Flow spec ✓ define ✓ planbuild ○ prove ○ polish ○ review ○ seal ○ ship ○
@@ -1,3 +1,3 @@
1
1
  exit 0
2
2
  ── rite-seal ─────────
3
- Flow spec ✓ define ✓ build ✓ prove ✓ polish ✓ review ✓ seal ◉ ship ○
3
+ Flow spec ✓ define ✓ plan ✓ build ✓ prove ✓ polish ✓ review ✓ seal ◉ ship ○
@@ -12,25 +12,8 @@ import (
12
12
  "github.com/devrites/devrites/internal/state"
13
13
  )
14
14
 
15
- // phaseArc is the canonical order the lifecycle advances through (ADR-0004).
16
- var phaseArc = []state.Phase{
17
- state.PhaseFrame,
18
- state.PhaseSpec,
19
- state.PhaseTemper,
20
- state.PhaseDefine,
21
- state.PhasePlan,
22
- state.PhaseVet,
23
- state.PhaseBuild,
24
- state.PhaseConverge,
25
- state.PhaseProve,
26
- state.PhasePolish,
27
- state.PhaseReview,
28
- state.PhaseSeal,
29
- state.PhaseShip,
30
- state.PhaseDone,
31
- }
32
-
33
15
  func TestADR0004RequiredSectionsAreAdditiveDownTheArc(t *testing.T) {
16
+ phaseArc := state.LifecyclePhases()
34
17
  for _, p := range phaseArc {
35
18
  if !state.KnownPhase(p) {
36
19
  t.Fatalf("phase %q in the arc is not a known phase", p)
@@ -795,7 +795,7 @@ func TestParityPreamble(t *testing.T) {
795
795
  //
796
796
  // Golden: the header rule width, the slice meter (round-half math, ✅ ALL BUILT
797
797
  // vs the last-built tail), and the flow ribbon (conditional temper/vet, the
798
- // plan→build and done cursor rules) are checked against golden snapshots.
798
+ // explicit plan and terminal done cursor rules) are checked against golden snapshots.
799
799
 
800
800
  func TestParityProgress(t *testing.T) {
801
801
  work := t.TempDir()
@@ -9,9 +9,11 @@ workspace map; `proof.md` may stand in for `evidence.md`.
9
9
 
10
10
  | Phase | Required artifacts |
11
11
  | --- | --- |
12
+ | frame | `state.md` |
12
13
  | spec | `README.md`/`index.md`/`feature.md`, `brief.md`, `spec.md`, `state.md`, `decisions.md`, `assumptions.md`, `questions.md` |
13
- | define/plan/vet/build | spec artifacts plus `architecture.md`, `plan.md`, `tasks.md`, `traceability.md` |
14
- | prove/polish/review/seal/ship | plan artifacts plus `evidence.md`/`proof.md`, `touched-files.md` |
14
+ | temper | spec artifacts |
15
+ | define/plan/vet/build/converge | spec artifacts plus `architecture.md`, `plan.md`, `tasks.md`, `traceability.md` |
16
+ | prove/polish/review/seal/ship/done | plan artifacts plus `evidence.md`/`proof.md`, `touched-files.md` |
15
17
  | conditional | `flows.md` when diagrams clarify; `design-brief.md` and `browser-evidence.md` for UI; `drift.md` for drift; `handoff.md` only when requested; `references.md` + `references/` when references exist |
16
18
 
17
19
  ## What each file owns
@@ -33,7 +35,7 @@ workspace map; `proof.md` may stand in for `evidence.md`.
33
35
  | `evidence.md` / `proof.md` | `EVID-###` command/action, result, timestamp if available, related AC/slice IDs, limitation | 280 lines |
34
36
  | `browser-evidence.md` | UI route/viewports/screenshots/console/network/interactions and Visual Verdict | 220 lines |
35
37
  | `drift.md` | `DRIFT-###` spec/plan drift and resolution | 160 lines |
36
- | `touched-files.md` | implementation files, slice ownership, reason, and a concern-ordered `## Review trail` of `path:line` stops for human review | 180 lines |
38
+ | `touched-files.md` | implementation files, slice ownership, reason, and a concern-ordered `## Review trail` of `path:line` stops for human review | 160 lines |
37
39
  | `design-brief.md` | UI design direction, states, interaction model | 160 lines |
38
40
  | `handoff.md` | cold-resume guide: current objective, last completed slice, next action, blockers, read-next links | 120 lines |
39
41
 
@@ -9,9 +9,11 @@ workspace map; `proof.md` may stand in for `evidence.md`.
9
9
 
10
10
  | Phase | Required artifacts |
11
11
  | --- | --- |
12
+ | frame | `state.md` |
12
13
  | spec | `README.md`/`index.md`/`feature.md`, `brief.md`, `spec.md`, `state.md`, `decisions.md`, `assumptions.md`, `questions.md` |
13
- | define/plan/vet/build | spec artifacts plus `architecture.md`, `plan.md`, `tasks.md`, `traceability.md` |
14
- | prove/polish/review/seal/ship | plan artifacts plus `evidence.md`/`proof.md`, `touched-files.md` |
14
+ | temper | spec artifacts |
15
+ | define/plan/vet/build/converge | spec artifacts plus `architecture.md`, `plan.md`, `tasks.md`, `traceability.md` |
16
+ | prove/polish/review/seal/ship/done | plan artifacts plus `evidence.md`/`proof.md`, `touched-files.md` |
15
17
  | conditional | `flows.md` when diagrams clarify; `design-brief.md` and `browser-evidence.md` for UI; `drift.md` for drift; `handoff.md` only when requested; `references.md` + `references/` when references exist |
16
18
 
17
19
  ## What each file owns
@@ -33,7 +35,7 @@ workspace map; `proof.md` may stand in for `evidence.md`.
33
35
  | `evidence.md` / `proof.md` | `EVID-###` command/action, result, timestamp if available, related AC/slice IDs, limitation | 280 lines |
34
36
  | `browser-evidence.md` | UI route/viewports/screenshots/console/network/interactions and Visual Verdict | 220 lines |
35
37
  | `drift.md` | `DRIFT-###` spec/plan drift and resolution | 160 lines |
36
- | `touched-files.md` | implementation files, slice ownership, reason, and a concern-ordered `## Review trail` of `path:line` stops for human review | 180 lines |
38
+ | `touched-files.md` | implementation files, slice ownership, reason, and a concern-ordered `## Review trail` of `path:line` stops for human review | 160 lines |
37
39
  | `design-brief.md` | UI design direction, states, interaction model | 160 lines |
38
40
  | `handoff.md` | cold-resume guide: current objective, last completed slice, next action, blockers, read-next links | 120 lines |
39
41
 
@@ -18,6 +18,6 @@ This project has DevRites installed for both Claude Code and Codex.
18
18
  ## Workflow contract
19
19
 
20
20
  - Keep all feature state in `.devrites/work/<slug>/` and preserve `.devrites/ACTIVE`.
21
- - Follow the DevRites lifecycle: spec -> define -> build -> prove -> polish -> review -> seal -> ship.
21
+ - Follow the DevRites lifecycle: frame -> spec -> temper -> define -> plan -> vet -> build -> converge -> prove -> polish -> review -> seal -> ship -> done.
22
22
  - Claims of completion need recorded evidence in the feature workspace, not confidence alone.
23
23
  <!-- END DEVRITES CODEX -->
@@ -9,9 +9,11 @@ workspace map; `proof.md` may stand in for `evidence.md`.
9
9
 
10
10
  | Phase | Required artifacts |
11
11
  | --- | --- |
12
+ | frame | `state.md` |
12
13
  | spec | `README.md`/`index.md`/`feature.md`, `brief.md`, `spec.md`, `state.md`, `decisions.md`, `assumptions.md`, `questions.md` |
13
- | define/plan/vet/build | spec artifacts plus `architecture.md`, `plan.md`, `tasks.md`, `traceability.md` |
14
- | prove/polish/review/seal/ship | plan artifacts plus `evidence.md`/`proof.md`, `touched-files.md` |
14
+ | temper | spec artifacts |
15
+ | define/plan/vet/build/converge | spec artifacts plus `architecture.md`, `plan.md`, `tasks.md`, `traceability.md` |
16
+ | prove/polish/review/seal/ship/done | plan artifacts plus `evidence.md`/`proof.md`, `touched-files.md` |
15
17
  | conditional | `flows.md` when diagrams clarify; `design-brief.md` and `browser-evidence.md` for UI; `drift.md` for drift; `handoff.md` only when requested; `references.md` + `references/` when references exist |
16
18
 
17
19
  ## What each file owns
@@ -33,7 +35,7 @@ workspace map; `proof.md` may stand in for `evidence.md`.
33
35
  | `evidence.md` / `proof.md` | `EVID-###` command/action, result, timestamp if available, related AC/slice IDs, limitation | 280 lines |
34
36
  | `browser-evidence.md` | UI route/viewports/screenshots/console/network/interactions and Visual Verdict | 220 lines |
35
37
  | `drift.md` | `DRIFT-###` spec/plan drift and resolution | 160 lines |
36
- | `touched-files.md` | implementation files, slice ownership, reason, and a concern-ordered `## Review trail` of `path:line` stops for human review | 180 lines |
38
+ | `touched-files.md` | implementation files, slice ownership, reason, and a concern-ordered `## Review trail` of `path:line` stops for human review | 160 lines |
37
39
  | `design-brief.md` | UI design direction, states, interaction model | 160 lines |
38
40
  | `handoff.md` | cold-resume guide: current objective, last completed slice, next action, blockers, read-next links | 120 lines |
39
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devrites",
3
- "version": "3.0.2",
3
+ "version": "3.0.3",
4
4
  "description": "DevRites — disciplined senior-engineer workflow skills pack for Claude Code and Codex",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://github.com/ViktorsBaikers/DevRites#readme",
@@ -132,7 +132,7 @@ This project has DevRites installed for both Claude Code and Codex.
132
132
  ## Workflow contract
133
133
 
134
134
  - Keep all feature state in `.devrites/work/<slug>/` and preserve `.devrites/ACTIVE`.
135
- - Follow the DevRites lifecycle: spec -> define -> build -> prove -> polish -> review -> seal -> ship.
135
+ - Follow the DevRites lifecycle: frame -> spec -> temper -> define -> plan -> vet -> build -> converge -> prove -> polish -> review -> seal -> ship -> done.
136
136
  - Claims of completion need recorded evidence in the feature workspace, not confidence alone.
137
137
  <!-- END DEVRITES CODEX -->
138
138
  EOF
@@ -77,9 +77,11 @@ fi
77
77
 
78
78
  # 7 — state phase / status
79
79
  if [ -f "$st" ]; then
80
- sfield() { awk -v k="$1" 'match($0,"^[[:space:]]*-?[[:space:]]*" k ":[[:space:]]*"){r=substr($0,RLENGTH+1); sub(/[[:space:]]*(#|\|).*$/,"",r); sub(/[[:space:]]+$/,"",r); print r; exit}' "$st"; }
81
- ph="$(sfield Phase)"; stt="$(sfield Status)"
82
- case "$ph" in seal|ship|done) ;; *) problems+=("state.md Phase='${ph}' (expected seal/ship/done)") ;; esac
80
+ ph="$(python3 "$ROOT/scripts/workflow_schema.py" field "$st" phase 2>/dev/null || true)"
81
+ stt="$(python3 "$ROOT/scripts/workflow_schema.py" field "$st" status 2>/dev/null || true)"
82
+ if ! python3 "$ROOT/scripts/workflow_schema.py" phase-property "$ph" shippable; then
83
+ problems+=("state.md Phase='${ph}' (expected a shippable phase)")
84
+ fi
83
85
  case "$stt" in awaiting_human|blocked) problems+=("state.md Status='${stt}' (not shippable)") ;; esac
84
86
  else
85
87
  problems+=("state.md missing")
@@ -23,6 +23,27 @@ else
23
23
  echo " FAIL — a known-shippable workspace should grade GO"; fail=1
24
24
  fi
25
25
 
26
+ echo
27
+ echo "== grade synthetic/canonical-cursor (expect GO) =="
28
+ canonical="$tmp/canonical-cursor"
29
+ mkdir -p "$canonical"
30
+ cp -R "$good/." "$canonical/"
31
+ cat > "$canonical/state.md" <<'MD'
32
+ # State
33
+
34
+ ## Cursor
35
+ | Key | Value |
36
+ | --- | --- |
37
+ | phase | done |
38
+ | status | done |
39
+ | next_action | archived |
40
+ MD
41
+ if bash "$GRADER" "$canonical"; then
42
+ echo " PASS — canonical cursor graded GO"
43
+ else
44
+ echo " FAIL — canonical cursor should grade GO"; fail=1
45
+ fi
46
+
26
47
  echo
27
48
  echo "== grade golden/blocked-feature (expect NO-GO) =="
28
49
  if bash "$GRADER" "$bad"; then