plain-forge 1.0.23 → 1.0.24-next.019bba8

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 (61) hide show
  1. package/README.md +14 -11
  2. package/bin/cli.mjs +5 -4
  3. package/forge/rules/plain-forge.md +10 -0
  4. package/forge/skills/add-concept/SKILL.md +1 -1
  5. package/forge/skills/add-feature/SKILL.md +8 -7
  6. package/forge/skills/add-feature/references/checklist.md +2 -2
  7. package/forge/skills/add-functional-spec/SKILL.md +14 -10
  8. package/forge/skills/add-functional-specs/SKILL.md +14 -10
  9. package/forge/skills/add-implementation-requirement/SKILL.md +1 -1
  10. package/forge/skills/add-resource/SKILL.md +3 -2
  11. package/forge/skills/add-template/SKILL.md +1 -1
  12. package/forge/skills/add-test-requirement/SKILL.md +4 -4
  13. package/forge/skills/add-test-scenarios/SKILL.md +98 -0
  14. package/forge/skills/analyze-2-func-specs/SKILL.md +1 -1
  15. package/forge/skills/analyze-func-specs/SKILL.md +2 -2
  16. package/forge/skills/analyze-if-func-spec-too-complex/SKILL.md +44 -24
  17. package/forge/skills/break-down-func-spec/SKILL.md +57 -33
  18. package/forge/skills/check-plain-env/SKILL.md +2 -2
  19. package/forge/skills/consolidate-concepts/SKILL.md +8 -8
  20. package/forge/skills/create-import-module/SKILL.md +1 -1
  21. package/forge/skills/create-requires-module/SKILL.md +6 -3
  22. package/forge/skills/debug-specs/SKILL.md +14 -8
  23. package/forge/skills/forge-plain/SKILL.md +3 -3
  24. package/forge/skills/forge-plain/references/checklist.md +3 -3
  25. package/forge/skills/forge-plain/references/phase-1-product.md +2 -2
  26. package/forge/skills/forge-plain/references/phase-2-tech.md +1 -1
  27. package/forge/skills/forge-plain/references/phase-3-testing.md +5 -5
  28. package/forge/skills/init-config-file/SKILL.md +2 -2
  29. package/forge/skills/init-plain-project/SKILL.md +6 -6
  30. package/forge/skills/load-plain-reference/SKILL.md +25 -25
  31. package/forge/skills/load-plain-reference/references/project-model.md +2 -1
  32. package/forge/skills/load-plain-reference/references/rendering-and-testing.md +7 -5
  33. package/forge/{rules → skills/load-plain-reference/rules}/bullet-continuation.md +11 -11
  34. package/forge/{rules → skills/load-plain-reference/rules}/concise-specs-examples.md +100 -69
  35. package/forge/{rules → skills/load-plain-reference/rules}/concise-specs-integration-examples.md +39 -24
  36. package/forge/{rules → skills/load-plain-reference/rules}/concise-specs.md +3 -2
  37. package/forge/{rules → skills/load-plain-reference/rules}/func-specs.md +37 -28
  38. package/forge/{rules → skills/load-plain-reference/rules}/impl-reqs.md +1 -1
  39. package/forge/{rules → skills/load-plain-reference/rules}/integration-embedded-testing.md +1 -1
  40. package/forge/{rules → skills/load-plain-reference/rules}/linked-resources.md +7 -4
  41. package/forge/{rules → skills/load-plain-reference/rules}/module-structure.md +16 -9
  42. package/forge/{rules → skills/load-plain-reference/rules}/requires-modules.md +1 -0
  43. package/forge/skills/load-plain-reference/rules/semantic-ids.md +47 -0
  44. package/forge/skills/load-plain-reference/rules/test-plain-files.md +67 -0
  45. package/forge/{rules → skills/load-plain-reference/rules}/test-reqs.md +6 -6
  46. package/forge/skills/plain-healthcheck/SKILL.md +31 -13
  47. package/forge/skills/refactor-module/SKILL.md +16 -16
  48. package/forge/skills/resolve-section-ownership/SKILL.md +3 -3
  49. package/forge/skills/resolve-spec-conflict/SKILL.md +14 -8
  50. package/package.json +1 -1
  51. package/forge/skills/add-acceptance-test/SKILL.md +0 -101
  52. /package/forge/{rules → skills/load-plain-reference/rules}/definitions.md +0 -0
  53. /package/forge/{rules → skills/load-plain-reference/rules}/examples/integration-embedded-testing/prepare_environment_java.sh +0 -0
  54. /package/forge/{rules → skills/load-plain-reference/rules}/examples/integration-embedded-testing/run_conformance_tests_java.sh +0 -0
  55. /package/forge/{rules → skills/load-plain-reference/rules}/examples/integration-embedded-testing/run_unittests_java.sh +0 -0
  56. /package/forge/{rules → skills/load-plain-reference/rules}/exported-concepts.md +0 -0
  57. /package/forge/{rules → skills/load-plain-reference/rules}/import-modules.md +0 -0
  58. /package/forge/{rules → skills/load-plain-reference/rules}/integration-embedded.md +0 -0
  59. /package/forge/{rules → skills/load-plain-reference/rules}/integration-standalone.md +0 -0
  60. /package/forge/{rules → skills/load-plain-reference/rules}/integrations.md +0 -0
  61. /package/forge/{rules → skills/load-plain-reference/rules}/required-concepts.md +0 -0
