plain-forge 1.0.17 → 1.0.19

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 (51) hide show
  1. package/README.md +15 -8
  2. package/bin/cli.mjs +53 -24
  3. package/forge/rules/bullet-continuation.md +59 -0
  4. package/forge/rules/definitions.md +15 -2
  5. package/forge/rules/exported-concepts.md +0 -2
  6. package/forge/rules/func-specs.md +52 -9
  7. package/forge/rules/impl-reqs.md +0 -2
  8. package/forge/rules/import-modules.md +0 -2
  9. package/forge/rules/integration-embedded-testing.md +4 -3
  10. package/forge/rules/integration-embedded.md +0 -2
  11. package/forge/rules/integration-standalone.md +0 -2
  12. package/forge/rules/integrations.md +0 -2
  13. package/forge/rules/linked-resources.md +7 -8
  14. package/forge/rules/required-concepts.md +0 -2
  15. package/forge/rules/requires-modules.md +0 -2
  16. package/forge/rules/test-reqs.md +0 -2
  17. package/forge/skills/add-acceptance-test/SKILL.md +3 -25
  18. package/forge/skills/add-concept/SKILL.md +3 -22
  19. package/forge/skills/add-feature/SKILL.md +71 -67
  20. package/forge/skills/add-feature/references/checklist.md +38 -0
  21. package/forge/skills/add-feature/references/phase-0-intent.md +29 -0
  22. package/forge/skills/add-functional-spec/SKILL.md +3 -23
  23. package/forge/skills/add-functional-specs/SKILL.md +3 -24
  24. package/forge/skills/add-implementation-requirement/SKILL.md +4 -23
  25. package/forge/skills/add-resource/SKILL.md +7 -8
  26. package/forge/skills/add-test-requirement/SKILL.md +4 -21
  27. package/forge/skills/analyze-2-func-specs/SKILL.md +10 -10
  28. package/forge/skills/analyze-func-specs/SKILL.md +10 -10
  29. package/forge/skills/analyze-if-func-spec-too-complex/SKILL.md +93 -31
  30. package/forge/skills/break-down-func-spec/SKILL.md +78 -29
  31. package/forge/skills/create-import-module/SKILL.md +7 -0
  32. package/forge/skills/create-requires-module/SKILL.md +2 -1
  33. package/forge/skills/forge-plain/SKILL.md +80 -299
  34. package/forge/skills/forge-plain/references/checklist.md +66 -0
  35. package/forge/skills/forge-plain/references/phase-0-intent.md +29 -0
  36. package/forge/skills/forge-plain/references/phase-1-product.md +40 -0
  37. package/forge/skills/forge-plain/references/phase-2-tech.md +24 -0
  38. package/forge/skills/forge-plain/references/phase-3-testing.md +66 -0
  39. package/forge/skills/forge-plain/references/phase-4-validate-handoff.md +49 -0
  40. package/forge/skills/init-config-file/SKILL.md +2 -0
  41. package/forge/skills/init-plain-project/SKILL.md +4 -0
  42. package/forge/skills/init-plain-project/references/checklist.md +31 -0
  43. package/forge/skills/load-codeplain-reference/SKILL.md +188 -0
  44. package/forge/skills/load-plain-reference/SKILL.md +48 -678
  45. package/forge/skills/load-plain-reference/references/project-model.md +47 -0
  46. package/forge/skills/load-plain-reference/references/rendering-and-testing.md +57 -0
  47. package/forge/skills/plain-healthcheck/SKILL.md +2 -2
  48. package/forge/skills/resolve-spec-conflict/SKILL.md +13 -5
  49. package/forge/skills/run-codeplain/SKILL.md +1 -1
  50. package/package.json +1 -1
  51. package/forge/rules/line-length.md +0 -47
@@ -31,8 +31,8 @@ Work through each question. If any answer is "yes", the specs likely conflict.
31
31
  Do the two specs make mutually exclusive assertions about the same behavior?
32
32
 
