@turri-dev/cli 0.1.27 → 0.1.28-next.d5f2680

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 (216) hide show
  1. package/README.md +6 -6
  2. package/dist/advisor-chat.d.ts +63 -0
  3. package/dist/advisor-chat.js +290 -0
  4. package/dist/background-skills.d.ts +53 -0
  5. package/dist/background-skills.js +121 -0
  6. package/dist/bedrock-region.d.ts +66 -0
  7. package/dist/bedrock-region.js +144 -0
  8. package/dist/btw.d.ts +1 -1
  9. package/dist/btw.js +1 -1
  10. package/dist/change-plain-cli.js +20 -13
  11. package/dist/chat-idle.d.ts +7 -0
  12. package/dist/chat-idle.js +20 -0
  13. package/dist/chats.d.ts +10 -0
  14. package/dist/chats.js +23 -0
  15. package/dist/cli-options.d.ts +1 -2
  16. package/dist/cli-options.js +2 -7
  17. package/dist/cli.js +11 -3
  18. package/dist/config-command.d.ts +14 -0
  19. package/dist/config-command.js +35 -15
  20. package/dist/config-edit.d.ts +3 -3
  21. package/dist/config-edit.js +16 -12
  22. package/dist/config.d.ts +54 -34
  23. package/dist/config.js +40 -44
  24. package/dist/conform-cli.js +12 -10
  25. package/dist/conformance-switch.d.ts +34 -0
  26. package/dist/conformance-switch.js +108 -0
  27. package/dist/cultivate-cli.js +15 -5
  28. package/dist/drift-cli.js +2 -0
  29. package/dist/extension.d.ts +15 -0
  30. package/dist/extension.js +260 -83
  31. package/dist/host-session.d.ts +26 -0
  32. package/dist/host-session.js +30 -2
  33. package/dist/host.d.ts +5 -2
  34. package/dist/host.js +7 -1
  35. package/dist/init-config.d.ts +1 -1
  36. package/dist/init-config.js +20 -11
  37. package/dist/loop-cli.d.ts +3 -3
  38. package/dist/loop-cli.js +13 -16
  39. package/dist/loop-tools.js +18 -10
  40. package/dist/model-check.d.ts +8 -3
  41. package/dist/model-check.js +13 -8
  42. package/dist/new-project.js +12 -8
  43. package/dist/{validate-cli.js → parse-cli.js} +11 -5
  44. package/dist/parse-tool.d.ts +9 -0
  45. package/dist/parse-tool.js +33 -0
  46. package/dist/pi-launch.js +1 -1
  47. package/dist/plain/check.d.ts +53 -6
  48. package/dist/plain/check.js +217 -24
  49. package/dist/plain/concepts.d.ts +8 -0
  50. package/dist/plain/concepts.js +66 -23
  51. package/dist/plain/cycles.d.ts +21 -0
  52. package/dist/plain/cycles.js +190 -0
  53. package/dist/plain/errors.d.ts +4 -0
  54. package/dist/plain/errors.js +7 -0
  55. package/dist/plain/files.d.ts +18 -1
  56. package/dist/plain/files.js +39 -2
  57. package/dist/plain/graph.d.ts +33 -4
  58. package/dist/plain/graph.js +60 -12
  59. package/dist/plain/highlight.d.ts +3 -2
  60. package/dist/plain/highlight.js +4 -3
  61. package/dist/plain/index.d.ts +8 -5
  62. package/dist/plain/index.js +8 -5
  63. package/dist/plain/liquid.js +1 -6
  64. package/dist/plain/markdown.d.ts +32 -3
  65. package/dist/plain/markdown.js +146 -24
  66. package/dist/plain/module-concepts.js +2 -2
  67. package/dist/plain/parser.d.ts +83 -28
  68. package/dist/plain/parser.js +381 -260
  69. package/dist/plain/plain.tmLanguage.json +29 -3
  70. package/dist/plain/project.d.ts +48 -0
  71. package/dist/plain/project.js +155 -0
  72. package/dist/plain/spec.d.ts +90 -28
  73. package/dist/plain/spec.js +107 -133
  74. package/dist/plain/test-plain-file.d.ts +59 -0
  75. package/dist/plain/test-plain-file.js +232 -0
  76. package/dist/regenerate/activity.d.ts +20 -9
  77. package/dist/regenerate/activity.js +11 -4
  78. package/dist/regenerate/advisor-records.d.ts +93 -0
  79. package/dist/regenerate/advisor-records.js +110 -0
  80. package/dist/regenerate/advisor-runs.d.ts +87 -0
  81. package/dist/regenerate/advisor-runs.js +327 -0
  82. package/dist/regenerate/base-folder.d.ts +68 -0
  83. package/dist/regenerate/base-folder.js +168 -0
  84. package/dist/regenerate/cases.d.ts +9 -6
  85. package/dist/regenerate/cases.js +70 -14
  86. package/dist/regenerate/change-view.d.ts +8 -3
  87. package/dist/regenerate/change-view.js +71 -22
  88. package/dist/regenerate/chunk-plan.d.ts +36 -15
  89. package/dist/regenerate/chunk-plan.js +165 -59
  90. package/dist/regenerate/conform.d.ts +3 -0
  91. package/dist/regenerate/conform.js +6 -5
  92. package/dist/regenerate/conformance-agents.d.ts +18 -39
  93. package/dist/regenerate/conformance-agents.js +60 -88
  94. package/dist/regenerate/conformance.d.ts +23 -13
  95. package/dist/regenerate/conformance.js +119 -82
  96. package/dist/regenerate/diff-view.d.ts +1 -1
  97. package/dist/regenerate/diff-view.js +20 -4
  98. package/dist/regenerate/drift.d.ts +47 -15
  99. package/dist/regenerate/drift.js +101 -30
  100. package/dist/regenerate/jobs.d.ts +2 -2
  101. package/dist/regenerate/jobs.js +1 -1
  102. package/dist/regenerate/ledger.d.ts +19 -0
  103. package/dist/regenerate/loop.d.ts +62 -43
  104. package/dist/regenerate/loop.js +472 -341
  105. package/dist/regenerate/paths.d.ts +4 -0
  106. package/dist/regenerate/paths.js +7 -1
  107. package/dist/regenerate/plain-palette.js +2 -0
  108. package/dist/regenerate/prompt.d.ts +57 -19
  109. package/dist/regenerate/prompt.js +157 -122
  110. package/dist/regenerate/records.d.ts +43 -12
  111. package/dist/regenerate/records.js +102 -88
  112. package/dist/regenerate/regenerate.js +29 -11
  113. package/dist/regenerate/regression.d.ts +4 -4
  114. package/dist/regenerate/regression.js +14 -10
  115. package/dist/regenerate/renames.d.ts +42 -0
  116. package/dist/regenerate/renames.js +185 -0
  117. package/dist/regenerate/requires.d.ts +1 -1
  118. package/dist/regenerate/requires.js +10 -3
  119. package/dist/regenerate/resources.d.ts +5 -3
  120. package/dist/regenerate/resources.js +4 -4
  121. package/dist/regenerate/scripts-being-written.d.ts +19 -0
  122. package/dist/regenerate/scripts-being-written.js +30 -0
  123. package/dist/regenerate/spec-map-view.d.ts +2 -2
  124. package/dist/regenerate/spec-map-view.js +46 -15
  125. package/dist/regenerate/spec-map.d.ts +27 -5
  126. package/dist/regenerate/spec-map.js +92 -60
  127. package/dist/regenerate/spec-steps.d.ts +48 -5
  128. package/dist/regenerate/spec-steps.js +213 -28
  129. package/dist/regenerate/state.d.ts +4 -3
  130. package/dist/regenerate/stop-report.d.ts +1 -1
  131. package/dist/regenerate/stop-report.js +10 -10
  132. package/dist/regenerate/test-advisor.d.ts +101 -0
  133. package/dist/regenerate/test-advisor.js +379 -0
  134. package/dist/regenerate/test-kinds.d.ts +71 -28
  135. package/dist/regenerate/test-kinds.js +110 -63
  136. package/dist/regenerate/test-scripts.d.ts +2 -0
  137. package/dist/regenerate/test-scripts.js +4 -0
  138. package/dist/regenerate/testing-steps.d.ts +41 -0
  139. package/dist/regenerate/testing-steps.js +110 -0
  140. package/dist/regenerate/testing.d.ts +1 -1
  141. package/dist/regenerate/testing.js +5 -4
  142. package/dist/regenerate/unit-review.d.ts +1 -1
  143. package/dist/regenerate/unit-review.js +3 -3
  144. package/dist/regenerate-cli.js +11 -12
  145. package/dist/release-agent.js +4 -0
  146. package/dist/release-cli.js +2 -0
  147. package/dist/release-tools.js +2 -0
  148. package/dist/run-report.d.ts +2 -2
  149. package/dist/run-report.js +4 -3
  150. package/dist/self-invocation.d.ts +1 -1
  151. package/dist/self-invocation.js +1 -1
  152. package/dist/sentinel.js +1 -1
  153. package/dist/setup.d.ts +10 -0
  154. package/dist/setup.js +52 -4
  155. package/dist/skill.d.ts +10 -0
  156. package/dist/skill.js +6 -0
  157. package/dist/skills.js +3 -1
  158. package/dist/spec-tools.js +21 -31
  159. package/dist/test-plain-files.d.ts +41 -0
  160. package/dist/test-plain-files.js +177 -0
  161. package/docs/README.md +3 -1
  162. package/docs/authoring-plain.md +46 -13
  163. package/docs/chats.md +3 -1
  164. package/docs/config.md +20 -15
  165. package/docs/deploy.md +1 -1
  166. package/docs/development.md +2 -1
  167. package/docs/headless.md +15 -18
  168. package/docs/hosting.md +28 -12
  169. package/docs/installation.md +1 -0
  170. package/docs/parser.md +88 -27
  171. package/docs/regenerating.md +87 -52
  172. package/docs/sentinel.md +1 -1
  173. package/docs/skills-and-gates.md +3 -1
  174. package/docs/test-advisor.md +110 -0
  175. package/docs/theming.md +1 -1
  176. package/docs/using.md +17 -15
  177. package/genome/rules/bullet-continuation.md +8 -8
  178. package/genome/rules/concise-specs-examples.md +111 -80
  179. package/genome/rules/concise-specs-integration-examples.md +56 -41
  180. package/genome/rules/concise-specs.md +17 -16
  181. package/genome/rules/definitions.md +5 -5
  182. package/genome/rules/examples/integration-embedded-testing/run_conformance_tests_java.sh +1 -1
  183. package/genome/rules/func-specs.md +69 -74
  184. package/genome/rules/impl-reqs.md +4 -4
  185. package/genome/rules/integration-embedded-testing.md +20 -20
  186. package/genome/rules/integration-embedded.md +31 -31
  187. package/genome/rules/integration-standalone.md +9 -9
  188. package/genome/rules/integrations.md +18 -18
  189. package/genome/rules/linked-resources.md +19 -16
  190. package/genome/rules/module-structure.md +21 -14
  191. package/genome/rules/project-model.md +18 -17
  192. package/genome/rules/required-concepts.md +1 -1
  193. package/genome/rules/requires-modules.md +6 -5
  194. package/genome/rules/semantic-ids.md +49 -0
  195. package/genome/rules/stdlib.md +4 -5
  196. package/genome/rules/test-plain-files.md +130 -0
  197. package/genome/rules/test-reqs.md +8 -8
  198. package/genome/rules/turri-regeneration.md +23 -8
  199. package/genome/skills/analyze-2-func-specs/SKILL.md +36 -21
  200. package/genome/skills/analyze-func-specs/SKILL.md +46 -32
  201. package/genome/skills/break-down-func-spec/SKILL.md +91 -67
  202. package/genome/skills/consolidate-concepts/SKILL.md +10 -10
  203. package/genome/skills/convert-old-syntax/SKILL.md +68 -0
  204. package/genome/skills/convert-old-syntax/references/rubric.md +11 -0
  205. package/genome/skills/debug-specs/SKILL.md +62 -56
  206. package/genome/skills/implement-conformance-testing-script/SKILL.md +19 -15
  207. package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +2 -2
  208. package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +2 -2
  209. package/genome/skills/implement-unit-testing-script/SKILL.md +14 -10
  210. package/genome/skills/refactor-module/SKILL.md +35 -35
  211. package/genome/skills/resolve-section-ownership/SKILL.md +9 -9
  212. package/genome/skills/resolve-spec-conflict/SKILL.md +35 -29
  213. package/package.json +7 -6
  214. package/dist/regenerate/choose-conformance.d.ts +0 -32
  215. package/dist/regenerate/choose-conformance.js +0 -117
  216. /package/dist/{validate-cli.d.ts → parse-cli.d.ts} +0 -0
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: analyze-func-specs
3
3
  description: >-