@@ -10,7 +10,7 @@ description: >-
10
10
 
11
11
  # Analyze If Functional Spec Is Too Complex
12
12
 
13
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
13
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
14
14
 
15
15
  ## Why This Matters
16
16
 
@@ -50,20 +50,25 @@ Too complex:
50
50
  ```plain
51
51
  ***functional specs***
52
52
 
53
- - A :User: can create, edit, delete, and archive :Task: items, with validation on all fields and confirmation dialogs for destructive actions.
53
+ # manage-tasks
54
+ A :User: can create, edit, delete, and archive :Task: items, with validation on all fields and confirmation dialogs for destructive actions.
54
55
  ```
55
56
 
56
57
  Acceptable (one behavior each):
57
58
  ```plain
58
59
  ***functional specs***
59
60
 
60
- - A :User: can create :Task:. Only valid :Task: items can be added.
61
+ # create-task
62
+ A :User: can create :Task:. Only valid :Task: items can be added.
61
63
 
62
- - A :User: can edit :Task:.
64
+ # edit-task
65
+ A :User: can edit :Task:.
63
66
 
64
- - A :User: can delete :Task:.
67
+ # delete-task
68
+ A :User: can delete :Task:.
65
69
 
66
- - A :User: can archive :Task:.
70
+ # archive-task
71
+ A :User: can archive :Task:.
67
72
 
68
73
  ```
69
74
 
@@ -84,19 +89,23 @@ Too complex:
84
89
  ```plain
85
90
  ***functional specs***
86
91
 
87
- - :Order: processing depends on :OrderType:. Standard orders are validated and stored. Express orders skip validation and are queued for immediate dispatch. Bulk orders are split into sub-orders of 100 items each, validated individually, and processed in parallel with progress tracking.
92
+ # process-order
93
+ :Order: processing depends on :OrderType:. Standard orders are validated and stored. Express orders skip validation and are queued for immediate dispatch. Bulk orders are split into sub-orders of 100 items each, validated individually, and processed in parallel with progress tracking.
88
94
  ```
89
95
 
90
96
  Acceptable (separate the modes):
91
97
  ```plain
92
98
  ***functional specs***
93
99
 
94
- - A standard :Order: is validated and stored.
100
+ # process-standard-order
101
+ A standard :Order: is validated and stored.
95
102
 
96
- - An express :Order: is queued for immediate dispatch without validation.
103
+ # process-express-order
104
+ An express :Order: is queued for immediate dispatch without validation.
97
105
 
98
- - A bulk :Order: is split into sub-orders of 100 items each.
99
- - Each sub-order is processed individually.
106
+ # split-bulk-order
107
+ A bulk :Order: is split into sub-orders of 100 items each.
108
+ - Each sub-order is processed individually.
100
109
  ```
101
110
 
102
111
  ### 4. Cross-Cutting Concerns
@@ -107,17 +116,21 @@ Too complex:
107
116
  ```plain
108
117
  ***functional specs***
109
118
 
110
- - :Resource: items are fetched from the external API with pagination support, retry on transient errors with exponential backoff, caching for 5 minutes, and logging of all API calls.
119
+ # fetch-resources
120
+ :Resource: items are fetched from the external API with pagination support, retry on transient errors with exponential backoff, caching for 5 minutes, and logging of all API calls.
111
121
  ```
112
122
 
113
123
  Acceptable (separate concerns):
114
124
  ```plain
115
125
  ***functional specs***
116
- - :Resource: items are fetched from the external API.
126
+ # fetch-resources
127
+ :Resource: items are fetched from the external API.
117
128
 
118
- - :Resource: items are fetched from the external API in pages.
129
+ # fetch-resources-paged
130
+ :Resource: items are fetched from the external API in pages.
119
131
 
120
- - Fetching :Resource: items is retried on transient errors using exponential backoff.
132
+ # retry-resource-fetch
133
+ Fetching :Resource: items is retried on transient errors using exponential backoff.
121
134
  ```
122
135
 
123
136
  ### 5. UI Complexity
@@ -128,18 +141,22 @@ Too complex:
128
141
  ```plain
129
142
  ***functional specs***
130
143
 
131
- - The dashboard shows :User: profile, recent :Task: items in a sortable table, a notification bell with unread count, and a sidebar with navigation links that highlights the active page.
144
+ # dashboard
145
+ The dashboard shows :User: profile, recent :Task: items in a sortable table, a notification bell with unread count, and a sidebar with navigation links that highlights the active page.
132
146
  ```
133
147
 
134
148
  Acceptable (build incrementally):