33
33
  ```
34
- Spec A: The system should return :Resource: items sorted by name in ascending order.
35
- Spec B: The system should return :Resource: items sorted by creation date in descending order.
34
+ Spec A: :Resource: items are returned sorted by name in ascending order.
35
+ Spec B: :Resource: items are returned sorted by creation date in descending order.
36
36
 
37
37
  Verdict: CONFLICTING — both define the sort order for the same response,
38
38
  but specify different fields and directions. A single implementation cannot
@@ -44,8 +44,8 @@ satisfy both unless scoped to different contexts.
44
44
  Does one spec set a state or value that the other spec assumes is different?
45
45
 
46
46
  ```
47
- Spec A: :TaskList: should initially be empty.
48
- Spec B: :TaskList: should contain a default "Welcome" :Task: on first load.
47
+ Spec A: :TaskList: is initially empty.
48
+ Spec B: :TaskList: contains a default "Welcome" :Task: on first load.
49
49
 
50
50
  Verdict: CONFLICTING — both define the initial state of :TaskList: differently.
51
51
  ```
@@ -55,8 +55,8 @@ Verdict: CONFLICTING — both define the initial state of :TaskList: differently
55
55
  Does the later spec silently replace behavior established by the earlier spec without acknowledging it?
56
56
 
57
57
  ```
58
- Spec A: The system should validate :User: credentials using an API key.
59
- Spec B: The system should validate :User: credentials using OAuth 2.0.
58
+ Spec A: :User: credentials are validated using an API key.
59
+ Spec B: :User: credentials are validated using OAuth 2.0.
60
60
 
61
61
  Verdict: CONFLICTING — both define the authentication mechanism but pick
62
62
  different approaches. The later spec overrides the earlier one.
@@ -67,8 +67,8 @@ different approaches. The later spec overrides the earlier one.
67
67
  Are the two specs ambiguous enough that a renderer could interpret them as conflicting, even if the user intends them to be complementary?
68
68
 
69
69
  ```
70
- Spec A: The system should return all :Resource: items.
71
- Spec B: The system should return only active :Resource: items.
70
+ Spec A: All :Resource: items are returned.
71
+ Spec B: Only active :Resource: items are returned.
72
72
 
73
73
  Verdict: CONFLICTING (ambiguous) — "all" vs "only active" appear contradictory.
74
74
  Could be resolved by scoping each to different conditions (e.g., filtered vs unfiltered).
@@ -79,8 +79,8 @@ Could be resolved by scoping each to different conditions (e.g., filtered vs unf
79
79
  Do both specs impose constraints on the same `:Concept:` that cannot coexist?
80
80
 
81
81
  ```
82
- Spec A: :BatchSize: should be 100 items.
83
- Spec B: :BatchSize: should be 50 items for :Resource: types with attachments.
82
+ Spec A: :BatchSize: is 100 items.
83
+ Spec B: :BatchSize: is 50 items for :Resource: types with attachments.
84
84
 
85
85
  Verdict: COMPATIBLE — Spec B adds a conditional refinement, not a contradiction.
86
86
  ```
@@ -41,8 +41,8 @@ Work through each question for the pair under inspection. If any answer is "yes"
41
41
  Do the two specs make mutually exclusive assertions about the same behavior?
42
42
 
43
43
  ```
44
- Spec A: The system should return :Resource: items sorted by name in ascending order.
45
- Spec B: The system should return :Resource: items sorted by creation date in descending order.
44
+ Spec A: :Resource: items are returned sorted by name in ascending order.
45
+ Spec B: :Resource: items are returned sorted by creation date in descending order.
46
46
 
47
47
  Verdict: CONFLICTING — both define the sort order for the same response,
48
48
  but specify different fields and directions. A single implementation cannot
@@ -54,8 +54,8 @@ satisfy both unless scoped to different contexts.
54
54
  Does one spec set a state or value that the other spec assumes is different?
55
55
 
