plain-forge 1.0.1

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 (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +247 -0
  3. package/bin/cli.mjs +143 -0
  4. package/forge/docs/.gitkeep +0 -0
  5. package/forge/rules/definitions.md +57 -0
  6. package/forge/rules/exported-concepts.md +39 -0
  7. package/forge/rules/func-specs.md +72 -0
  8. package/forge/rules/impl-reqs.md +50 -0
  9. package/forge/rules/import-modules.md +51 -0
  10. package/forge/rules/required-concepts.md +45 -0
  11. package/forge/rules/requires-modules.md +59 -0
  12. package/forge/rules/test-reqs.md +47 -0
  13. package/forge/skills/add-acceptance-test/SKILL.md +98 -0
  14. package/forge/skills/add-concept/SKILL.md +67 -0
  15. package/forge/skills/add-feature/SKILL.md +136 -0
  16. package/forge/skills/add-functional-spec/SKILL.md +81 -0
  17. package/forge/skills/add-functional-specs/SKILL.md +115 -0
  18. package/forge/skills/add-implementation-requirement/SKILL.md +73 -0
  19. package/forge/skills/add-resource/SKILL.md +108 -0
  20. package/forge/skills/add-template/SKILL.md +65 -0
  21. package/forge/skills/add-test-requirement/SKILL.md +68 -0
  22. package/forge/skills/analyze-2-func-specs/SKILL.md +102 -0
  23. package/forge/skills/analyze-func-specs/SKILL.md +124 -0
  24. package/forge/skills/analyze-if-func-spec-too-complex/SKILL.md +152 -0
  25. package/forge/skills/break-down-func-spec/SKILL.md +156 -0
  26. package/forge/skills/check-plain-env/SKILL.md +288 -0
  27. package/forge/skills/consolidate-concepts/SKILL.md +193 -0
  28. package/forge/skills/create-import-module/SKILL.md +98 -0
  29. package/forge/skills/create-requires-module/SKILL.md +104 -0
  30. package/forge/skills/debug-specs/SKILL.md +189 -0
  31. package/forge/skills/forge-integration/SKILL.md +443 -0
  32. package/forge/skills/forge-plain/SKILL.md +333 -0
  33. package/forge/skills/implement-conformance-testing-script/SKILL.md +247 -0
  34. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_cypress.ps1 +324 -0
  35. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_golang.ps1 +100 -0
  36. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +102 -0
  37. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.ps1 +92 -0
  38. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +100 -0
  39. package/forge/skills/implement-prepare-environment-script/SKILL.md +242 -0
  40. package/forge/skills/implement-prepare-environment-script/assets/prepare_environment_java.sh +42 -0
  41. package/forge/skills/implement-prepare-environment-script/assets/prepare_environment_python.sh +81 -0
  42. package/forge/skills/implement-unit-testing-script/SKILL.md +133 -0
  43. package/forge/skills/implement-unit-testing-script/assets/run_unittests_flutter.ps1 +82 -0
  44. package/forge/skills/implement-unit-testing-script/assets/run_unittests_golang.ps1 +68 -0
  45. package/forge/skills/implement-unit-testing-script/assets/run_unittests_java.sh +45 -0
  46. package/forge/skills/implement-unit-testing-script/assets/run_unittests_python.ps1 +76 -0
  47. package/forge/skills/implement-unit-testing-script/assets/run_unittests_python.sh +90 -0
  48. package/forge/skills/implement-unit-testing-script/assets/run_unittests_react.ps1 +83 -0
  49. package/forge/skills/init-config-file/SKILL.md +261 -0
  50. package/forge/skills/init-plain-project/SKILL.md +124 -0
  51. package/forge/skills/load-plain-reference/SKILL.md +646 -0
  52. package/forge/skills/plain-healthcheck/SKILL.md +132 -0
  53. package/forge/skills/refactor-module/SKILL.md +197 -0
  54. package/forge/skills/resolve-spec-conflict/SKILL.md +88 -0
  55. package/forge/skills/run-codeplain/SKILL.md +540 -0
  56. package/package.json +42 -0
@@ -0,0 +1,193 @@
1
+ ---
2
+ name: consolidate-concepts
3
+ description: >-
4
+ Gather concept definitions scattered across multiple modules into a single
5
+ shared import module in template/. Removes the moved definitions from the
6
+ original modules and adds the new import to their frontmatter. Use when
7
+ concepts are duplicated or spread across modules and should be centralized.
8
+ ---
9
+
10
+ # Consolidate Concepts
11
+
12
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
13
+
14
+ ## When to Use
15
+
16
+ - Multiple modules define the same or closely related concepts independently.
17
+ - A `requires` chain uses long `exported_concepts` lists to share definitions that would be simpler as an import.
18
+ - After a `refactor-module` split, shared concepts ended up duplicated or awkwardly exported.
19
+ - The user wants a single source of truth for domain concepts used across modules.
20
+
21
+ ## Guiding Principle
22
+
23
+ This is a structural refactoring. The **behavior** of every affected module must remain **identical**. No functional spec, implementation req, or test req is changed. Only concept definitions move — from scattered locations into one shared import module — and the modules' `import` lists are updated to reference it.
24
+
25
+ ## Input
26
+
27
+ The set of modules to consolidate from, plus optionally the name for the new (or existing) import module. If not specified, ask the user.
28
+
29
+ ## Phase 1 — Analyze Concepts Across Modules
30
+
31
+ 1. **Read all source modules.** For each `.plain` file involved, read the full file including frontmatter, definitions, implementation reqs, test reqs, and functional specs. Also read their `import` and `requires` chains.
32
+ 2. **Build a concept inventory.** For each concept defined across all source modules, record:
33
+ - Where it is defined (which file, which line)
34
+ - Which modules reference it (in definitions, functional specs, implementation reqs, or test reqs)
35
+ - Whether it is currently in an `exported_concepts` list
36
+ - Which other concepts it references in its definition (dependency graph)
37
+ 3. **Identify consolidation candidates.** A concept should be consolidated if:
38
+ - It is defined in one module but referenced by specs in another module (currently shared via `exported_concepts`)
39
+ - It is duplicated across multiple modules
40
+ - It is a foundational domain concept that logically belongs in a shared vocabulary
41
+ 4. **Identify concepts that should stay local.** A concept should remain in its module if:
42
+ - It is only used within that single module's specs and definitions
43
+ - It is an internal implementation detail not meaningful outside that module
44
+
45
+ ## Phase 2 — Plan the Consolidation
46
+
47
+ Present the plan to the user and get explicit confirmation before making changes.
48
+
49
+ ### 2a. Choose the target import module
50
+
51
+ - **New import module** — create a new `.plain` file in `template/`. Choose a name that reflects the shared domain (e.g., `template/myapp-concepts.plain`).
52
+ - **Existing import module** — add the concepts to an import module that is already used by the affected modules. This avoids adding another import reference.
53
+
54
+ If the target is an existing import module, read it fully to understand what it already contains.
55
+
56
+ ### 2b. Determine which concepts move
57
+
58
+ For each consolidation candidate, confirm:
59
+ - The concept will be removed from its current module's `***definitions***` section.
60
+ - The concept will be added to the target import module's `***definitions***` section.
61
+ - The concept's full definition text (including all sub-bullets for attributes and constraints) is moved verbatim.
62
+
63
+ ### 2c. Determine concept ordering in the target
64
+
65
+ Concepts in the import module must be ordered so that every concept is defined **after** any concepts it references. Use the dependency graph from Phase 1 to establish a valid topological order.
66
+
67
+ ### 2d. Determine import and export changes
68
+
69
+ For each affected module, determine the frontmatter changes:
70
+
71
+ | Change | When |
72
+ |--------|------|
73
+ | Add the new import to `import` list | Module does not already import the target |
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) |
76
+
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
+
79
+ ### 2e. Present the plan
80
+
81
+ Summarize for the user:
82
+ - Target import module (new or existing) and its path
83
+ - List of concepts being moved, with source module for each
84
+ - List of concepts staying local (and why)
85
+ - Frontmatter changes per module (`import` additions, `exported_concepts` removals)
86
+ - Confirmation that no functional specs, implementation reqs, or test reqs are changing
87
+
88
+ Get explicit user confirmation before proceeding.
89
+
90
+ ## Phase 3 — Execute
91
+
92
+ ### 3a. Create or update the import module
93
+
94
+ If creating a new import module:
95
+ 1. Create `template/<name>.plain` with YAML frontmatter. If it needs concepts from another import, add that to its own `import` list.
96
+ 2. Add a `***definitions***` section with all consolidated concepts in dependency order.
97
+ 3. Do **not** add `***functional specs***` — import modules must not contain them.
98
+
99
+ If updating an existing import module:
100
+ 1. Read the current file.
101
+ 2. Insert the new concepts into the `***definitions***` section, respecting dependency order relative to existing concepts.
102
+ 3. Verify no concept name collisions with concepts already in the file or its own imports.
103
+
104
+ ### 3b. Update each source module
105
+
106
+ For each module that had concepts moved out:
107
+
108
+ 1. **Remove the concept definitions** from the module's `***definitions***` section. Remove the full definition including all sub-bullets.
109
+ 2. **Add the import** to the module's YAML frontmatter `import` list (if not already present).
110
+ 3. **Update `exported_concepts`** — remove concepts that no longer need to be exported (see 2d).
111
+ 4. **Do not touch** `***functional specs***`, `***implementation reqs***`, or `***test reqs***` — concept references (`:ConceptName:`) in these sections remain unchanged since the concept is now provided by the import.
112
+
113
+ ### 3c. Update downstream modules (if applicable)
114
+
115
+ If concepts were removed from a module's `exported_concepts` and downstream `requires` modules relied on them:
116
+ 1. Add the new import to the downstream module's `import` list so it gets the concepts directly.
117
+ 2. Verify the downstream module's specs can still resolve all concept references.
118
+
119
+ ## Phase 4 — Verify
120
+
121
+ ### 4a. Concept availability check
122
+
123
+ For every affected module (source modules, downstream modules, and the import module itself):
124
+ - [ ] Every `:Concept:` referenced in functional specs is resolvable (defined locally, via import, or via exported concepts from requires)
125
+ - [ ] Every `:Concept:` referenced in definitions is defined before the concept that references it
126
+ - [ ] Every `:Concept:` referenced in implementation reqs and test reqs is resolvable
127
+
128
+ ### 4b. No duplicates check
129
+
130
+ - [ ] No concept is defined in both the import module and a source module
131
+ - [ ] No concept is defined in both the import module and another import that a source module uses
132
+ - [ ] Concept names are globally unique across each module's full resolution scope (local + imports + requires exports)
133
+
134
+ ### 4c. Definition integrity check
135
+
136
+ - [ ] Each moved concept's definition text is identical to the original — no rewording, no lost sub-bullets
137
+ - [ ] Concept ordering in the import module respects the dependency graph (no forward references)
138
+
139
+ ### 4d. No behavioral change check
140
+
141
+ - [ ] No `***functional specs***` were modified in any module
142
+ - [ ] No `***implementation reqs***` were modified in any module
143
+ - [ ] No `***test reqs***` were modified in any module
144
+ - [ ] No `***acceptance tests***` were modified in any module
145
+
146
+ ### 4e. Structural validation
147
+
148
+ For the import module:
149
+ - [ ] File is in the `template/` directory
150
+ - [ ] Does not contain `***functional specs***`
151
+ - [ ] Does not use `requires`
152
+ - [ ] YAML frontmatter is correctly formatted
153
+
154
+ For each source module:
155
+ - [ ] YAML frontmatter `import` list includes the target import module
156
+ - [ ] `exported_concepts` is correct (no over-export, no missing exports)
157
+ - [ ] Module still has at least one functional spec and one implementation req
158
+
159
+ ### 4f. Read all modified files
160
+
161
+ Read each modified `.plain` file in full and present the changes to the user for approval. If the user requests changes, apply them and re-verify.
162
+
163
+ ## Common Pitfalls
164
+
165
+ ### Moving a concept that is only used locally
166
+ If a concept is only referenced within a single module, consolidating it into a shared import adds unnecessary coupling. Keep it local.
167
+
168
+ ### Forgetting to update downstream requires modules
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
+
171
+ ### Breaking concept ordering
172
+ Concepts in the import module must be topologically ordered. If `:Meal:` references `:MealType:` in its definition, then `:MealType:` must appear first. The source modules may have had them in the right order locally, but merging concepts from different modules requires re-establishing a valid order.
173
+
174
+ ### Creating circular imports
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
+
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.
179
+
180
+ ## Validation Checklist
181
+
182
+ - [ ] User confirmed the consolidation plan before execution
183
+ - [ ] All moved concepts are defined in the import module with identical text
184
+ - [ ] Concepts are in valid dependency order in the import module
185
+ - [ ] No concept is defined in both the import module and a source module
186
+ - [ ] Every affected module's `import` list includes the target import module
187
+ - [ ] `exported_concepts` updated correctly — no missing exports, no unnecessary exports
188
+ - [ ] All concept references in all affected modules resolve correctly
189
+ - [ ] No functional specs, implementation reqs, test reqs, or acceptance tests were modified
190
+ - [ ] Import module is in `template/` and has no functional specs or requires
191
+ - [ ] No circular imports introduced
192
+ - [ ] Downstream requires modules updated if needed
193
+ - [ ] User approved the final result
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: create-import-module
3
+ description: >-
4
+ Create a ***plain import module that provides shared definitions,
5
+ implementation reqs, and test reqs for other modules to import. Use when
6
+ the user wants to create a new .plain file that contains only definitions,
7
+ implementation reqs, and/or test reqs — no functional specs.
8
+ ---
9
+
10
+ # Create Import Module
11
+
12
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
13
+
14
+ ## What an Import Module Is
15
+
16
+ An import module is a `.plain` file that lives in the **`template/`** directory and contains **only** `***definitions***`, `***implementation reqs***`, and/or `***test reqs***`. It must **not** contain `***functional specs***` and must **not** use `requires` in its frontmatter. Other modules pull in its content via the `import` field in their YAML frontmatter, gaining access to its definitions and reqs.
17
+
18
+ Use import modules for:
19
+ - Sharing concept definitions across multiple modules
20
+ - Providing common implementation requirements (e.g., technology stack, coding standards)
21
+ - Providing common test requirements
22
+ - Creating reusable foundational structure (templates)
23
+
24
+ If the module needs functional specs (i.e., it describes what software should do), it is not an import module — see the `create-requires-module` skill.
25
+
26
+ ## Workflow
27
+
28
+ 1. **Determine what shared content this module should provide** — which definitions, implementation reqs, or test reqs will other modules need?
29
+ 2. **Create the `.plain` file in the `template/` directory** with YAML frontmatter. Use `required_concepts` to declare concepts that importing modules must define. It may optionally `import` other templates for layered reuse, but must **not** use `requires`.
30
+ 3. **Add the shared content** — definitions, implementation reqs, and/or test reqs.
31
+ 4. **Do not add `***functional specs***`** — import modules must not contain functional specs.
32
+ 5. **Verify concept availability** — ensure all `:Concepts:` referenced are either defined in this module, provided by its own imports, declared as `required_concepts`, or are predefined concepts.
33
+
34
+ ## Format
35
+
36
+ The `import` field is a list of module paths in the YAML frontmatter:
37
+
38
+ ```plain
39
+ ---
40
+ import:
41
+ - base_template
42
+ required_concepts: [":AppName:"]
43
+ description: Shared API definitions and reqs
44
+ ---
45
+
46
+ ***definitions***
47
+ - :ApiClient: is the HTTP client used to communicate with external services.
48
+ - :ApiResponse: is the response returned by :ApiClient:.
49
+
50
+ ***implementation reqs***
51
+ - :Implementation: should handle HTTP errors by raising appropriate exceptions.
52
+ - :ApiClient: should support configurable timeouts.
53
+
54
+ ***test reqs***
55
+ - :ConformanceTests: should mock all external HTTP calls made by :ApiClient:.
56
+ ```
57
+
58
+ The default import directory is `template/` — the `template/` prefix is not needed in import paths. The `.plain` extension is omitted. Note the absence of `***functional specs***` — import modules must not have them.
59
+
60
+ ## Satisfying Required Concepts
61
+
62
+ If an imported template declares `required_concepts`, the importing module **must** define those concepts in its own `***definitions***` section:
63
+
64
+ ```plain
65
+ ---
66
+ import:
67
+ - auth_template
68
+ ---
69
+
70
+ > auth_template declares required_concepts: [":AuthSchema:", ":AuthApiSpec:"]
71
+ > So this module must define them:
72
+
73
+ ***definitions***
74
+ - :AuthSchema: is the JSON schema describing the authentication data structure.
75
+ - :AuthApiSpec: is the OpenAPI specification for the external service's auth endpoint.
76
+ ```
77
+
78
+ ## Import vs Requires
79
+
80
+ | Aspect | `import` | `requires` |
81
+ |--------|----------|------------|
82
+ | Pulls in definitions | Yes | No (only `exported_concepts`) |
83
+ | Pulls in implementation reqs | Yes | No |
84
+ | Pulls in test reqs | Yes | No |
85
+ | Pulls in functional specs | No | Yes (as previous requirements) |
86
+ | Copies generated code | No | Yes |
87
+ | Typical use | Templates, shared definitions | Build dependency chain |
88
+
89
+ ## Validation Checklist
90
+
91
+ - [ ] Module file is in the `template/` directory
92
+ - [ ] Module does **not** contain `***functional specs***`
93
+ - [ ] Module does **not** use `requires` in its frontmatter
94
+ - [ ] Contains at least one of: definitions, implementation reqs, or test reqs
95
+ - [ ] All `required_concepts` from any imports this module itself uses are satisfied
96
+ - [ ] `required_concepts` declared for any concepts referenced but not defined here
97
+ - [ ] No concept name collisions between this module's imports and local definitions
98
+ - [ ] YAML frontmatter is correctly formatted between `---` markers
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: create-requires-module
3
+ description: >-
4
+ Create a ***plain module that uses requires to depend on another module in
5
+ the build chain. Use when the user wants to create a new .plain file that
6
+ builds on top of a previously built module, inheriting its functional specs
7
+ and generated code as a starting point.
8
+ ---
9
+
10
+ # Create Requires Module
11
+
12
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
13
+
14
+ ## What Requires Does
15
+
16
+ `requires` establishes a build ordering between modules. The required module is built **before** the current one. This does not necessarily mean the current module extends or depends on the required module's code — it may be completely independent. The `requires` relationship simply ensures the build order is correct.
17
+
18
+ When this module is rendered:
19
+ - The required module's generated code (`plain_modules/<required_module>`) is copied as the starting point.
20
+ - The required module's `***functional specs***` become visible as **previous functional specs**.
21
+ - Only `exported_concepts` from the required module are available (not its full definitions).
22
+
23
+ Use `requires` for:
24
+ - Ensuring a module is built after another in the build chain
25
+ - Building on top of an existing module's functionality
26
+ - Extending a base module with additional features
27
+
28
+ If you only need shared definitions and reqs (no functional specs, no generated code), use `import` instead — see the `create-import-module` skill.
29
+
30
+ ## Workflow
31
+
32
+ 1. **Identify the dependency.** Determine which module this new module builds on. That module must already exist and be renderable.
33
+ 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/`.
34
+ 3. **Review the required module's functional specs** — they will be treated as previous requirements. Your new functional specs must not conflict with them.
35
+ 4. **Review the required module's `exported_concepts`** — only those concepts are available to reference from the required module.
36
+ 5. **Add module-specific content** — definitions, implementation reqs, test reqs, and functional specs unique to this module.
37
+ 6. **Check for conflicts** between your new functional specs and the required module's specs.
38
+
39
+ ## Format
40
+
41
+ The `requires` field is a list of module paths in the YAML frontmatter:
42
+
43
+ ```plain
44
+ ---
45
+ requires:
46
+ - base_module
47
+ import:
48
+ - shared_template
49
+ description: Extended module that builds on base_module
50
+ ---
51
+
52
+ ***definitions***
53
+ - :NewFeature: is a feature added by this module.
54
+
55
+ ***functional specs***
56
+
57
+ - The system should support :NewFeature:.
58
+ ```
59
+
60
+ 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).
61
+
62
+ ## Exported Concepts
63
+
64
+ The required module controls what concepts are visible via `exported_concepts`:
65
+
66
+ ```plain
67
+ > In the required module's frontmatter:
68
+ ---
69
+ exported_concepts: [":StorageClient:", ":BackupResult:"]
70
+ ---
71
+ ```
72
+
73
+ Only `:StorageClient:` and `:BackupResult:` would be available to modules that `require` this one. All other concepts from the required module are internal.
74
+
75
+ ## Chronological Ordering with Requires
76
+
77
+ Functional specs from `requires` modules are considered **previous functional specs**. This means:
78
+ - They are already rendered and their code exists.
79
+ - Your new specs are rendered after them, with full awareness of what they defined.
80
+ - Your new specs must not conflict with the required module's specs.
81
+ - The renderer sees the required module's functional specs as context when rendering yours.
82
+
83
+ The current module may or may not be functionally related to the required module. In some cases `requires` simply enforces build order — the two modules may be independent pieces of the same project that need to be built in sequence.
84
+
85
+ ## Import vs Requires
86
+
87
+ | Aspect | `import` | `requires` |
88
+ |--------|----------|------------|
89
+ | Pulls in definitions | Yes | No (only `exported_concepts`) |
90
+ | Pulls in implementation reqs | Yes | No |
91
+ | Pulls in test reqs | Yes | No |
92
+ | Pulls in functional specs | No | Yes (as previous requirements) |
93
+ | Copies generated code | No | Yes |
94
+ | Typical use | Templates, shared definitions | Build dependency chain |
95
+
96
+ ## Validation Checklist
97
+
98
+ - [ ] Module file is at the repository root (not in `template/`)
99
+ - [ ] Required module exists and is renderable
100
+ - [ ] Required module's `exported_concepts` provide the concepts you need
101
+ - [ ] New functional specs do not conflict with the required module's specs
102
+ - [ ] Module has at least one functional spec and one implementation req
103
+ - [ ] Both `requires` and `import` are used correctly (not mixed up)
104
+ - [ ] YAML frontmatter is correctly formatted between `---` markers
@@ -0,0 +1,189 @@
1
+ ---
2
+ name: debug-specs
3
+ description: >-
4
+ Investigate a bug observed in the running application by reading the generated
5
+ code in plain_modules/, tracing the issue back to the specs, and fixing only
6
+ the .plain files. Generated code is never modified. Use when the user reports
7
+ unexpected behavior, visual glitches, crashes, or incorrect logic in the app.
8
+ ---
9
+
10
+ # Debug Specs
11
+
12
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
13
+
14
+ ## When to Use
15
+
16
+ - The user observes a bug in the running application (visual, behavioral, crash, performance).
17
+ - A conformance test or unit test is failing.
18
+ - The generated code does something unexpected or incorrect.
19
+ - The user points to a specific functional spec that seems wrong.
20
+
21
+ ## Guiding Principle
22
+
23
+ Generated code in `plain_modules/` and `conformance_tests/` is **read-only** — it exists solely as evidence for diagnosis. All fixes are applied exclusively to the `.plain` spec files. The workflow is: observe → read generated code → trace to spec → fix the spec.
24
+
25
+ ## Input
26
+
27
+ 1. **The module name** — identifies the `plain_modules/<module_name>/` directory and the corresponding `.plain` file(s).
28
+ 2. **The user's observation** — what is wrong? This can be a bug description, a screenshot, a test failure, an error message, or a general "this doesn't work right."
29
+ 3. **Optional: a specific functional spec** — if the user suspects a particular spec, start there. Otherwise, investigate broadly.
30
+
31
+ ## Phase 1 — Understand the Context
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.
34
+ 2. **Read the user's observation carefully.** Rephrase it back to confirm understanding. Identify:
35
+ - What is the expected behavior?
36
+ - What is the actual behavior?
37
+ - Is this a visual issue, a logic issue, a crash, or a data issue?
38
+
39
+ ## Phase 2 — Investigate the Generated Code
40
+
41
+ Read files in `plain_modules/<module_name>/` to understand what the renderer produced. **Do not modify any generated files.**
42
+
43
+ ### 2a. Narrow the search
44
+
45
+ If the user pointed to a specific spec or area:
46
+ - Identify which generated files implement that spec's behavior.
47
+ - Read those files to understand the current implementation.
48
+
49
+ If the investigation is broad:
50
+ - Start from the entry point and follow the execution path related to the observed bug.
51
+ - Use the observation to narrow down: UI issue → look at widgets/views, logic issue → look at business logic/providers, data issue → look at models/repositories.
52
+
53
+ ### 2b. Read the relevant generated code
54
+
55
+ For each relevant file:
56
+ 1. Read the code and understand what it does.
57
+ 2. Compare the behavior to what the spec says it should do.
58
+ 3. Note any discrepancies — places where the code doesn't match the spec's intent.
59
+
60
+ ### 2c. Check conformance tests and unit tests (if relevant)
61
+
62
+ If the bug manifests as a test failure:
63
+ 1. Read the failing test in `conformance_tests/<module_name>/` or `plain_modules/<module_name>/test/`.
64
+ 2. Understand what the test expects vs. what the implementation does.
65
+ 3. Determine whether the test expectation is correct (matches the spec) or incorrect (doesn't match the spec).
66
+
67
+ ## Phase 3 — Diagnose the Root Cause
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:
70
+
71
+ | Root Cause | Symptom | Fix |
72
+ |------------|---------|-----|
73
+ | **Ambiguous spec** | The spec is correct in intent, but vague enough that the renderer interpreted it differently than intended. | Add explicit detail to the spec to eliminate the ambiguity. |
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
+ | **Conflicting specs** | Two specs contradict each other, causing the renderer to produce inconsistent behavior. | Use the `resolve-spec-conflict` skill. |
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
+ | **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
+ ### How to diagnose
80
+
81
+ 1. **Read the spec that governs the buggy behavior.** Does it clearly and unambiguously describe the correct behavior?
82
+ - If the spec is clear and correct but the code is wrong → **ambiguous spec** (the renderer misinterpreted it) or **missing implementation req**.
83
+ - If the spec doesn't mention the behavior at all → **missing spec**.
84
+ - If the spec explicitly describes the wrong behavior → **incorrect spec**.
85
+ 2. **Check for conflicts.** Could another spec be overriding or contradicting this behavior?
86
+ - Read all functional specs that touch the same concepts.
87
+ - If two specs are in tension → **conflicting specs**.
88
+ 3. **Check implementation reqs.** Is the renderer missing guidance on how to implement correctly?
89
+ - Does the implementation req specify the right library, pattern, or constraint?
90
+ - If a platform-specific or framework-specific detail is missing → **missing implementation req**.
91
+
92
+ ## Phase 4 — Fix the Specs
93
+
94
+ Apply the fix based on the diagnosed root cause. Use the appropriate skill:
95
+
96
+ | Root Cause | Skill to Use |
97
+ |------------|-------------|
98
+ | Ambiguous spec | Edit the spec inline — add sub-bullets or reword for clarity |
99
+ | Missing spec | `add-functional-spec` |
100
+ | Conflicting specs | `resolve-spec-conflict` |
101
+ | Incorrect spec | Edit the spec inline — rewrite the incorrect part |
102
+ | Missing implementation req | `add-implementation-requirement` |
103
+
104
+ ### Fix guidelines
105
+
106
+ - **Minimal changes.** Only modify what is necessary to fix the observed bug. Avoid rewriting unrelated specs.
107
+ - **Preserve chronological order.** If adding a new spec, place it correctly relative to existing specs.
108
+ - **Stay language-agnostic.** Functional specs describe behavior, not implementation. Platform-specific guidance belongs in implementation reqs.
109
+ - **Respect the 200 LOC limit.** If a fix makes a spec too complex, use `break-down-func-spec` to split it.
110
+ - **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
+
112
+ ## Phase 5 — Verify and Report
113
+
114
+ 1. **Re-read the modified `.plain` file(s)** in full to confirm correctness.
115
+ 2. **Summarize the findings** for the user:
116
+ - What was observed (the bug)
117
+ - What the generated code was doing (the symptom in code)
118
+ - Which spec(s) caused the issue (the root cause)
119
+ - What was changed in the specs (the fix)
120
+ - What to expect after re-rendering
121
+ 3. **If uncertain**, present the diagnosis and proposed fix to the user for confirmation before making changes. Some bugs have multiple possible causes — when in doubt, explain the options and let the user decide.
122
+
123
+ ## Debugging Strategies
124
+
125
+ ### Strategy 1: Observation-Driven (most common)
126
+
127
+ Start from the user's observation and work backward through the code to the spec.
128
+
129
+ ```
130
+ User sees bug → Read generated code → Find the responsible code path →
131
+ Identify which spec governs that code → Diagnose why the spec produced wrong code →
132
+ Fix the spec
133
+ ```
134
+
135
+ ### Strategy 2: Spec-Focused
136
+
137
+ The user suspects a specific spec. Compare the spec directly against the generated code.
138
+
139
+ ```
140
+ User points to spec → Read the spec → Find the generated code that implements it →
141
+ Compare spec intent vs. code behavior → Diagnose the gap → Fix the spec
142
+ ```
143
+
144
+ ### Strategy 3: Test-Failure-Driven
145
+
146
+ A test is failing. Use the test as the entry point.
147
+
148
+ ```
149
+ Read failing test → Understand what it expects → Read the implementation →
150
+ 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)
152
+ ```
153
+
154
+ ### Strategy 4: Differential
155
+
156
+ The bug appeared after a new spec was added. Compare before and after.
157
+
158
+ ```
159
+ Identify the newly added spec → Read the specs it might conflict with →
160
+ Check if the new spec introduced the bug → Use resolve-spec-conflict or
161
+ revise the new spec
162
+ ```
163
+
164
+ ## Common Pitfalls
165
+
166
+ ### Fixing the code instead of the spec
167
+ Never modify files in `plain_modules/` or `conformance_tests/`. Even if the fix is obvious in the code, the change must be made in the `.plain` file so it persists across re-renders.
168
+
169
+ ### Treating symptoms instead of root causes
170
+ If the user says "the button is in the wrong place," don't just add positioning detail. Investigate why the renderer placed it there — the root cause might be a missing layout spec, an ambiguous screen description, or a conflict with another spec.
171
+
172
+ ### Over-specifying the fix
173
+ Adding too much implementation detail to a functional spec (e.g., specific pixel values, widget names, CSS properties) makes it brittle. Prefer behavior-level fixes. Use implementation reqs for platform-specific guidance.
174
+
175
+ ### Ignoring ripple effects
176
+ A spec fix may affect other specs that reference the same concepts. Always check neighboring specs for conflicts after making a change.
177
+
178
+ ## Validation Checklist
179
+
180
+ - [ ] User's observation is clearly understood (expected vs. actual behavior)
181
+ - [ ] Generated code has been read to understand the current implementation
182
+ - [ ] Root cause is diagnosed (ambiguous / missing / conflicting / incorrect / missing impl req)
183
+ - [ ] Fix is applied in the `.plain` file(s) only — no generated code modified
184
+ - [ ] Fix is minimal and targeted to the observed bug
185
+ - [ ] Fix does not introduce new conflicts with existing specs
186
+ - [ ] Modified specs respect the 200 LOC limit
187
+ - [ ] Modified specs remain language-agnostic
188
+ - [ ] Chronological ordering is preserved
189
+ - [ ] Summary of findings and fix presented to the user