135
149
  ```plain
136
150
  ***functional specs***
137
151
 
138
- - A dashboard page is shown for :User:.
152
+ # dashboard-page
153
+ A dashboard page is shown for :User:.
139
154
 
140
- - Recent :Task: items are shown in a sortable table on the dashboard.
155
+ # dashboard-recent-tasks
156
+ Recent :Task: items are shown in a sortable table on the dashboard.
141
157
 
142
- - A notification indicator with the unread count is shown on the dashboard.
158
+ # dashboard-notifications
159
+ A notification indicator with the unread count is shown on the dashboard.
143
160
  ```
144
161
 
145
162
  ### 6. Data Transformation Complexity
@@ -157,18 +174,21 @@ Too complex (builds the component and uses it in one spec):
157
174
  ```plain
158
175
  ***functional specs***
159
176
 
160
- - A :Report: is exported to PDF, laying out multi-page tables with repeating headers and page numbers, and charts rendered from :Report: data.
177
+ # export-report-pdf
178
+ A :Report: is exported to PDF, laying out multi-page tables with repeating headers and page numbers, and charts rendered from :Report: data.
161
179
  ```
162
180
 
163
181
  Acceptable (component in its own spec, then referenced):
164
182
  ```plain
165
183
  ***functional specs***
166
184
 
167
- - :PdfRenderer: lays out multi-page tables from structured content.
168
- - Table headers repeat at the top of each page.
169
- - Each page shows its page number.
185
+ # pdf-renderer-tables
186
+ :PdfRenderer: lays out multi-page tables from structured content.
187
+ - Table headers repeat at the top of each page.
188
+ - Each page shows its page number.
170
189
 
171
- - A :Report: is exported to PDF using :PdfRenderer:, embedding charts rendered from :Report: data.
190
+ # export-report-pdf
191
+ A :Report: is exported to PDF using :PdfRenderer:, embedding charts rendered from :Report: data.
172
192
  ```
173
193
 
174
194
  When this indicator fires, the fix is `break-down-func-spec` Strategy 6 — extract the component into its own earlier spec and reference it.
@@ -8,7 +8,7 @@ description: >-
8
8
 
9
9
  # Break Down Functional Spec
10
10
 
11
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
11
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
12
12
 
13
13
  ## When to Use
14
14
 
@@ -36,12 +36,13 @@ The functional spec to break down, plus the full `.plain` file it belongs to.
36
36
  - Independently meaningful (makes sense on its own with previous specs as context)
37
37
  - Self-contained (does not require a later spec to be useful)
38
38
  - Within the 200 LOC limit
39
- 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
+ 5. **Draft the replacement specs** — write the smaller specs in chronological order, each with its own func-id per `semantic-ids.md`; the replacement that keeps the original's main behavior may keep the original's func-id. The first replacement spec typically sets up the foundation, and subsequent ones layer behavior on top.
40
40
  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.
41
41
  7. **Verify each replacement spec** — run `analyze-if-func-spec-too-complex` on each to confirm it fits within the limit.
42
42
  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`.
43
- 9. **Replace in the file** — remove the original spec and insert the replacement specs in its position, preserving chronological order.
44
- 10. **Read the file again** to confirm correct placement and syntax.
43
+ 9. **Replace in the file** — remove the original functionality (heading and body) and insert the replacement functionalities, each as a `# <func-id>` heading with its body, in its position, preserving chronological order.
44
+ 10. **Bring the test plain files in step** — invoke `add-test-scenarios` for each replacement functionality. It moves every scenario of the original's test plain file to the replacement it tests, writes scenarios for outcomes that have none, and deletes the original's file when its func-id no longer exists.
45
+ 11. **Read the file again** to confirm correct placement and syntax.
45
46
 
46
47
  ## Splitting Strategies
47
48
 
@@ -53,18 +54,22 @@ If the spec bundles multiple independently testable actions, split each into its
53
54
  ```plain
54
55
  ***functional specs***
55
56
 
56
- - A :User: can create, edit, and delete :Recipe: items, with validation on all fields.
57
+ # manage-recipes
58
+ A :User: can create, edit, and delete :Recipe: items, with validation on all fields.
57
59
  ```
58
60
 
59
61
  **After:**
60
62
  ```plain
61
63
  ***functional specs***
62
64
 
63
- - A :User: can create a :Recipe:. Only valid :Recipe: items can be created.
65
+ # create-recipe
66
+ A :User: can create a :Recipe:. Only valid :Recipe: items can be created.
64
67
 
65
- - A :User: can edit an existing :Recipe:. Validation rules apply to the edited fields.
68
+ # edit-recipe
69
+ A :User: can edit an existing :Recipe:. Validation rules apply to the edited fields.
66
70
 
67
- - A :User: can delete a :Recipe:.
71
+ # delete-recipe
72
+ A :User: can delete a :Recipe:.
68
73
  ```
69
74
 
70
75
  ### Strategy 2: Separate Setup from Behavior
@@ -75,18 +80,22 @@ If the spec introduces a new construct and immediately defines complex behavior
75
80
  ```plain
76
81
  ***functional specs***
77
82
 
78
- - The :MealPlan: screen displays a weekly grid of :Slot: items, allows drag-and-drop reordering, and shows nutritional totals per day.
83
+ # meal-plan-screen
84
+ The :MealPlan: screen displays a weekly grid of :Slot: items, allows drag-and-drop reordering, and shows nutritional totals per day.
79
85
  ```