4
- Analyze a batch of functional specs from a ***plain spec file to determine
4
+ Analyze a batch of functional specs from a .plain file to determine
5
5
  which pairs conflict. Replaces the pair-by-pair `analyze-2-func-specs` flow
6
- when a caller wants to check many specs at once (e.g. a new spec against
7
- every existing spec, or a freshly inserted batch against itself).
6
+ when a caller wants to check many functional specs at once (e.g. a new one against
7
+ every existing one, or a freshly inserted batch against itself).
8
8
  allowed-tools: [read, ls, grep, find]
9
9
  ---
10
10
 
@@ -15,18 +15,18 @@ allowed-tools: [read, ls, grep, find]
15
15
  A **set of two or more functional specs** to check against each other. Callers typically supply one of:
16
16
 
17
17
  - A whole `***functional specs***` section to self-check.
18
- - A new spec (or batch of new specs) **plus** the existing specs from the same file and any `requires` modules.
19
- - An explicit list of spec snippets the user wants compared.
18
+ - A new functional spec (or batch of them) **plus** the existing functional specs from the same file and any `requires` modules.
19
+ - An explicit list of functional spec snippets the user wants compared.
20
20
 
21
- Each spec must be identifiable. If the caller didn't label them, assign **stable identifiers** in order of appearance: `S1`, `S2`, `S3`, …. Use those identifiers in the output. If the caller provided their own IDs or quoted snippets, use those instead and keep them verbatim.
21
+ Each functional spec must be identifiable. Use its func-id (`<module>:<func-id>` when the batch spans modules). A draft that has no func-id yet gets a **stable identifier** in order of appearance: `S1`, `S2`, `S3`, …. Use those identifiers in the output. If the caller provided its own labels or quoted snippets, use those instead and keep them verbatim.
22
22
 