56
56
  ```
57
- Spec A: :TaskList: should initially be empty.
58
- Spec B: :TaskList: should contain a default "Welcome" :Task: on first load.
57
+ Spec A: :TaskList: is initially empty.
58
+ Spec B: :TaskList: contains a default "Welcome" :Task: on first load.
59
59
 
60
60
  Verdict: CONFLICTING — both define the initial state of :TaskList: differently.
61
61
  ```
@@ -65,8 +65,8 @@ Verdict: CONFLICTING — both define the initial state of :TaskList: differently
65
65
  Does the later spec silently replace behavior established by the earlier spec without acknowledging it?
66
66
 
67
67
  ```
68
- Spec A: The system should validate :User: credentials using an API key.
69
- Spec B: The system should validate :User: credentials using OAuth 2.0.
68
+ Spec A: :User: credentials are validated using an API key.
69
+ Spec B: :User: credentials are validated using OAuth 2.0.
70
70
 
71
71
  Verdict: CONFLICTING — both define the authentication mechanism but pick
72
72
  different approaches. The later spec overrides the earlier one.
@@ -77,8 +77,8 @@ different approaches. The later spec overrides the earlier one.
77
77
  Are the two specs ambiguous enough that a renderer could interpret them as conflicting, even if the user intends them to be complementary?
78
78
 
79
79
  ```
80
- Spec A: The system should return all :Resource: items.
81
- Spec B: The system should return only active :Resource: items.
80
+ Spec A: All :Resource: items are returned.
81
+ Spec B: Only active :Resource: items are returned.
82
82
 
83
83
  Verdict: CONFLICTING (ambiguous) — "all" vs "only active" appear contradictory.
84
84
  Could be resolved by scoping each to different conditions (e.g., filtered vs unfiltered).