80
86
 
81
87
  **After:**
82
88
  ```plain
83
89
  ***functional specs***
84
90
 
85
- - The :MealPlan: screen displays a weekly grid of :Slot: items.
91
+ # meal-plan-grid
92
+ The :MealPlan: screen displays a weekly grid of :Slot: items.
86
93
 
87
- - A :User: can reorder :Slot: items within a day on the :MealPlan: screen using drag-and-drop.
94
+ # reorder-slots
95
+ A :User: can reorder :Slot: items within a day on the :MealPlan: screen using drag-and-drop.
88
96
 
89
- - The :MealPlan: screen displays nutritional totals for each day.
97
+ # daily-nutrition-totals
98
+ The :MealPlan: screen displays nutritional totals for each day.
90
99
  ```
91
100
 
92
101
  ### Strategy 3: Separate Core Logic from Cross-Cutting Concerns
@@ -97,18 +106,22 @@ If the spec mixes primary functionality with error handling, retries, caching, p
97
106
  ```plain
98
107
  ***functional specs***
99
108
 
100
- - :Ingredient: data is fetched from the external API with pagination, retry on transient errors, and caching for 10 minutes.
109
+ # fetch-ingredients
110
+ :Ingredient: data is fetched from the external API with pagination, retry on transient errors, and caching for 10 minutes.
101
111
  ```
102
112
 
103
113
  **After:**
104
114
  ```plain
105
115
  ***functional specs***
106
116
 
107
- - :Ingredient: data is fetched from the external API.
117
+ # fetch-ingredients
118
+ :Ingredient: data is fetched from the external API.
108
119
 
109
- - :Ingredient: data is fetched from the external API in pages.
120
+ # fetch-ingredients-paged
121
+ :Ingredient: data is fetched from the external API in pages.
110
122
 
111
- - Fetching :Ingredient: data is retried on transient errors.
123
+ # retry-ingredient-fetch
124
+ Fetching :Ingredient: data is retried on transient errors.
112
125
  ```
113
126
 
114
127
  ### Strategy 4: Separate Conditional Paths
@@ -119,20 +132,24 @@ If the spec describes different modes or branches, give each its own spec.
119
132
  ```plain
120
133
  ***functional specs***
121
134
 
122
- - :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.
135
+ # generate-meal-plan
136
+ :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.
123
137
  ```
124
138
 
125
139
  **After:**
126
140
  ```plain
127
141
  ***functional specs***
128
142
 
129
- - A standard :MealPlan: is generated using round-robin :Recipe: assignment.
143
+ # generate-standard-plan
144
+ A standard :MealPlan: is generated using round-robin :Recipe: assignment.
130
145
 
131
- - A restrictive :MealPlan: is generated.
132
- - Excluded :Ingredient: items are filtered out first.
133
- - Round-robin :Recipe: assignment is then applied.
146
+ # generate-restrictive-plan
147
+ A restrictive :MealPlan: is generated.
148
+ - Excluded :Ingredient: items are filtered out first.
149
+ - Round-robin :Recipe: assignment is then applied.
134
150
 
135
- - A :User: can manually assign :Recipe: items to :Slot: items for a custom :MealPlan:.
151
+ # assign-custom-plan
152
+ A :User: can manually assign :Recipe: items to :Slot: items for a custom :MealPlan:.
136
153
  ```
137
154
 
138
155
  ### Strategy 5: Build UI Incrementally
@@ -143,18 +160,22 @@ If the spec describes a full screen, split into layout + individual interactive
143
160
  ```plain
144
161
  ***functional specs***
145
162
 
146
- - 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.
163
+ # dashboard-screen
164
+ 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.
147
165
  ```
148
166
 
149
167
  **After:**
150
168
  ```plain
151
169
  ***functional specs***
152
170
 
153
- - The :Dashboard: screen shows a summary card with :MealFrameStats:.
171
+ # dashboard-summary-card
172
+ The :Dashboard: screen shows a summary card with :MealFrameStats:.
154
173
 
155
- - The :Dashboard: screen shows a scrollable list of recent :MealPlan: items.
174
+ # dashboard-recent-plans
175
+ The :Dashboard: screen shows a scrollable list of recent :MealPlan: items.
156
176
 
157
- - The :Dashboard: screen includes a button to create a new :MealPlan:.
177
+ # dashboard-new-plan-button
178
+ The :Dashboard: screen includes a button to create a new :MealPlan:.
158
179
  ```
159
180
 
160
181
  ### Strategy 6: Extract a Reusable Technical Component
@@ -167,18 +188,21 @@ Define the component concept in `***definitions***` (via `add-concept`) before t
167
188
  ```plain
168
189
  ***functional specs***
169
190
 
170
- - A :Report: is exported to PDF, laying out multi-page tables with repeating headers, page numbers, and charts rendered from :Report: data.
191
+ # export-report-pdf
192
+ A :Report: is exported to PDF, laying out multi-page tables with repeating headers, page numbers, and charts rendered from :Report: data.
171
193
  ```
172
194
 