23
23
  The skill also needs the `***definitions***` section (and any imported definitions) so referenced `:Concepts:` can be resolved.
24
24
 
25
25
  ## Workflow
26
26
 
27
- 1. **Read all input specs and the relevant `***definitions***`** so every `:Concept:` is understood.
28
- 2. **Establish chronological order** across the batch. Earlier specs are considered to have been rendered first; later specs are evaluated with the earlier ones in context. If the caller already provided an order, preserve it.
29
- 3. **Generate the pair list.** Enumerate every unordered pair `(Sᵢ, Sⱼ)` with `i < j`. Skip pairs where the two specs share no `:Concept:` and no overlapping subject — they are trivially compatible and listing them adds noise.
27
+ 1. **Read all input functional specs and the relevant `***definitions***`** so every `:Concept:` is understood.
28
+ 2. **Establish chronological order** across the batch. Earlier functional specs are considered to have been regenerated first; later ones are evaluated with the earlier ones in context. If the caller already provided an order, preserve it.
29
+ 3. **Generate the pair list.** Enumerate every unordered pair of functional specs, the earlier first. Skip pairs where the two share no `:Concept:` and no overlapping subject — they are trivially compatible and listing them adds noise.
30
30
  4. **Run the conflict analysis below on each remaining pair.** Use the same checklist that the legacy `analyze-2-func-specs` skill used, but apply it pair by pair across the batch in a single pass — do not require the caller to invoke the analyzer once per pair.
31
31
  5. **Record every CONFLICTING pair.** Compatible pairs are not listed individually; only the conflicts are emitted.
32
32
  6. **Output the verdict** in the format below. No reasoning, no category labels, no resolution suggestions.
@@ -37,11 +37,14 @@ Work through each question for the pair under inspection. If any answer is "yes"
37
37
 
38
38
  ### 1. Direct Contradiction
39
39
 
40
- Do the two specs make mutually exclusive assertions about the same behavior?
40
+ Do the two functional specs make mutually exclusive assertions about the same behavior?
41
41
 
42
42
  ```
43
- Spec A: :Resource: items are returned sorted by name in ascending order.
44
- Spec B: :Resource: items are returned sorted by creation date in descending order.
43
+ # sort-by-name
44
+ :Resource: items are returned sorted by name in ascending order.
45
+
46
+ # sort-by-date
47
+ :Resource: items are returned sorted by creation date in descending order.
45
48
 
46
49
  Verdict: CONFLICTING — both define the sort order for the same response,
47
50
  but specify different fields and directions. A single implementation cannot
@@ -50,34 +53,43 @@ satisfy both unless scoped to different contexts.
50
53
 
51
54
  ### 2. State or Data Conflict
52
55
 
53
- Does one spec set a state or value that the other spec assumes is different?
56
+ Does one functional spec set a state or value that the other assumes is different?
54
57
 
55
58
  ```
56
- Spec A: :TaskList: is initially empty.
57
- Spec B: :TaskList: contains a default "Welcome" :Task: on first load.
59
+ # empty-task-list
60
+ :TaskList: is initially empty.
61
+
62
+ # welcome-task
63
+ :TaskList: contains a default "Welcome" :Task: on first load.
58
64
 
59
65
  Verdict: CONFLICTING — both define the initial state of :TaskList: differently.
60
66
  ```
61
67
 
62
68
  ### 3. Behavioral Override
63
69
 
64
- Does the later spec silently replace behavior established by the earlier spec without acknowledging it?
70
+ Does the later functional spec silently replace behavior established by the earlier one without acknowledging it?
65
71
 
66
72
  ```
67
- Spec A: :User: credentials are validated using an API key.
68
- Spec B: :User: credentials are validated using OAuth 2.0.
73
+ # api-key-auth
74
+ :User: credentials are validated using an API key.
75
+
76
+ # oauth-auth
77
+ :User: credentials are validated using OAuth 2.0.
69
78
 
70
79
  Verdict: CONFLICTING — both define the authentication mechanism but pick
71
- different approaches. The later spec overrides the earlier one.
80
+ different approaches. The later one overrides the earlier one.
72
81
  ```
73
82
 
74
83
  ### 4. Scope Ambiguity
75
84
 
76
- Are the two specs ambiguous enough that a renderer could interpret them as conflicting, even if the user intends them to be complementary?
85
+ Are the two functional specs ambiguous enough that a coding agent could interpret them as conflicting, even if the user intends them to be complementary?
77
86
 
78
87
  ```
79
- Spec A: All :Resource: items are returned.
80
- Spec B: Only active :Resource: items are returned.
88
+ # list-resources
89
+ All :Resource: items are returned.
90
+
91
+ # list-active-resources
92
+ Only active :Resource: items are returned.
81
93
 
82
94
  Verdict: CONFLICTING (ambiguous) — "all" vs "only active" appear contradictory.
83
95
  Could be resolved by scoping each to different conditions (e.g., filtered vs unfiltered).