@@ -89,8 +89,8 @@ Could be resolved by scoping each to different conditions (e.g., filtered vs unf
89
89
  Do both specs impose constraints on the same `:Concept:` that cannot coexist?
90
90
 
91
91
  ```
92
- Spec A: :BatchSize: should be 100 items.
93
- Spec B: :BatchSize: should be 50 items for :Resource: types with attachments.
92
+ Spec A: :BatchSize: is 100 items.
93
+ Spec B: :BatchSize: is 50 items for :Resource: types with attachments.
94
94
 
95
95
  Verdict: COMPATIBLE — Spec B adds a conditional refinement, not a contradiction.
96
96
  ```
@@ -31,20 +31,40 @@ A drafted functional spec (not yet inserted into the file), plus the full contex
31
31
 
32
32
  Work through each indicator. A single "yes" does not automatically mean the spec is too complex, but multiple "yes" answers are a strong signal.
33
33
 
34
+ ### 0. First-Spec Bootstrap Cost
35
+
36
+ Is this the first functional spec in a new root module with no implementation baseline supplied by
37
+ `requires`? If so, include the implicit cost of creating the project structure, package metadata,
38
+ framework configuration, entry point, initial source files, and unit-test infrastructure.
39
+
40
+ The first spec must be substantially simpler than a later spec. It should expose one minimal,
41
+ deterministic capability that can be invoked and tested. Setup without an observable result is not
42
+ acceptable, but combining bootstrap work with persistence, integrations, multiple interfaces,
43
+ branching workflows, or cross-cutting behavior is a strong `TOO COMPLEX` signal.
44
+
34
45
  ### 1. Number of Distinct Behaviors
35
46
 
36
47
  Does the spec describe more than one independently testable behavior?
37
48
 
38
- ```
39
49
  Too complex:
40
- - :User: should be able to create, edit, delete, and archive :Task: items,
41
- with validation on all fields and confirmation dialogs for destructive actions.
50
+ ```plain
51
+ ***functional specs***
52
+
53
+ - A :User: can create, edit, delete, and archive :Task: items, with validation on all fields and confirmation dialogs for destructive actions.
54
+ ```
42
55
 
43
56
  Acceptable (one behavior each):
44
- - :User: should be able to create :Task:. Only valid :Task: items can be added.
45
- - :User: should be able to edit :Task:.
46
- - :User: should be able to delete :Task:.
47
- - :User: should be able to archive :Task:.
57
+ ```plain
58
+ ***functional specs***
59
+
60
+ - A :User: can create :Task:. Only valid :Task: items can be added.
61
+
62
+ - A :User: can edit :Task:.
63
+
64
+ - A :User: can delete :Task:.
65
+
66
+ - A :User: can archive :Task:.
67
+
48
68
  ```
49
69
 
50
70
  ### 2. Number of Concepts Introduced or Modified
@@ -59,18 +79,23 @@ Does the spec require introducing new data structures, UI components, API endpoi
59
79
 
60
80
  Does the spec describe multiple conditional paths, modes, or special cases?
61
81
 
62
- ```
82
+
63
83
  Too complex:
64
- - The system should process :Order: differently based on :OrderType:.
65
- Standard orders are validated and stored. Express orders skip validation
66
- and are queued for immediate dispatch. Bulk orders are split into
67
- sub-orders of 100 items each, validated individually, and processed
68
- in parallel with progress tracking.
84
+ ```plain
85
+ ***functional specs***
86
+
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.
88
+ ```
69
89
 
70
90
  Acceptable (separate the modes):
71
- - The system should process standard :Order: by validating and storing it.
72
- - The system should process express :Order: by queuing it for immediate dispatch without validation.
73
- - The system should process bulk :Order: by splitting it into sub-orders of 100 items each.
91
+ ```plain
92
+ ***functional specs***
93
+
94
+ - A standard :Order: is validated and stored.
95
+
96
+ - An express :Order: is queued for immediate dispatch without validation.
97
+
98
+ - A bulk :Order: is split into sub-orders of 100 items each.
74
99
  - Each sub-order is processed individually.
75
100
  ```
76
101
 
@@ -78,32 +103,43 @@ Acceptable (separate the modes):
78
103
 
79
104
  Does the spec bundle core functionality with cross-cutting concerns like error handling, logging, retry logic, pagination, or caching?
80
105
 
81
- ```
82
106
  Too complex:
83
- - The system should fetch :Resource: items from the external API with
84
- pagination support, retry on transient errors with exponential backoff,
85
- cache results for 5 minutes, and log all API calls.
107
+ ```plain
108
+ ***functional specs***
109
+
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.
111
+ ```
86
112
 
87
113
  Acceptable (separate concerns):
88
- - The system should fetch :Resource: items from the external API.
89
- - The system should paginate when fetching :Resource: items from the external API.
90
- - The system should retry fetching :Resource: on transient errors using exponential backoff.
114
+ ```plain
115
+ ***functional specs***
116
+ - :Resource: items are fetched from the external API.
117
+
118
+ - :Resource: items are fetched from the external API in pages.
119
+
120
+ - Fetching :Resource: items is retried on transient errors using exponential backoff.
91
121
  ```
92
122
 
93
123
  ### 5. UI Complexity
94
124
 
95
125
  Does the spec describe a complete screen or page with multiple interactive elements, layouts, and state transitions?
96
126
 
97
- ```
98
127
  Too complex:
99
- - Display a dashboard showing :User: profile, recent :Task: items in a
100
- sortable table, a notification bell with unread count, and a sidebar
101
- with navigation links that highlights the active page.
128
+ ```plain
129
+ ***functional specs***
130
+
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.
132
+ ```
102
133
 
103
134
  Acceptable (build incrementally):
104
- - Display a dashboard page for :User:.
105
- - Show recent :Task: items in a sortable table on the dashboard.
106
- - Show a notification indicator with the unread count on the dashboard.
135
+ ```plain
136
+ ***functional specs***
137
+
138
+ - A dashboard page is shown for :User:.
139
+
140
+ - Recent :Task: items are shown in a sortable table on the dashboard.
141
+
142
+ - A notification indicator with the unread count is shown on the dashboard.
107
143
  ```
108
144
 
109
145
  ### 6. Data Transformation Complexity
@@ -113,14 +149,40 @@ Does the spec involve complex data mapping, aggregation, or transformation acros
113
149
  - Simple field mapping or filtering → likely fine
114
150
  - Multi-step transformations, joins across entities, or aggregations → likely too complex
115
151
 
116
- ### 7. Rough LOC Estimation
152
+ ### 7. Implied Technical Component
153
+
154
+ Does the spec imply building a substantial technical component — an engine, parser, scheduler, layout algorithm, state machine, or sync mechanism — **in addition to** the behavior it describes? A component is not a free primitive: code must be generated for it too, so it counts toward the 200-LOC budget and must be evaluated as part of the estimate. A spec that needs a component **and** wires up behavior on top of it is really two bodies of code in one spec — a strong "too complex" signal. Count the component's implementation, not just the glue that calls it.
155
+
156
+ Too complex (builds the component and uses it in one spec):
157
+ ```plain
158
+ ***functional specs***
159
+
160
+ - A :Report: is exported to PDF, laying out multi-page tables with repeating headers and page numbers, and charts rendered from :Report: data.
161
+ ```
162
+
163
+ Acceptable (component in its own spec, then referenced):
164
+ ```plain
165
+ ***functional specs***
166
+
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.
170
+
171
+ - A :Report: is exported to PDF using :PdfRenderer:, embedding charts rendered from :Report: data.
172
+ ```
173
+
174
+ When this indicator fires, the fix is `break-down-func-spec` Strategy 6 — extract the component into its own earlier spec and reference it.
175
+
176
+ ### 8. Rough LOC Estimation
117
177
 
118
178
  Mentally estimate the implementation. Consider:
119
179
  - New files that need to be created
120
180
  - New functions/methods
181
+ - Code for any implied technical component (engine, parser, algorithm), not just the glue that uses it
121
182
  - Data model changes (schema, migrations, types)
122
183
  - UI components (if applicable)
123
184
  - Test setup and assertions (unit tests are auto-generated alongside)
185
+ - For the first spec in a new root module, all project and test scaffold implied by implementation requirements
124
186
  - Error handling paths
125
187
  - Import statements and boilerplate
126
188
 
@@ -31,6 +31,7 @@ The functional spec to break down, plus the full `.plain` file it belongs to.
31
31
  - Cross-cutting concerns mixed with core functionality?
32
32
  - A full UI screen described in one spec?
33
33
  - Complex data transformations across multiple entities?
34
+ - Implies one substantial technical component (engine, parser, scheduler, algorithm, state machine, sync mechanism) that must be built in code?
34
35
  4. **Identify the split boundaries** — find the natural seams where the spec can be divided. Each resulting spec must be:
35
36
  - Independently meaningful (makes sense on its own with previous specs as context)
36
37
  - Self-contained (does not require a later spec to be useful)
@@ -50,15 +51,20 @@ If the spec bundles multiple independently testable actions, split each into its
50
51
 
51
52
  **Before:**
52
53
  ```plain
53
- - :User: should be able to create, edit, and delete :Recipe: items, with
54
- validation on all fields.
54
+ ***functional specs***
55
+
56
+ - A :User: can create, edit, and delete :Recipe: items, with validation on all fields.
55
57
  ```
56
58
 
57
59
  **After:**
58
60
  ```plain
59
- - :User: should be able to create a :Recipe:. Only valid :Recipe: items can be created.
60
- - :User: should be able to edit an existing :Recipe:. Validation rules apply to the edited fields.
61
- - :User: should be able to delete a :Recipe:.
61
+ ***functional specs***
62
+
63
+ - A :User: can create a :Recipe:. Only valid :Recipe: items can be created.
64
+
65
+ - A :User: can edit an existing :Recipe:. Validation rules apply to the edited fields.
66
+
67
+ - A :User: can delete a :Recipe:.
62
68
  ```
63
69
 
64
70
  ### Strategy 2: Separate Setup from Behavior
@@ -67,16 +73,20 @@ If the spec introduces a new construct and immediately defines complex behavior
67
73
 
68
74
  **Before:**
69
75
  ```plain
70
- - The system should provide a :MealPlan: screen that displays a weekly grid of
71
- :Slot: items, allows drag-and-drop reordering, and shows nutritional totals
72
- per day.
76
+ ***functional specs***
77
+
78
+ - The :MealPlan: screen displays a weekly grid of :Slot: items, allows drag-and-drop reordering, and shows nutritional totals per day.
73
79
  ```
74
80
 
75
81
  **After:**
76
82
  ```plain
77
- - The system should provide a :MealPlan: screen that displays a weekly grid of :Slot: items.
78
- - :User: should be able to reorder :Slot: items within a day on the :MealPlan: screen using drag-and-drop.
79
- - The :MealPlan: screen should display nutritional totals for each day.
83
+ ***functional specs***
84
+
85
+ - The :MealPlan: screen displays a weekly grid of :Slot: items.
86
+
87
+ - A :User: can reorder :Slot: items within a day on the :MealPlan: screen using drag-and-drop.
88
+
89
+ - The :MealPlan: screen displays nutritional totals for each day.
80
90
  ```
81
91
 
82
92
  ### Strategy 3: Separate Core Logic from Cross-Cutting Concerns
@@ -85,15 +95,20 @@ If the spec mixes primary functionality with error handling, retries, caching, p
85
95
 
86
96
  **Before:**
87
97
  ```plain
88
- - The system should fetch :Ingredient: data from the external API with
89
- pagination, retry on transient errors, and cache results for 10 minutes.
98
+ ***functional specs***
99
+
100
+ - :Ingredient: data is fetched from the external API with pagination, retry on transient errors, and caching for 10 minutes.
90
101
  ```
91
102
 
92
103
  **After:**
93
104
  ```plain
94
- - The system should fetch :Ingredient: data from the external API.
95
- - The system should paginate when fetching :Ingredient: data from the external API.
96
- - The system should retry fetching :Ingredient: data on transient errors.
105
+ ***functional specs***
106
+
107
+ - :Ingredient: data is fetched from the external API.
108
+
109
+ - :Ingredient: data is fetched from the external API in pages.
110
+
111
+ - Fetching :Ingredient: data is retried on transient errors.
97
112
  ```
98
113
 
99
114
  ### Strategy 4: Separate Conditional Paths
@@ -102,19 +117,22 @@ If the spec describes different modes or branches, give each its own spec.
102
117
 
103
118
  **Before:**
104
119
  ```plain
105
- - The system should process :MealPlan: generation differently based on :DietType:.
106
- Standard plans use round-robin assignment. Restrictive plans filter out
107
- excluded ingredients first, then apply round-robin. Custom plans allow manual
108
- slot-by-slot selection.
120
+ ***functional specs***
121
+
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.
109
123
  ```
110
124
 
111
125
  **After:**
112
126
  ```plain
113
- - The system should generate a standard :MealPlan: using round-robin :Recipe: assignment.
114
- - The system should generate a restrictive :MealPlan:.
127
+ ***functional specs***
128
+
129
+ - A standard :MealPlan: is generated using round-robin :Recipe: assignment.
130
+
131
+ - A restrictive :MealPlan: is generated.
115
132
  - Excluded :Ingredient: items are filtered out first.
116
133
  - Round-robin :Recipe: assignment is then applied.
117
- - The system should allow :User: to manually assign :Recipe: items to :Slot: items for a custom :MealPlan:.
134
+
135
+ - A :User: can manually assign :Recipe: items to :Slot: items for a custom :MealPlan:.
118
136
  ```
119
137
 
120
138
  ### Strategy 5: Build UI Incrementally
@@ -123,18 +141,48 @@ If the spec describes a full screen, split into layout + individual interactive
123
141
 
124
142
  **Before:**
125
143
  ```plain
126
- - Display the :Dashboard: screen showing a summary card with stats, a scrollable
127
- list of recent :MealPlan: items, a floating action button to create a new plan,
128
- and a bottom navigation bar.
144
+ ***functional specs***
145
+
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.
129
147
  ```
130
148
 
131
149
  **After:**
132
150
  ```plain
133
- - Display the :Dashboard: screen with a summary card showing :MealFrameStats:.
134
- - The :Dashboard: screen should show a scrollable list of recent :MealPlan: items.
135
- - The :Dashboard: screen should include a button to create a new :MealPlan:.
151
+ ***functional specs***
152
+
153
+ - The :Dashboard: screen shows a summary card with :MealFrameStats:.
154
+
155
+ - The :Dashboard: screen shows a scrollable list of recent :MealPlan: items.
156
+
157
+ - The :Dashboard: screen includes a button to create a new :MealPlan:.
136
158
  ```
137
159
 
160
+ ### Strategy 6: Extract a Reusable Technical Component
161
+
162
+ 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.
163
+
164
+ Define the component concept in `***definitions***` (via `add-concept`) before the first spec that references it.
165
+
166
+ **Before:**
167
+ ```plain
168
+ ***functional specs***
169
+
170
+ - A :Report: is exported to PDF, laying out multi-page tables with repeating headers, page numbers, and charts rendered from :Report: data.
171
+ ```
172
+
173
+ **After:**
174
+ ```plain
175
+ ***functional specs***
176
+
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.
180
+
181
+ - A :Report: is exported to PDF using :PdfRenderer:, embedding charts rendered from :Report: data.
182
+ ```
183
+
184
+ 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.
185
+
138
186
  ## Preserving Chronological Order
139
187
 
140
188
  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.
@@ -151,6 +199,7 @@ If the original spec had acceptance tests, redistribute them to the most appropr
151
199
  - [ ] Replacement specs are in correct chronological order
152
200
  - [ ] Each replacement spec is independently meaningful
153
201
  - [ ] All `:Concepts:` referenced in replacement specs are defined
202
+ - [ ] Any extracted technical component is defined as a concept, built by its own earlier spec, and only **referenced** (not re-described) by the original
154
203
  - [ ] Replacement specs are language-agnostic
155
204
  - [ ] All external interfaces remain explicit
156
205
  - [ ] Acceptance tests (if any) have been redistributed or rewritten
@@ -44,14 +44,19 @@ description: Shared API definitions and reqs
44
44
  ---
45
45
 
46
46
  ***definitions***
47
+
47
48
  - :ApiClient: is the HTTP client used to communicate with external services.
49
+
48
50
  - :ApiResponse: is the response returned by :ApiClient:.
49
51
 
50
52
  ***implementation reqs***
53
+
51
54
  - :Implementation: should handle HTTP errors by raising appropriate exceptions.
55
+
52
56
  - :ApiClient: should support configurable timeouts.
53
57
 
54
58
  ***test reqs***
59
+
55
60
  - :ConformanceTests: should mock all external HTTP calls made by :ApiClient:.
56
61
  ```
57
62
 
@@ -71,7 +76,9 @@ import:
71
76
  > So this module must define them:
72
77
 
73
78
  ***definitions***
79
+
74
80
  - :AuthSchema: is the JSON schema describing the authentication data structure.
81
+
75
82
  - :AuthApiSpec: is the OpenAPI specification for the external service's auth endpoint.
76
83
  ```
77
84
 
@@ -50,11 +50,12 @@ description: Extended module that builds on base_module
50
50
  ---
51
51
 
52
52
  ***definitions***
53
+
53
54
  - :NewFeature: is a feature added by this module.
54
55
 
55
56
  ***functional specs***
56
57
 
57
- - The system should support :NewFeature:.
58
+ - :NewFeature: is available.
58
59
  ```
59
60
 
60
61
  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).