173
195
  **After:**
174
196
  ```plain
175
197
  ***functional specs***
176
198
 
177
- - :PdfRenderer: lays out multi-page tables from structured content.
178
- - Table headers repeat at the top of each page.
179
- - Each page shows its page number.
199
+ # pdf-renderer-tables
200
+ :PdfRenderer: lays out multi-page tables from structured content.
201
+ - Table headers repeat at the top of each page.
202
+ - Each page shows its page number.
180
203
 
181
- - A :Report: is exported to PDF using :PdfRenderer:, embedding charts rendered from :Report: data.
204
+ # export-report-pdf
205
+ A :Report: is exported to PDF using :PdfRenderer:, embedding charts rendered from :Report: data.
182
206
  ```
183
207
 
184
208
  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 with `create-requires-module` / `refactor-module` instead of a sibling spec.
@@ -187,7 +211,7 @@ The extracted component spec and the rewritten original must together still cove
187
211
 
188
212
  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.
189
213
 
190
- 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.
214
+ The original functionality's test plain file is split the same way: each scenario moves to the replacement functionality it tests, a scenario that no longer fits one replacement is rewritten, and each replacement ends with at least one conformance scenario when conformance tests are enabled (see `add-test-scenarios`).
191
215
 
192
216
  ## Validation Checklist
193
217
 
@@ -203,4 +227,4 @@ If the original spec had acceptance tests, redistribute them to the most appropr
203
227
  - [ ] Replacement specs are language-agnostic
204
228
  - [ ] Replacement specs trimmed per `concise-specs.md` — a split is not a licence to re-add prose
205
229
  - [ ] All external interfaces remain explicit
206
- - [ ] Acceptance tests (if any) have been redistributed or rewritten
230
+ - [ ] Test plain files follow the split: one per replacement functionality, every original scenario moved or rewritten, none bound to a func-id that no longer exists
@@ -12,7 +12,7 @@ description: >-
12
12
 
13
13
  # Check Plain Env
14
14
 
15
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
15
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
16
16
 
17
17
  This skill answers one question: **does the host machine have everything the ***plain project needs to render and test?** It reads the project, derives the requirement list, probes the machine, and returns a report. It never installs anything itself — that decision belongs to the user.
18
18
 
@@ -43,7 +43,7 @@ The skill is a **derive → probe → report** pass. It does not stop at the fir
43
43
  ### Step 1 — Inventory the project
44
44
 
45
45
  1. **Detect the host OS** first. Run `uname -s 2>/dev/null || echo "$OS"`. Use the result to (a) pick the right script extensions to inspect (`.sh` vs `.ps1`) and (b) pick the right install commands later (Homebrew, apt, dnf, pacman, choco, scoop, winget).
46
- 2. **List every `.plain` file** in the repo root and in any subdirectory that contains them. Note which are top modules (not `requires`-ed by anything) and which are import modules (under `template/`).
46
+ 2. **List every `.plain` file** in the repo root and in any subdirectory that contains them. Note which are top modules (not `requires`-ed by any other module) and which are import modules (under `template/`).
47
47
  3. **List every `config.yaml`** in the repo and read each one. Note the `*-script` keys it sets and the values they point at.
48
48
  4. **List every script under `test_scripts/`** (both `.sh` and `.ps1` — projects can ship both).
49
49
  5. **List every file under `resources/`** if the directory exists. Schemas and protocol files there often imply running services (e.g. a Postgres `.sql` schema implies a Postgres server).
@@ -9,7 +9,7 @@ description: >-
9
9
 
10
10
  # Consolidate Concepts
11
11
 
12
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
12
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
13
13
 
14
14
  ## When to Use
15
15
 
@@ -72,7 +72,7 @@ For each affected module, determine the frontmatter changes:
72
72
  |--------|------|
73
73
  | Add the new import to `import` list | Module does not already import the target |
74
74
  | Remove concepts from `exported_concepts` | Concepts that were exported only to share definitions — now handled by the import |
75
- | Keep concepts in `exported_concepts` | Concepts that downstream `requires` modules still need via export (because those downstream modules do not import the new template) |
75
+ | Keep concepts in `exported_concepts` | Concepts that downstream modules still need via export (because those downstream modules do not import the new template) |
76
76
 
77
77
  **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.
78
78
 
@@ -112,7 +112,7 @@ For each module that had concepts moved out:
112
112
 
113
113
  ### 3c. Update downstream modules (if applicable)
114
114
 
115
- If concepts were removed from a module's `exported_concepts` and downstream `requires` modules relied on them:
115
+ If concepts were removed from a module's `exported_concepts` and downstream modules relied on them:
116
116
  1. Add the new import to the downstream module's `import` list so it gets the concepts directly.
117
117
  2. Verify the downstream module's specs can still resolve all concept references.
118
118
 