@@ -85,13 +97,16 @@ Could be resolved by scoping each to different conditions (e.g., filtered vs unf
85
97
 
86
98
  ### 5. Shared Concept, Different Constraints
87
99
 
88
- Do both specs impose constraints on the same `:Concept:` that cannot coexist?
100
+ Do both functional specs impose constraints on the same `:Concept:` that cannot coexist?
89
101
 
90
102
  ```
91
- Spec A: :BatchSize: is 100 items.
92
- Spec B: :BatchSize: is 50 items for :Resource: types with attachments.
103
+ # default-batch-size
104
+ :BatchSize: is 100 items.
105
+
106
+ # attachment-batch-size
107
+ :BatchSize: is 50 items for :Resource: types with attachments.
93
108
 
94
- Verdict: COMPATIBLE — Spec B adds a conditional refinement, not a contradiction.
109
+ Verdict: COMPATIBLE — attachment-batch-size adds a conditional refinement, not a contradiction.
95
110
  ```
96
111
 
97
112
  ## Output Format
@@ -104,20 +119,19 @@ If **no pair** is conflicting:
104
119
  COMPATIBLE
105
120
  ```
106
121
 
107
- If **one or more pairs** are conflicting, emit `CONFLICTING` followed by one line per conflicting pair, in `Sᵢ x Sⱼ` form (using the identifiers from the input, with `i < j`), sorted lexicographically:
122
+ If **one or more pairs** are conflicting, emit `CONFLICTING` followed by one line per conflicting pair, in `<a> x <b>` form (the identifiers from step 1, the one that comes first in the input on the left), sorted lexicographically:
108
123
 
109
124
  ```
110
125
  CONFLICTING
111
- S1 x S4
112
- S2 x S3
113
- S3 x S5
126
+ add-task x import-tasks
127
+ list-tasks x S2
114
128
  ```
115
129
 
116
130
  Rules for the output:
117
131
 
118
132
  - Do **not** list compatible pairs.
119
133
  - Do **not** include reasoning, checklist categories, or fixes — the caller decides what to do with each conflict (typically: invoke `resolve-spec-conflict` on each pair).
120
- - If the input contained fewer than two specs, emit `COMPATIBLE` (nothing to compare).
121
- - Identifiers must match exactly what the caller provided (or the `S1`, `S2`, … fallback assigned in step 1).
134
+ - If the input contained fewer than two functional specs, emit `COMPATIBLE` (nothing to compare).
135
+ - Identifiers must match exactly what *Input* settled: the func-ids, the caller's own labels, or the `S1`, `S2`, … fallback for a draft.
122
136
 
123
137
  The internal pairwise analysis informs the verdict but must not appear in the output.
@@ -1,19 +1,19 @@
1
1
  ---
2
2
  name: break-down-func-spec
3
3
  description: >-
4
- Break down a functional spec that is too complex into smaller specs that
5
- each imply ≤ 200 lines of code. Use when a spec is judged too large against
4
+ Break down a functional spec that is too complex into smaller ones that
5
+ each imply ≤ 200 lines of code. Use when a functional spec is judged too large against
6
6
  the complexity limit (`func-specs.md`), before or after it is written in.
7
7
  allowed-tools: [read, write, edit, ls, grep, find]
8
8
  ---
9
9
 
10
- # Break Down Functional Spec
10
+ # Break Down Functional Functional spec
11
11
 
12
12
  ## When to Use
13
13
 
14
- - A spec is judged to exceed the 200 LOC limit (`func-specs.md`, *Complexity limit*) and needs to be split before it is written in.
15
- - A spec already written in turns out too large - its pulse could not get its unit tests to pass.
16
- - A spec bundles multiple behaviors, constructs, or concerns that should be separated.
14
+ - A functional spec is judged to exceed the 200 LOC limit (`func-specs.md`, *Complexity limit*) and needs to be split before it is written in.
15
+ - A functional spec already written in turns out too large - its pulse could not get its unit tests to pass.
16
+ - A functional spec bundles multiple behaviors, constructs, or concerns that should be separated.
17
17
 
18
18
  ## Input
19
19
 
@@ -22,184 +22,208 @@ The functional spec to break down, plus the full `.plain` file it belongs to.
22
22
  ## Workflow
23
23
 
24
24
  1. **Read the full `.plain` file** — definitions, implementation reqs, and all functional specs (including `requires` modules) to understand context.
25
- 2. **Identify the spec to break down** — the one flagged as too complex or pointed to by the user.
25
+ 2. **Identify the functional spec to break down** — the one flagged as too complex or pointed to by the user.
26
26
  3. **Analyze why it is too complex** — use the signs in `func-specs.md` (*Complexity limit*):
27
27
  - Multiple distinct behaviors bundled together?
28
28
  - Too many new constructs introduced at once?
29
29
  - Complex branching logic or conditional paths?
30
- - Cross-cutting concerns mixed with core functionality?
31
- - A full UI screen described in one spec?
30
+ - Cross-cutting concerns mixed with core behaviour?
31
+ - A full UI screen described in one functional spec?
32
32
  - Complex data transformations across multiple entities?
33
33
  - Implies one substantial technical component (engine, parser, scheduler, algorithm, state machine, sync mechanism) that must be built in code?
34
- 4. **Identify the split boundaries** — find the natural seams where the spec can be divided. Each resulting spec must be:
35
- - Independently meaningful (makes sense on its own with previous specs as context)
36
- - Self-contained (does not require a later spec to be useful)
34
+ 4. **Identify the split boundaries** — find the natural seams where the functional spec can be divided. Each resulting one must be:
35
+ - Independently meaningful (makes sense on its own with the functional specs before it as context)
36
+ - Self-contained (does not require a later functional spec to be useful)
37
37
  - Within the 200 LOC limit
38
- 5. **Draft the replacement specs** — write the smaller specs in chronological order. The first replacement spec typically sets up the foundation, and subsequent ones layer behavior on top.
39
- 6. **Verify functional completeness** — this is critical. The replacement specs taken together must cover **100% of the functionality** described in the original spec. Walk through every behavior, condition, and detail in the original and confirm it appears in exactly one of the replacement specs. Nothing may be lost, weakened, or left implicit. If any functionality from the original is missing, add it to the appropriate replacement spec or create an additional one.
40
- 7. **Verify each replacement spec** — judge each against the complexity limit, and split again any that is still too large.
41
- 8. **Check for conflicts** — run `analyze-func-specs` **once** with the full set of replacement specs plus every existing spec in the file and its `requires` chain. The batched analyzer reports every conflicting pair (replacement × existing and replacement × replacement) in one call — do not loop over pairs. Resolve each reported pair with `resolve-spec-conflict`, then re-run `analyze-func-specs` over the touched set until the verdict is `COMPATIBLE`.
42
- 9. **Replace in the file** — remove the original spec and insert the replacement specs in its position, preserving chronological order.
43
- 10. **Read the file again** to confirm correct placement and syntax.
38
+ 5. **Draft the replacements** — write the smaller functional specs in chronological order, each with its own func-id per `semantic-ids.md`; the replacement that keeps the original's main behaviour may keep the original's func-id. The first replacement typically sets up the foundation, and subsequent ones layer behavior on top.
39
+ 6. **Verify functional completeness** — this is critical. The replacements taken together must cover **100% of the behaviour** the original describes. Walk through every behavior, condition, and detail in the original and confirm it appears in exactly one of the replacements. Nothing may be lost, weakened, or left implicit. If any behaviour from the original is missing, add it to the appropriate replacement or create an additional one.
40
+ 7. **Verify each replacement** — judge each against the complexity limit, and split again any that is still too large.
41
+ 8. **Check for conflicts** — run `analyze-func-specs` **once** with the full set of replacements plus every existing functional spec in the file and its `requires` chain. The batched analyzer reports every conflicting pair (replacement × existing and replacement × replacement) in one call — do not loop over pairs. Resolve each reported pair with `resolve-spec-conflict`, then re-run `analyze-func-specs` over the touched set until the verdict is `COMPATIBLE`.
42
+ 9. **Replace in the file** — remove the original functional spec (heading and body) and insert the replacements in its position, each as a `# <func-id>` heading with its body, preserving chronological order.
43
+ 10. **Bring the test plain files in step**, in the same ***plain diff - every replacement gets its test plain file, each scenario of the original's moves to the replacement it tests, and the original's file is deleted when its func-id is gone (*Keeping test plain files in step* in `test-plain-files.md`). No scenario is written for a replacement that the original's did not have.
44
+ 11. **Read the file again** to confirm correct placement and syntax.
44
45
 
45
46
  ## Splitting Strategies
46
47
 
47
48
  ### Strategy 1: Separate Distinct Behaviors
48
49
 
49
- If the spec bundles multiple independently testable actions, split each into its own spec.
50
+ If the functional spec bundles multiple independently testable actions, split each into its own.
50
51
 
51
52
  **Before:**
52
53
  ```plain
53
54
  ***functional specs***
54
55
 
55
- - A :User: can create, edit, and delete :Recipe: items, with validation on all fields.
56
+ # manage-recipes
57
+ A :User: can create, edit, and delete :Recipe: items, with validation on all fields.
56
58
  ```
57
59
 
58
60
  **After:**
59
61
  ```plain
60
62
  ***functional specs***
61
63
 
62
- - A :User: can create a :Recipe:. Only valid :Recipe: items can be created.
64
+ # create-recipe
65
+ A :User: can create a :Recipe:. Only valid :Recipe: items can be created.
63
66
 
64
- - A :User: can edit an existing :Recipe:. Validation rules apply to the edited fields.
67
+ # edit-recipe
68
+ A :User: can edit an existing :Recipe:. Validation rules apply to the edited fields.
65
69
 
66
- - A :User: can delete a :Recipe:.
70
+ # delete-recipe
71
+ A :User: can delete a :Recipe:.
67
72
  ```
68
73
 
69
74
  ### Strategy 2: Separate Setup from Behavior
70
75
 
71
- If the spec introduces a new construct and immediately defines complex behavior on it, split into setup + behavior.
76
+ If the functional spec introduces a new construct and immediately defines complex behavior on it, split into setup + behavior.
72
77
 
73
78
  **Before:**
74
79
  ```plain
75
80
  ***functional specs***
76
81
 
77
- - The :MealPlan: screen displays a weekly grid of :Slot: items, allows drag-and-drop reordering, and shows nutritional totals per day.
82
+ # meal-plan-screen
83
+ The :MealPlan: screen displays a weekly grid of :Slot: items, allows drag-and-drop reordering, and shows nutritional totals per day.
78
84
  ```
79
85
 
80
86
  **After:**
81
87
  ```plain
82
88
  ***functional specs***
83
89
 
84
- - The :MealPlan: screen displays a weekly grid of :Slot: items.
90
+ # meal-plan-grid
91
+ The :MealPlan: screen displays a weekly grid of :Slot: items.
85
92
 
86
- - A :User: can reorder :Slot: items within a day on the :MealPlan: screen using drag-and-drop.
93
+ # reorder-slots
94
+ A :User: can reorder :Slot: items within a day on the :MealPlan: screen using drag-and-drop.
87
95
 
88
- - The :MealPlan: screen displays nutritional totals for each day.
96
+ # daily-nutrition-totals
97
+ The :MealPlan: screen displays nutritional totals for each day.
89
98
  ```
90
99
 
91
100
  ### Strategy 3: Separate Core Logic from Cross-Cutting Concerns
92
101
 
93
- If the spec mixes primary functionality with error handling, retries, caching, pagination, or logging, pull cross-cutting concerns into their own specs.
102
+ If the functional spec mixes primary behaviour with error handling, retries, caching, pagination, or logging, pull cross-cutting concerns into their own functional specs.
94
103
 
95
104
  **Before:**
96
105
  ```plain
97
106
  ***functional specs***
98
107
 
99
- - :Ingredient: data is fetched from the external API with pagination, retry on transient errors, and caching for 10 minutes.
108
+ # fetch-ingredients
109
+ :Ingredient: data is fetched from the external API with pagination, retry on transient errors, and caching for 10 minutes.
100
110
  ```
101
111
 
102
112
  **After:**
103
113
  ```plain
104
114
  ***functional specs***
105
115
 
106
- - :Ingredient: data is fetched from the external API.
116
+ # fetch-ingredients
117
+ :Ingredient: data is fetched from the external API.
107
118
 
108
- - :Ingredient: data is fetched from the external API in pages.
119
+ # fetch-ingredients-paged
120
+ :Ingredient: data is fetched from the external API in pages.
109
121
 
110
- - Fetching :Ingredient: data is retried on transient errors.
122
+ # retry-ingredient-fetch
123
+ Fetching :Ingredient: data is retried on transient errors.
111
124
  ```
112
125
 
113
126
  ### Strategy 4: Separate Conditional Paths
114
127
 
115
- If the spec describes different modes or branches, give each its own spec.
128
+ If the functional spec describes different modes or branches, give each its own.
116
129
 
117
130
  **Before:**
118
131
  ```plain
119
132
  ***functional specs***
120
133
 
121
- - :MealPlan: generation depends on :DietType:. Standard plans use round-robin assignment. Restrictive plans filter out excluded ingredients first, then apply round-robin. Custom plans allow manual slot-by-slot selection.
134
+ # generate-meal-plan
135
+ :MealPlan: generation depends on :DietType:. Standard plans use round-robin assignment. Restrictive plans filter out excluded ingredients first, then apply round-robin. Custom plans allow manual slot-by-slot selection.
122
136
  ```
123
137
 
124
138
  **After:**
125
139
  ```plain
126
140
  ***functional specs***
127
141
 
128
- - A standard :MealPlan: is generated using round-robin :Recipe: assignment.
142
+ # generate-standard-plan
143
+ A standard :MealPlan: is generated using round-robin :Recipe: assignment.
129
144
 
130
- - A restrictive :MealPlan: is generated.
131
- - Excluded :Ingredient: items are filtered out first.
132
- - Round-robin :Recipe: assignment is then applied.
145
+ # generate-restrictive-plan
146
+ A restrictive :MealPlan: is generated.
147
+ - Excluded :Ingredient: items are filtered out first.
148
+ - Round-robin :Recipe: assignment is then applied.
133
149
 
134
- - A :User: can manually assign :Recipe: items to :Slot: items for a custom :MealPlan:.
150
+ # assign-custom-plan
151
+ A :User: can manually assign :Recipe: items to :Slot: items for a custom :MealPlan:.
135
152
  ```
136
153
 
137
154
  ### Strategy 5: Build UI Incrementally
138
155
 
139
- If the spec describes a full screen, split into layout + individual interactive elements.
156
+ If the functional spec describes a full screen, split into layout + individual interactive elements.
140
157
 
141
158
  **Before:**
142
159
  ```plain
143
160
  ***functional specs***
144
161
 
145
- - The :Dashboard: screen shows a summary card with stats, a scrollable list of recent :MealPlan: items, a floating action button to create a new plan, and a bottom navigation bar.
162
+ # dashboard-screen
163
+ The :Dashboard: screen shows a summary card with stats, a scrollable list of recent :MealPlan: items, a floating action button to create a new plan, and a bottom navigation bar.
146
164
  ```
147
165
 
148
166
  **After:**
149
167
  ```plain
150
168
  ***functional specs***
151
169
 
152
- - The :Dashboard: screen shows a summary card with :MealFrameStats:.
170
+ # dashboard-summary-card
171
+ The :Dashboard: screen shows a summary card with :MealFrameStats:.
153
172
 
154
- - The :Dashboard: screen shows a scrollable list of recent :MealPlan: items.
173
+ # dashboard-recent-plans
174
+ The :Dashboard: screen shows a scrollable list of recent :MealPlan: items.
155
175
 
156
- - The :Dashboard: screen includes a button to create a new :MealPlan:.
176
+ # dashboard-new-plan-button
177
+ The :Dashboard: screen includes a button to create a new :MealPlan:.
157
178
  ```
158
179
 
159
180
  ### Strategy 6: Extract a Reusable Technical Component
160
181
 
161
- Sometimes a spec is too complex not because it bundles many behaviors, but because it implies building one substantial technical component inline — an engine, parser, scheduler, layout algorithm, state machine, or sync mechanism. Splitting the behavior sideways does not help when the weight sits in that single component. Instead, pull the component out: define a concept for it, build it in its own dedicated spec placed **earlier** in the chain, then rewrite the original to use the component **by reference**. Because specs render incrementally top-to-bottom, the original now implies far less code — it wires up a component that already exists rather than implementing it from scratch.
182
+ Sometimes a functional spec is too complex not because it bundles many behaviors, but because it implies building one substantial technical component inline — an engine, parser, scheduler, layout algorithm, state machine, or sync mechanism. Splitting the behavior sideways does not help when the weight sits in that single component. Instead, pull the component out: define a concept for it, build it in its own dedicated functional spec placed **earlier** in the chain, then rewrite the original to use the component **by reference**. Because functional specs are regenerated incrementally top-to-bottom, the original now implies far less code — it wires up a component that already exists rather than implementing it from scratch.
162
183
 
163
- Define the component concept in `***definitions***` (per `definitions.md`) before the first spec that references it.
184
+ Define the component concept in `***definitions***` (per `definitions.md`) before the first functional spec that references it.
164
185
 
165
186
  **Before:**
166
187
  ```plain
167
188
  ***functional specs***
168
189
 
169
- - A :Report: is exported to PDF, laying out multi-page tables with repeating headers, page numbers, and charts rendered from :Report: data.
190
+ # export-report-pdf
191
+ A :Report: is exported to PDF, laying out multi-page tables with repeating headers, page numbers, and charts rendered from :Report: data.
170
192
  ```
171
193
 
172
194
  **After:**
173
195
  ```plain
174
196
  ***functional specs***
175
197
 
176
- - :PdfRenderer: lays out multi-page tables from structured content.
177
- - Table headers repeat at the top of each page.
178
- - Each page shows its page number.
198
+ # pdf-renderer-tables
199
+ :PdfRenderer: lays out multi-page tables from structured content.
200
+ - Table headers repeat at the top of each page.
201
+ - Each page shows its page number.
179
202
 
180
- - A :Report: is exported to PDF using :PdfRenderer:, embedding charts rendered from :Report: data.
203
+ # export-report-pdf
204
+ A :Report: is exported to PDF using :PdfRenderer:, embedding charts rendered from :Report: data.
181
205
  ```
182
206
 
183
- The extracted component spec and the rewritten original must together still cover 100% of the original functionality (step 6): the original must **reference** the component, never re-describe it. Keep the component's technology and architecture choices in `***implementation reqs***`, not in the functional spec. If the component is a self-contained subsystem or will be reused across modules, promote it to its own module - one that `requires` it, following `requires-modules.md`, or with `refactor-module` - instead of a sibling spec.
207
+ The extracted component's functional spec and the rewritten original must together still cover 100% of the original behaviour (step 6): the original must **reference** the component, never re-describe it. Keep the component's technology and architecture choices in `***implementation reqs***`, not in the functional spec. If the component is a self-contained subsystem or will be reused across modules, promote it to its own module - one that `requires` it, following `requires-modules.md`, or with `refactor-module` - instead of a sibling functional spec.
184
208
 
185
209
  ## Preserving Chronological Order
186
210
 
187
- The replacement specs take the position of the original spec. Earlier specs remain unchanged. The first replacement spec should make sense given only the specs above it. Each subsequent replacement spec can reference behavior from the ones before it.
211
+ The replacements take the position of the original. Earlier functional specs remain unchanged. The first replacement should make sense given only the functional specs above it. Each subsequent replacement can reference behavior from the ones before it.
188
212
 
189
- If the original spec had acceptance tests, redistribute them to the most appropriate replacement spec — or drop tests that no longer apply to a single smaller spec and rewrite them.
213
+ The original's test plain file is split the same way: each scenario moves to the replacement it tests, and one that no longer fits a single replacement is rewritten to fit the one it tests most. A replacement no scenario moves to gets no test plain file - never an empty one (see `test-plain-files.md`).
190
214
 
191
215
  ## Validation Checklist
192
216
 
193
- - [ ] Original spec has been removed from the file
194
- - [ ] Replacement specs together cover 100% of the original spec's functionality — nothing lost
195
- - [ ] Each replacement spec implies ≤ 200 LOC (judged against the complexity limit)
196
- - [ ] No conflicts between replacement specs and existing specs (verified via one batched `analyze-func-specs` call)
197
- - [ ] No conflicts between the replacement specs themselves (covered by the same batched call)
198
- - [ ] Replacement specs are in correct chronological order
199
- - [ ] Each replacement spec is independently meaningful
200
- - [ ] All `:Concepts:` referenced in replacement specs are defined
201
- - [ ] Any extracted technical component is defined as a concept, built by its own earlier spec, and only **referenced** (not re-described) by the original
202
- - [ ] Replacement specs are language-agnostic
203
- - [ ] Replacement specs trimmed per `concise-specs.md` — a split is not a licence to re-add prose
217
+ - [ ] The original functional spec has been removed from the file
218
+ - [ ] The replacements together cover 100% of the original's behaviour — nothing lost
219
+ - [ ] Each replacement implies ≤ 200 LOC (judged against the complexity limit)
220
+ - [ ] No conflicts between the replacements and existing functional specs (verified via one batched `analyze-func-specs` call)
221
+ - [ ] No conflicts between the replacements themselves (covered by the same batched call)
222
+ - [ ] The replacements are in correct chronological order
223
+ - [ ] Each replacement is independently meaningful
224
+ - [ ] All `:Concepts:` referenced in the replacements are defined
225
+ - [ ] Any extracted technical component is defined as a concept, built by its own earlier functional spec, and only **referenced** (not re-described) by the original
226
+ - [ ] The replacements are language-agnostic
227
+ - [ ] The replacements trimmed per `concise-specs.md` — a split is not a licence to re-add prose
204
228
  - [ ] All external interfaces remain explicit
205
- - [ ] Acceptance tests (if any) have been redistributed or rewritten
229
+ - [ ] Test plain files follow the split: one per replacement, every original scenario moved or rewritten, none bound to a func-id that no longer exists
@@ -34,11 +34,11 @@ The set of modules to consolidate from, plus optionally the name for the new (or
34
34
  - Whether it is currently in an `exported_concepts` list
35
35
  - Which other concepts it references in its definition (dependency graph)
36
36
  3. **Identify consolidation candidates.** A concept should be consolidated if:
37
- - It is defined in one module but referenced by specs in another module (currently shared via `exported_concepts`)
37
+ - It is defined in one module but referenced by functional specs in another module (currently shared via `exported_concepts`)
38
38
  - It is duplicated across multiple modules
39
39
  - It is a foundational domain concept that logically belongs in a shared vocabulary
40
40
  4. **Identify concepts that should stay local.** A concept should remain in its module if:
41
- - It is only used within that single module's specs and definitions
41
+ - It is only used within that single module's functional specs and definitions
42
42
  - It is an internal implementation detail not meaningful outside that module
43
43
 
44
44
  ## Phase 2 — Plan the Consolidation
@@ -71,7 +71,7 @@ For each affected module, determine the frontmatter changes:
71
71
  |--------|------|
72
72
  | Add the new import to `import` list | Module does not already import the target |
73
73
  | Remove concepts from `exported_concepts` | Concepts that were exported only to share definitions — now handled by the import |
74
- | Keep concepts in `exported_concepts` | Concepts that downstream `requires` modules still need via export (because those downstream modules do not import the new template) |
74
+ | Keep concepts in `exported_concepts` | Concepts that downstream modules still need via export (because those downstream modules do not import the new template) |
75
75
 
76
76
  **Important:** `import` provides definitions to the importing module. `exported_concepts` on a `requires` module provides concepts to downstream modules in the build chain. If a downstream module will now `import` the shared template directly, the concept can be removed from `exported_concepts`. If a downstream module does **not** import the template, the concept must remain exported.
77
77
 
@@ -111,9 +111,9 @@ For each module that had concepts moved out:
111
111
 
112
112
  ### 3c. Update downstream modules (if applicable)
113
113
 
114
- If concepts were removed from a module's `exported_concepts` and downstream `requires` modules relied on them:
114
+ If concepts were removed from a module's `exported_concepts` and downstream modules relied on them:
115
115
  1. Add the new import to the downstream module's `import` list so it gets the concepts directly.
116
- 2. Verify the downstream module's specs can still resolve all concept references.
116
+ 2. Verify the downstream module's ***plain can still resolve all concept references.
117
117
 
118
118
  ## Phase 4 — Verify
119
119
 
@@ -140,7 +140,7 @@ For every affected module (source modules, downstream modules, and the import mo
140
140
  - [ ] No `***functional specs***` were modified in any module
141
141
  - [ ] No `***implementation reqs***` were modified in any module
142
142
  - [ ] No `***test reqs***` were modified in any module
143
- - [ ] No `***acceptance tests***` were modified in any module
143
+ - [ ] No test plain file was modified
144
144
 
145
145
  ### 4e. Structural validation
146
146
 
@@ -164,7 +164,7 @@ Read each modified `.plain` file in full and present the changes to the user for
164
164
  ### Moving a concept that is only used locally
165
165
  If a concept is only referenced within a single module, consolidating it into a shared import adds unnecessary coupling. Keep it local.
166
166
 
167
- ### Forgetting to update downstream requires modules
167
+ ### Forgetting to update downstream modules
168
168
  When a concept is removed from `exported_concepts`, any module that `requires` the source module and references that concept will break — unless it now imports the shared template. Always trace the full dependency chain.
169
169
 
170
170
  ### Breaking concept ordering
@@ -174,7 +174,7 @@ Concepts in the import module must be topologically ordered. If `:Meal:` referen
174
174
  An import module cannot `import` a module that directly or indirectly imports it back. If the shared concepts reference concepts from an existing template, the new import module should itself import that template — not the other way around.
175
175
 
176
176
  ### Removing concepts from exported_concepts prematurely
177
- Only remove a concept from `exported_concepts` if **every** downstream `requires` module that needs it will now get it via `import`. If even one downstream module does not import the shared template, the export must stay.
177
+ Only remove a concept from `exported_concepts` if **every** downstream module that needs it will now get it via `import`. If even one downstream module does not import the shared template, the export must stay.
178
178
 
179
179
  ## Validation Checklist
180
180
 
@@ -185,8 +185,8 @@ Only remove a concept from `exported_concepts` if **every** downstream `requires
185
185
  - [ ] Every affected module's `import` list includes the target import module
186
186
  - [ ] `exported_concepts` updated correctly — no missing exports, no unnecessary exports
187
187
  - [ ] All concept references in all affected modules resolve correctly
188
- - [ ] No functional specs, implementation reqs, test reqs, or acceptance tests were modified
188
+ - [ ] No functional specs, implementation reqs, test reqs, or test plain files were modified
189
189
  - [ ] Import module is in `template/` and has no functional specs or requires
190
190
  - [ ] No circular imports introduced
191
- - [ ] Downstream requires modules updated if needed
191
+ - [ ] Downstream modules updated if needed
192
192
  - [ ] User approved the final result
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: convert-old-syntax
3
+ description: >-
4
+ Convert one module from the old ***plain syntax - functional specs as `- `
5
+ bullets, acceptance tests nested under them - to `# <func-id>` headings and
6
+ test plain files, word for word, the ids confirmed by the person first. Use
7
+ when turri says a module is in the old ***plain syntax, or the person asks to
8
+ convert one. One run converts one module, the lowest of the chain first;
9
+ it never regenerates.
10
+ allowed-tools: [read, ls, grep, find, change_plain, parse]
11
+ metadata:
12
+ phases:
13
+ ids: "a func-id for each functional spec and a scenario-id for each acceptance test, proposed and confirmed"
14
+ rewrite: "the module and its test plain files, in one ***plain diff, word for word"
15
+ check: "parse, and which module is next"
16
+ gates:
17
+ - after: rewrite
18
+ review:
19
+ rubric: ./references/rubric.md
20
+ judges: 2
21
+ quorum: all
22
+ on_fail: retry
23
+ max_retries: 2
24
+ judge_tools: [read, ls, grep, find]
25
+ ---
26
+
27
+ # Convert Old Syntax
28
+
29
+ Moves one module from the old ***plain syntax to the new one: each functional spec a `# <func-id>` heading with its body, and its acceptance tests in its test plain file. Nothing is reworded, added or dropped, and nothing is regenerated. The chat runs it again for the next module, asking the person in between.
30
+
31
+ ## Steps
32
+
33
+ ### ids
34
+
35
+ **Which module.** Convert one module in this run. When the person named one, start at the lowest module of its `requires` chain still in the old syntax - the first, from the bottom of the chain, whose functional specs are `- ` bullets - which may be the one they named. Read the modules of the chain as text to tell: a module in the old syntax has `- ` bullets right under `***functional specs***`, or `***acceptance tests***` nested in it, and no `# <func-id>` heading. Skip import modules, which have no functional specs, and the standard library's templates (`stdlib/...`): there is nothing in them to convert. When every module of the chain is in the new syntax already, change nothing: say so, and that the run is done.
36
+
37
+ **Read the module as text,** with `read` - the parser refuses the old syntax, so `parse` cannot read it yet. Change nothing in this step.
38
+
39
+ **Propose the ids:**
40
+ - A func-id for each functional spec - each top-level `- ` bullet under `***functional specs***`: short kebab-case from what it means (`add-task`), lowercase letters, digits and hyphens only, unique in the module (`semantic-ids.md`)
41
+ - A scenario-id for each acceptance test nested under one, the same way from its text, unique among that functional spec's acceptance tests
42
+
43
+ Ask the person once, with `ask_user`: the whole list in its `context` - each func-id with the first words of its bullet, and under it each scenario-id with the first words of its acceptance test - and options to accept the list or change ids. When they change some, apply the changes and ask again with the new list, until they accept it. Ask nothing else.
44
+
45
+ ### rewrite
46
+
47
+ Write the whole conversion as one `change_plain` diff, with the confirmed ids:
48
+
49
+ - **The module.** Under `***functional specs***`, each bullet becomes its `# <func-id>` heading followed by its body: the bullet's text without its leading `- `, word for word. Its sub-bullets become `- ` bullets under that text, one level less indented, word for word and in the same order. Its nested `***acceptance tests***` are taken out of the module. The functional specs keep their order, one blank line between them. The frontmatter, every other section, the comments and any Liquid stay exactly as they are.
50
+ - **Its test plain files,** one for each functional spec that has acceptance tests, at `tests/<module>/<func-id>.plain`: frontmatter `module:` (the module's file name without `.plain`) and `func_id:`, then `***conformance tests***`, then `***acceptance tests***` (`test-plain-files.md`). Each acceptance test of the functional spec becomes a scenario under `***acceptance tests***`: its `# <scenario-id>` heading followed by its text without its `- `, word for word, and its sub-bullets as `- ` bullets under it. `***conformance tests***` stays empty. A functional spec with no acceptance tests gets no test plain file: it has no scenarios.
51
+
52
+ Nothing else: no word added, reworded or dropped, no conformance scenario, no fix to the ***plain however clear it seems. What the conversion shows to be wrong goes in the result, for the person to decide on later.
53
+
54
+ The change regenerates nothing: a module built before func-ids is not built on until its chain is regenerated from scratch, which the chat asks the person for.
55
+
56
+ The record for the review: the module as it was before the change, word for word as you read it; the confirmed ids; and every file the change wrote. When the review sends the step back, show the person what it found and your fix with `ask_user`, then write the fix with one `change_plain`.
57
+
58
+ ### check
59
+
60
+ Run `parse` on the module and show what it says in your reply.
61
+
62
+ When it reports an error the conversion made, show it to the person with `ask_user`, with the fix, and write the fix with one `change_plain`; then run `parse` again. An error the module had before the conversion stays for the person.
63
+
64
+ End with the result:
65
+ - the module converted, its functional specs and scenarios counted, and the files written
66
+ - what `parse` said
67
+ - the next module of the chain still in the old syntax, for the chat to convert with this skill again - or that the chain is done
68
+ - that nothing was regenerated: once the whole chain is converted, its code in `plain_modules/` was built when functional specs were numbered, and the chain has to be regenerated from scratch - only with the person's go
@@ -0,0 +1,11 @@
1
+ # The conversion lost, changed and added nothing
2
+
3
+ The artifact holds a module as it was in the old ***plain syntax, word for word, the func-ids and scenario-ids the person confirmed, and the files the conversion wrote. Read each file it names from disk, and check every criterion. One violation fails the review; name it, with the functional spec or scenario and the words that differ.
4
+
5
+ 1. **Every functional spec is there.** Each top-level `- ` bullet under `***functional specs***` of the module as it was is one `# <func-id>` heading in the module now, with the confirmed func-id, in the same order. No functional spec is missing, and none was added or split.
6
+ 2. **Every body is its bullet, word for word.** Under each heading, the text is the bullet's text without its leading `- `, word for word, and its sub-bullets follow as `- ` bullets, word for word and in the same order. Nothing is reworded, shortened, merged, reordered or added - not a word, not a full stop.
7
+ 3. **Every acceptance test is a scenario, word for word.** Each acceptance test nested under a bullet is a scenario under `***acceptance tests***` in that functional spec's test plain file: a `# <scenario-id>` heading with the confirmed scenario-id, then the acceptance test's text without its `- `, word for word, its sub-bullets as `- ` bullets.
8
+ 4. **Nothing was added to the tests.** No scenario that was not an acceptance test: `***conformance tests***` is empty in every test plain file, and `***acceptance tests***` holds only the converted acceptance tests.
9
+ 5. **A test plain file for every functional spec with acceptance tests, and none for the rest.** Each is at `tests/<module>/<func-id>.plain`, with frontmatter `module:` set to the module's name and `func_id:` to its func-id, then `***conformance tests***`, then `***acceptance tests***`, each heading at the start of a line. A functional spec with no acceptance tests has no test plain file - an empty one fails this point.
10
+ 6. **The rest of the module is untouched.** The frontmatter, `***definitions***`, `***implementation reqs***`, `***test reqs***`, comments and Liquid read exactly as they did, and no `***acceptance tests***` is left in the module.
11
+ 7. **The ids are well formed.** Every func-id and scenario-id is lowercase letters, digits and hyphens only; func-ids are unique in the module, and scenario-ids unique within their functional spec.