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.
- package/LICENSE +21 -0
- package/README.md +247 -0
- package/bin/cli.mjs +143 -0
- package/forge/docs/.gitkeep +0 -0
- package/forge/rules/definitions.md +57 -0
- package/forge/rules/exported-concepts.md +39 -0
- package/forge/rules/func-specs.md +72 -0
- package/forge/rules/impl-reqs.md +50 -0
- package/forge/rules/import-modules.md +51 -0
- package/forge/rules/required-concepts.md +45 -0
- package/forge/rules/requires-modules.md +59 -0
- package/forge/rules/test-reqs.md +47 -0
- package/forge/skills/add-acceptance-test/SKILL.md +98 -0
- package/forge/skills/add-concept/SKILL.md +67 -0
- package/forge/skills/add-feature/SKILL.md +136 -0
- package/forge/skills/add-functional-spec/SKILL.md +81 -0
- package/forge/skills/add-functional-specs/SKILL.md +115 -0
- package/forge/skills/add-implementation-requirement/SKILL.md +73 -0
- package/forge/skills/add-resource/SKILL.md +108 -0
- package/forge/skills/add-template/SKILL.md +65 -0
- package/forge/skills/add-test-requirement/SKILL.md +68 -0
- package/forge/skills/analyze-2-func-specs/SKILL.md +102 -0
- package/forge/skills/analyze-func-specs/SKILL.md +124 -0
- package/forge/skills/analyze-if-func-spec-too-complex/SKILL.md +152 -0
- package/forge/skills/break-down-func-spec/SKILL.md +156 -0
- package/forge/skills/check-plain-env/SKILL.md +288 -0
- package/forge/skills/consolidate-concepts/SKILL.md +193 -0
- package/forge/skills/create-import-module/SKILL.md +98 -0
- package/forge/skills/create-requires-module/SKILL.md +104 -0
- package/forge/skills/debug-specs/SKILL.md +189 -0
- package/forge/skills/forge-integration/SKILL.md +443 -0
- package/forge/skills/forge-plain/SKILL.md +333 -0
- package/forge/skills/implement-conformance-testing-script/SKILL.md +247 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_cypress.ps1 +324 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_golang.ps1 +100 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +102 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.ps1 +92 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +100 -0
- package/forge/skills/implement-prepare-environment-script/SKILL.md +242 -0
- package/forge/skills/implement-prepare-environment-script/assets/prepare_environment_java.sh +42 -0
- package/forge/skills/implement-prepare-environment-script/assets/prepare_environment_python.sh +81 -0
- package/forge/skills/implement-unit-testing-script/SKILL.md +133 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_flutter.ps1 +82 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_golang.ps1 +68 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_java.sh +45 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_python.ps1 +76 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_python.sh +90 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_react.ps1 +83 -0
- package/forge/skills/init-config-file/SKILL.md +261 -0
- package/forge/skills/init-plain-project/SKILL.md +124 -0
- package/forge/skills/load-plain-reference/SKILL.md +646 -0
- package/forge/skills/plain-healthcheck/SKILL.md +132 -0
- package/forge/skills/refactor-module/SKILL.md +197 -0
- package/forge/skills/resolve-spec-conflict/SKILL.md +88 -0
- package/forge/skills/run-codeplain/SKILL.md +540 -0
- 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
|