@@ -141,7 +141,7 @@ For every affected module (source modules, downstream modules, and the import mo
141
141
  - [ ] No `***functional specs***` were modified in any module
142
142
  - [ ] No `***implementation reqs***` were modified in any module
143
143
  - [ ] No `***test reqs***` were modified in any module
144
- - [ ] No `***acceptance tests***` were modified in any module
144
+ - [ ] No test plain file was modified
145
145
 
146
146
  ### 4e. Structural validation
147
147
 
@@ -165,7 +165,7 @@ Read each modified `.plain` file in full and present the changes to the user for
165
165
  ### Moving a concept that is only used locally
166
166
  If a concept is only referenced within a single module, consolidating it into a shared import adds unnecessary coupling. Keep it local.
167
167
 
168
- ### Forgetting to update downstream requires modules
168
+ ### Forgetting to update downstream modules
169
169
  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.
170
170
 
171
171
  ### Breaking concept ordering
@@ -175,7 +175,7 @@ Concepts in the import module must be topologically ordered. If `:Meal:` referen
175
175
  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.
176
176
 
177
177
  ### Removing concepts from exported_concepts prematurely
178
- 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.
178
+ 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.
179
179
 
180
180
  ## Validation Checklist
181
181
 
@@ -186,8 +186,8 @@ Only remove a concept from `exported_concepts` if **every** downstream `requires
186
186
  - [ ] Every affected module's `import` list includes the target import module
187
187
  - [ ] `exported_concepts` updated correctly — no missing exports, no unnecessary exports
188
188
  - [ ] All concept references in all affected modules resolve correctly
189
- - [ ] No functional specs, implementation reqs, test reqs, or acceptance tests were modified
189
+ - [ ] No functional specs, implementation reqs, test reqs, or test plain files were modified
190
190
  - [ ] Import module is in `template/` and has no functional specs or requires
191
191
  - [ ] No circular imports introduced
192
- - [ ] Downstream requires modules updated if needed
192
+ - [ ] Downstream modules updated if needed
193
193
  - [ ] User approved the final result
@@ -9,7 +9,7 @@ description: >-
9
9
 
10
10
  # Create Import Module
11
11
 
12
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
12
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
13
13
 
14
14
  ## What an Import Module Is
15
15
 
@@ -9,7 +9,7 @@ description: >-
9
9
 
10
10
  # Create Requires Module
11
11
 
12
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
12
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
13
13
 
14
14
  ## What Requires Does
15
15
 
@@ -19,6 +19,7 @@ When this module is rendered:
19
19
  - The required module's generated code (`plain_modules/<required_module>/code`) is copied as the starting point.
20
20
  - The `***functional specs***` of the required module **and all its ancestors** become visible as **previous functional specs**.
21
21
  - Of the required module's definitions, only the concepts in its `exported_concepts` are visible, each with its full definition text. Export visibility is **not** transitive — to see an ancestor's exports, list that ancestor in `requires` too.
22
+ - The required module's test plain files stay with the required module. The new module gets its own test plain files, one per functionality it adds (see `test-plain-files.md`).
22
23
 
23
24
  All modules connected by `requires` form a single tree with a common root. **Diamond joins are prohibited**: multiple `requires` entries must lie on one root-to-tip ancestor path. The deepest entry is the attachment point; the other entries exist only to make those ancestors' exports visible.
24
25
 
@@ -34,7 +35,7 @@ If you only need shared definitions and reqs (no functional specs, no generated
34
35
  2. **Create the `.plain` file at the repository root** with YAML frontmatter containing the `requires` field. Modules with functional specs live at the root, not in `template/`.
35
36
  3. **Review the functional specs of the whole ancestor chain** — they will be treated as previous requirements. Your new functional specs must not conflict with any of them.
36
37
  4. **Review each listed module's `exported_concepts`** — only those concepts are available to reference; an ancestor's exports require listing that ancestor.
37
- 5. **Add module-specific content** — definitions, implementation reqs, test reqs, and functional specs unique to this module.
38
+ 5. **Add module-specific content** — definitions, implementation reqs, test reqs, and functional specs unique to this module. Add every functional spec through `add-functional-spec` or `add-functional-specs`, which also create its test plain file.
38
39
  6. **Check for conflicts** between your new functional specs and any spec in the ancestor chain.
39
40
 
40
41
  ## Format
@@ -56,7 +57,8 @@ description: Extended module that builds on base_module
56
57
 
57
58
  ***functional specs***
58
59
 
59
- - :NewFeature: is available.
60
+ # new-feature
61
+ :NewFeature: is available.
60
62
  ```
61
63
 
62
64
  A module can use both `requires` and `import` together. `requires` points to other root-level modules; `import` resolves from the default `template/` directory (no prefix needed).
@@ -106,5 +108,6 @@ The current module may or may not be functionally related to the required module
106
108
  - [ ] Every listed module's `exported_concepts` provide the concepts you need
107
109
  - [ ] New functional specs do not conflict with any spec in the ancestor chain
108
110
  - [ ] Module has at least one functional spec and one implementation req
111
+ - [ ] Every functional spec has its test plain file
109
112
  - [ ] Both `requires` and `import` are used correctly (not mixed up)
110
113
  - [ ] YAML frontmatter is correctly formatted between `---` markers
@@ -9,7 +9,7 @@ description: >-
9
9
 
10
10
  # Debug Specs
11
11
 
12
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
12
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
13
13
 
14
14
  ## When to Use
15
15
 
@@ -30,7 +30,7 @@ Generated code in `plain_modules/<module>/code/` and `plain_modules/<module>/tes
30
30
 
31
31
  ## Phase 1 — Understand the Context
32
32
 
33
- 1. **Read the `.plain` file(s)** for the module — frontmatter, definitions, implementation reqs, test reqs, and all functional specs. Also read `import` and `requires` chains.
33
+ 1. **Read the `.plain` file(s)** for the module — frontmatter, definitions, implementation reqs, test reqs, and all functional specs. Also read `import` and `requires` chains, and the module's test plain files.
34
34
  2. **Read the user's observation carefully.** Rephrase it back to confirm understanding. Identify:
35
35
  - What is the expected behavior?
36
36
  - What is the actual behavior?
@@ -60,13 +60,13 @@ For each relevant file:
60
60
  ### 2c. Check conformance tests and unit tests (if relevant)
61
61
 
62
62
  If the bug manifests as a test failure:
63
- 1. Read the failing test — conformance tests in `plain_modules/<module_name>/tests/<functionality>/`, unit tests inside `plain_modules/<module_name>/code/`.
63
+ 1. Read the failing test — conformance tests in `plain_modules/<module_name>/tests/<func-id>/`, each labelled with the scenario-id it implements, unit tests inside `plain_modules/<module_name>/code/`.
64
64
  2. Understand what the test expects vs. what the implementation does.
65
65
  3. Determine whether the test expectation is correct (matches the spec) or incorrect (doesn't match the spec).
66
66
 
67
67
  ## Phase 3 — Diagnose the Root Cause
68
68
 
69
- Trace the issue from the generated code back to the specs. There are five possible root causes — determine which one applies **before** making changes:
69
+ Trace the issue from the generated code back to the specs. There are six possible root causes — determine which one applies **before** making changes:
70
70
 
71
71
  | Root Cause | Symptom | Fix |
72
72
  |------------|---------|-----|
@@ -74,6 +74,7 @@ Trace the issue from the generated code back to the specs. There are five possib
74
74
  | **Missing spec** | The desired behavior is not covered by any spec. The renderer had no guidance and either did nothing or made an arbitrary choice. | Add a new functional spec using the `add-functional-spec` skill. |
75
75
  | **Conflicting specs** | Two specs contradict each other, causing the renderer to produce inconsistent behavior. | Use the `resolve-spec-conflict` skill. |
76
76
  | **Incorrect spec** | The spec explicitly describes the wrong behavior. The renderer implemented it faithfully, but the spec itself is wrong. | Rewrite the spec to describe the correct behavior. |
77
+ | **Incorrect scenario** | The spec is correct and the code matches it, but a scenario in the test plain file expects an outcome the spec does not state, or misses one it states. | Fix the scenario with `add-test-scenarios`. |
77
78
  | **Missing implementation req** | The spec is correct, but the implementation req doesn't provide enough guidance for the renderer to produce the right code (e.g., missing library, missing architectural constraint, missing platform detail). | Add or update the implementation req using the `add-implementation-requirement` skill. |
78
79
 
79
80
  ### How to diagnose
@@ -85,7 +86,9 @@ Trace the issue from the generated code back to the specs. There are five possib
85
86
  2. **Check for conflicts.** Could another spec be overriding or contradicting this behavior?
86
87
  - Read all functional specs that touch the same concepts.
87
88
  - If two specs are in tension → **conflicting specs**.
88
- 3. **Check implementation reqs.** Is the renderer missing guidance on how to implement correctly?
89
+ 3. **Check the scenario.** When a conformance or acceptance test fails, find its scenario by the scenario-id in the test name and compare it with the spec.
90
+ - If the scenario contradicts or extends the spec → **incorrect scenario**.
91
+ 4. **Check implementation reqs.** Is the renderer missing guidance on how to implement correctly?
89
92
  - Does the implementation req specify the right library, pattern, or constraint?
90
93
  - If a platform-specific or framework-specific detail is missing → **missing implementation req**.
91
94
 
@@ -95,10 +98,11 @@ Apply the fix based on the diagnosed root cause. Use the appropriate skill:
95
98
 
96
99
  | Root Cause | Skill to Use |
97
100
  |------------|-------------|
98
- | Ambiguous spec | Edit the spec inline — add sub-bullets or reword for clarity |
101
+ | Ambiguous spec | Edit the spec inline — add detail under the statement line or reword for clarity |
99
102
  | Missing spec | `add-functional-spec` |
100
103
  | Conflicting specs | `resolve-spec-conflict` |
101
104
  | Incorrect spec | Edit the spec inline — rewrite the incorrect part |
105
+ | Incorrect scenario | `add-test-scenarios` |
102
106
  | Missing implementation req | `add-implementation-requirement` |
103
107
 
104
108
  ### Fix guidelines
@@ -107,6 +111,7 @@ Apply the fix based on the diagnosed root cause. Use the appropriate skill:
107
111
  - **Preserve chronological order.** If adding a new spec, place it correctly relative to existing specs.
108
112
  - **Stay language-agnostic.** Functional specs describe behavior, not implementation. Platform-specific guidance belongs in implementation reqs.
109
113
  - **Respect the 200 LOC limit.** If a fix makes a spec too complex, use `break-down-func-spec` to split it.
114
+ - **Keep the test plain file in step.** After changing a functional spec, invoke `add-test-scenarios` for it so its scenarios still follow from the spec.
110
115
  - **Check for new conflicts.** After editing, verify the fix doesn't conflict with other specs by running `analyze-func-specs` once with the edited spec(s) plus every existing spec that touches the same concepts. The batched analyzer reports all conflicting pairs in a single call; resolve each with `resolve-spec-conflict`.
111
116
 
112
117
  ## Phase 5 — Verify and Report
@@ -148,7 +153,7 @@ A test is failing. Use the test as the entry point.
148
153
  ```
149
154
  Read failing test → Understand what it expects → Read the implementation →
150
155
  Determine if the test or the implementation is wrong → Trace back to the spec →
151
- Fix the spec (or test reqs/acceptance tests if the test itself is wrong)
156
+ Fix the spec (or the test reqs / the scenario in the test plain file if the test itself is wrong)
152
157
  ```
153
158
 
154
159
  ### Strategy 4: Differential
@@ -179,11 +184,12 @@ A spec fix may affect other specs that reference the same concepts. Always check
179
184
 
180
185
  - [ ] User's observation is clearly understood (expected vs. actual behavior)
181
186
  - [ ] Generated code has been read to understand the current implementation
182
- - [ ] Root cause is diagnosed (ambiguous / missing / conflicting / incorrect / missing impl req)
187
+ - [ ] Root cause is diagnosed (ambiguous / missing / conflicting / incorrect / incorrect scenario / missing impl req)
183
188
  - [ ] Fix is applied in the `.plain` file(s) only — no generated code modified
184
189
  - [ ] Fix is minimal and targeted to the observed bug
185
190
  - [ ] Fix does not introduce new conflicts with existing specs
186
191
  - [ ] Modified specs respect the 200 LOC limit
187
192
  - [ ] Modified specs remain language-agnostic
188
193
  - [ ] Chronological ordering is preserved
194
+ - [ ] Test plain file of every changed functionality brought in step via `add-test-scenarios`
189
195
  - [ ] Summary of findings and fix presented to the user
@@ -12,7 +12,7 @@ description: >-
12
12
 
13
13
  # Forge Plain
14
14
 
15
- Always invoke the `load-plain-reference` skill first to load the `***plain` syntax rules — but only if it hasn't been loaded yet this session.
15
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
16
16
 
17
17
  ## Role
18
18
 
@@ -54,7 +54,7 @@ Use the dedicated edit skills for every write — never hand-author a `***plain`
54
54
 
55
55
  ## Review loop
56
56
 
57
- After each authoring step, review **only what just changed** — never re-review the whole file. Pick the single most relevant snippet (one concept, one functional spec, the module frontmatter, one requirement, one acceptance test, one script change, one `config.yaml` entry) and embed it directly in the `AskUserQuestion` prompt so the user sees exactly what they approve. Frame each question around one of:
57
+ After each authoring step, review **only what just changed** — never re-review the whole file. Pick the single most relevant snippet (one concept, one functional spec, the module frontmatter, one requirement, one test plain file, one script change, one `config.yaml` entry) and embed it directly in the `AskUserQuestion` prompt so the user sees exactly what they approve. Frame each question around one of:
58
58
 
59
59
  - **Missing parts** — something that should be in the snippet but isn't (an attribute, a validation rule, an edge case, a missing concept).
60
60
  - **Possible extensions** — behavior or detail that could reasonably be expanded.
@@ -84,7 +84,7 @@ When entering a phase, read its reference file and walk its topics **in order**
84
84
  | 0 — What is the intent? | `references/phase-0-intent.md` | a concise intent brief covering the problem, primary user and outcome, and initial boundary is explicitly confirmed; nothing is written to disk |
85
85
  | 1 — What are we building? | `references/phase-1-product.md` | the new `***definitions***` and `***functional specs***`, plus any technology-free `***implementation reqs***`, are on disk and approved |
86
86
  | 2 — What tech should it use? | `references/phase-2-tech.md` | the new `***implementation reqs***` are on disk and approved |
87
- | 3 — How is testing done? | `references/phase-3-testing.md` | the `***test reqs***` (and `***acceptance tests***` if conformance is on) are on disk, the `test_scripts/` and `config.yaml`(s) exist, and `check-plain-env` passed or each gap was acknowledged |
87
+ | 3 — How is testing done? | `references/phase-3-testing.md` | the `***test reqs***` (and the test plain files if conformance is on) are on disk, the `test_scripts/` and `config.yaml`(s) exist, and `check-plain-env` passed or each gap was acknowledged |
88
88
  | 4 — Validate and hand off | `references/phase-4-validate-handoff.md` | `plain-healthcheck` returned `PASS`, and the user has the render target plus every side-channel command |
89
89
 
90
90
  Between phases, summarize and get explicit overall confirmation before continuing — the intent brief