plain-forge 1.0.23 → 1.0.24-next.019bba8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +14 -11
  2. package/bin/cli.mjs +5 -4
  3. package/forge/rules/plain-forge.md +10 -0
  4. package/forge/skills/add-concept/SKILL.md +1 -1
  5. package/forge/skills/add-feature/SKILL.md +8 -7
  6. package/forge/skills/add-feature/references/checklist.md +2 -2
  7. package/forge/skills/add-functional-spec/SKILL.md +14 -10
  8. package/forge/skills/add-functional-specs/SKILL.md +14 -10
  9. package/forge/skills/add-implementation-requirement/SKILL.md +1 -1
  10. package/forge/skills/add-resource/SKILL.md +3 -2
  11. package/forge/skills/add-template/SKILL.md +1 -1
  12. package/forge/skills/add-test-requirement/SKILL.md +4 -4
  13. package/forge/skills/add-test-scenarios/SKILL.md +98 -0
  14. package/forge/skills/analyze-2-func-specs/SKILL.md +1 -1
  15. package/forge/skills/analyze-func-specs/SKILL.md +2 -2
  16. package/forge/skills/analyze-if-func-spec-too-complex/SKILL.md +44 -24
  17. package/forge/skills/break-down-func-spec/SKILL.md +57 -33
  18. package/forge/skills/check-plain-env/SKILL.md +2 -2
  19. package/forge/skills/consolidate-concepts/SKILL.md +8 -8
  20. package/forge/skills/create-import-module/SKILL.md +1 -1
  21. package/forge/skills/create-requires-module/SKILL.md +6 -3
  22. package/forge/skills/debug-specs/SKILL.md +14 -8
  23. package/forge/skills/forge-plain/SKILL.md +3 -3
  24. package/forge/skills/forge-plain/references/checklist.md +3 -3
  25. package/forge/skills/forge-plain/references/phase-1-product.md +2 -2
  26. package/forge/skills/forge-plain/references/phase-2-tech.md +1 -1
  27. package/forge/skills/forge-plain/references/phase-3-testing.md +5 -5
  28. package/forge/skills/init-config-file/SKILL.md +2 -2
  29. package/forge/skills/init-plain-project/SKILL.md +6 -6
  30. package/forge/skills/load-plain-reference/SKILL.md +25 -25
  31. package/forge/skills/load-plain-reference/references/project-model.md +2 -1
  32. package/forge/skills/load-plain-reference/references/rendering-and-testing.md +7 -5
  33. package/forge/{rules → skills/load-plain-reference/rules}/bullet-continuation.md +11 -11
  34. package/forge/{rules → skills/load-plain-reference/rules}/concise-specs-examples.md +100 -69
  35. package/forge/{rules → skills/load-plain-reference/rules}/concise-specs-integration-examples.md +39 -24
  36. package/forge/{rules → skills/load-plain-reference/rules}/concise-specs.md +3 -2
  37. package/forge/{rules → skills/load-plain-reference/rules}/func-specs.md +37 -28
  38. package/forge/{rules → skills/load-plain-reference/rules}/impl-reqs.md +1 -1
  39. package/forge/{rules → skills/load-plain-reference/rules}/integration-embedded-testing.md +1 -1
  40. package/forge/{rules → skills/load-plain-reference/rules}/linked-resources.md +7 -4
  41. package/forge/{rules → skills/load-plain-reference/rules}/module-structure.md +16 -9
  42. package/forge/{rules → skills/load-plain-reference/rules}/requires-modules.md +1 -0
  43. package/forge/skills/load-plain-reference/rules/semantic-ids.md +47 -0
  44. package/forge/skills/load-plain-reference/rules/test-plain-files.md +67 -0
  45. package/forge/{rules → skills/load-plain-reference/rules}/test-reqs.md +6 -6
  46. package/forge/skills/plain-healthcheck/SKILL.md +31 -13
  47. package/forge/skills/refactor-module/SKILL.md +16 -16
  48. package/forge/skills/resolve-section-ownership/SKILL.md +3 -3
  49. package/forge/skills/resolve-spec-conflict/SKILL.md +14 -8
  50. package/package.json +1 -1
  51. package/forge/skills/add-acceptance-test/SKILL.md +0 -101
  52. /package/forge/{rules → skills/load-plain-reference/rules}/definitions.md +0 -0
  53. /package/forge/{rules → skills/load-plain-reference/rules}/examples/integration-embedded-testing/prepare_environment_java.sh +0 -0
  54. /package/forge/{rules → skills/load-plain-reference/rules}/examples/integration-embedded-testing/run_conformance_tests_java.sh +0 -0
  55. /package/forge/{rules → skills/load-plain-reference/rules}/examples/integration-embedded-testing/run_unittests_java.sh +0 -0
  56. /package/forge/{rules → skills/load-plain-reference/rules}/exported-concepts.md +0 -0
  57. /package/forge/{rules → skills/load-plain-reference/rules}/import-modules.md +0 -0
  58. /package/forge/{rules → skills/load-plain-reference/rules}/integration-embedded.md +0 -0
  59. /package/forge/{rules → skills/load-plain-reference/rules}/integration-standalone.md +0 -0
  60. /package/forge/{rules → skills/load-plain-reference/rules}/integrations.md +0 -0
  61. /package/forge/{rules → skills/load-plain-reference/rules}/required-concepts.md +0 -0
@@ -38,8 +38,9 @@ A linked resource **must not** be any of the following:
38
38
 
39
39
  ***functional specs***
40
40
 
41
- - A :User: can add a :Task: by POSTing :TaskCreateRequest: to the `POST /tasks` endpoint of :TasksAPI:.
42
- - The endpoint responds per :TasksAPI:.
41
+ # add-task
42
+ A :User: can add a :Task: by POSTing :TaskCreateRequest: to the `POST /tasks` endpoint of :TasksAPI:.
43
+ - The endpoint responds per :TasksAPI:.
43
44
  ```
44
45
 
45
46
  ## Each linked resource is referenced from exactly one place
@@ -55,9 +56,11 @@ A linked resource **must not** be any of the following:
55
56
 
56
57
  ***functional specs***
57
58
 
58
- - A :User: can add a :Task: using :TaskModalSpec:.
59
+ # add-task
60
+ A :User: can add a :Task: using :TaskModalSpec:.
59
61
 
60
- - A :User: can edit a :Task: using :TaskModalSpec:.
62
+ # edit-task
63
+ A :User: can edit a :Task: using :TaskModalSpec:.
61
64
  ```
62
65
 
63
66
  ## File location and path resolution
@@ -9,7 +9,8 @@ When creating a new `.plain` file or reviewing the structure of a whole file, al
9
9
  ## File skeleton
10
10
  - A `.plain` file is one **module**: optional YAML frontmatter between `---` markers, followed by sections marked with `***section name***` headers
11
11
  - The frontmatter, when present, must be the first thing in the file
12
- - Every content line inside a section must be a `- ` list item — see `bullet-continuation.md`
12
+ - Every content line inside `***definitions***`, `***implementation reqs***`, and `***test reqs***` is a `- ` list item — see `bullet-continuation.md`
13
+ - Every functionality in `***functional specs***` is a `# <func-id>` heading followed by its body — see `func-specs.md` and `semantic-ids.md`
13
14
  - Every line must be as short and plain as its content allows — see `concise-specs.md`
14
15
 
15
16
  ## Frontmatter fields
@@ -23,18 +24,19 @@ When creating a new `.plain` file or reviewing the structure of a whole file, al
23
24
  | `required_concepts` | Declare concepts an import module expects the importing module to define | `required-concepts.md` |
24
25
 
25
26
  ## Sections
26
- - There are exactly four top-level section markers: `***definitions***`, `***implementation reqs***`, `***test reqs***`, and `***functional specs***`
27
+ - A spec plain file has exactly four top-level section markers: `***definitions***`, `***implementation reqs***`, `***test reqs***`, and `***functional specs***`
27
28
  - Each section appears **at most once** per file; all are optional (which ones are allowed depends on the module kind below)
28
- - `***acceptance tests***` is **never a top-level section** — it appears only nested under a single functional spec (see `func-specs.md`)
29
+ - `***conformance tests***` and `***acceptance tests***` never appear in a spec plain file, not even nested under a functional spec; they are the two sections of a test plain file (see `test-plain-files.md`)
29
30
  - Write sections in canonical order: `***definitions***` → `***implementation reqs***` → `***test reqs***` → `***functional specs***`
30
31
  - Definitions come first because every concept must be defined before it is referenced
31
- - Functional specs come last because they are rendered incrementally and their nested acceptance tests close the file
32
+ - Functional specs come last because they are rendered incrementally
32
33
 
33
34
  ## Module kinds
34
35
  - A **root module** lives at the repository root and carries behavior: it contains `***functional specs***`
35
36
  - To be renderable, a root module needs at least one functional spec plus the implementation reqs to build it — its own or from an `import`ed module (implementation reqs are not inherited through `requires`). A frontmatter-only file is a valid scaffold, but it cannot be rendered until a functional spec is added
36
37
  - A **requires module** is a root module that is used by another root module via `requires` directive (see `requires-modules.md`)
37
38
  - An **import module** provides shared content that other modules pull in via `import`: it contains only `***definitions***`, `***implementation reqs***`, and/or `***test reqs***` — never `***functional specs***`, never `requires` (see `import-modules.md`)
39
+ - A **test plain file** holds the scenarios of one functionality of a root module; its frontmatter `module:` and `func_id:` bind it to that functionality, by convention it lives under `tests/<module>/`, and it has no section of a spec plain file (see `test-plain-files.md`)
38
40
 
39
41
  ## Section ownership (where a fact lives)
40
42
  - The renderer reads each kind of fact **only from its owning section** — a fact placed in the wrong section is silently ignored, not flagged
@@ -47,7 +49,7 @@ When creating a new `.plain` file or reviewing the structure of a whole file, al
47
49
  | HOW the software is built — tech stack, architecture, coding standards — and **everything about `:UnitTests:`** | `***implementation reqs***` | `impl-reqs.md` |
48
50
  | **Everything about `:ConformanceTests:`** — framework, run command, mocking and network policy | `***test reqs***` | `test-reqs.md` |
49
51
  | WHAT the software does — observable, language-agnostic behavior | `***functional specs***` | `func-specs.md` |
50
- | End-to-end workflow verification of one functional spec | nested `***acceptance tests***` | `func-specs.md` |
52
+ | Test scenarios of one functionality, conformance and acceptance | the test plain file (by convention `tests/<module>/<func-id>.plain`) | `test-plain-files.md` |
51
53
 
52
54
  ## Comments
53
55
  - Lines beginning with `>` are ignored when rendering
@@ -67,9 +69,12 @@ When creating a new `.plain` file or reviewing the structure of a whole file, al
67
69
 
68
70
  ***functional specs***
69
71
 
70
- - A :Widget: can be created with up to {{ max_tags }} tags.
72
+ # create-widget
73
+ A :Widget: can be created with up to {{ max_tags }} tags.
71
74
  {% if max_tags > 1 %}
72
- - A :Widget: can have its tags listed.
75
+
76
+ # list-widget-tags
77
+ A :Widget: can have its tags listed.
73
78
  {% endif %}
74
79
  ```
75
80
 
@@ -99,7 +104,9 @@ import:
99
104
 
100
105
  ***functional specs***
101
106
 
102
- - A :Task: can be added to the :TaskList:.
107
+ # add-task
108
+ A :Task: can be added to the :TaskList:.
103
109
 
104
- - The :TaskList: is displayed.
110
+ # show-task-list
111
+ The :TaskList: is displayed.
105
112
  ```
@@ -13,6 +13,7 @@ When creating or editing a `.plain` file that uses `requires`, or one that is re
13
13
  - The `***functional specs***` of the required module **and of all its ancestors** become visible as **previous functional specs** — this visibility **is transitive** down the whole chain
14
14
  - Of a required module's definitions, only the concepts listed in its `exported_concepts` are visible; the module's other definitions stay internal. Each exported concept arrives with its full definition text
15
15
  - Export visibility **is not transitive**: an ancestor's exports are visible only if that ancestor is itself listed in `requires`
16
+ - The test plain files of a required module stay with that module; the current module never lists scenarios for a required module's functionality (see `test-plain-files.md`)
16
17
 
17
18
  ## Chain topology
18
19
 
@@ -0,0 +1,47 @@
1
+ ---
2
+ description: Syntax, uniqueness, and use of semantic func-ids and scenario-ids in .plain files
3
+ ---
4
+
5
+ # Rules for semantic IDs
6
+
7
+ Every functionality in `***functional specs***` and every scenario in a test plain file carries a semantic ID. The ID is the stable name that test plain files, render commands, render state, change detection, logs, and generated tests use for that functionality or scenario. Always follow these rules when writing or reading one.
8
+
9
+ ## Two kinds of ID
10
+
11
+ | ID | Written as | Identifies | Unique within |
12
+ |---|---|---|---|
13
+ | func-id | `# <func-id>` heading in `***functional specs***` of a spec plain file | one functionality | its module |
14
+ | scenario-id | `# <scenario-id>` heading in `***conformance tests***` or `***acceptance tests***` of a test plain file | one scenario | its functionality, across every test plain file bound to that functionality |
15
+
16
+ ## Syntax
17
+ - Lowercase letters, digits, and hyphens only: `add-task`, `export-csv-2`, `ctrl-d-exit`
18
+ - The heading is `# ` (hash, one space) followed by the ID and nothing else
19
+
20
+ ## Uniqueness
21
+ - A func-id is unique in its module; two modules may use the same func-id
22
+ - A scenario-id is unique for its functionality after every test plain file bound to that functionality is merged; two functionalities may use the same scenario-id
23
+ - Before adding an ID, search the module (or the functionality's test plain files) for the same heading; a duplicate is a syntax error that `plain-parser check` reports
24
+
25
+ ## Stability
26
+ - An ID is an identity, not a label: a functionality keeps its func-id for as long as it exists, even when its text changes
27
+ - To the renderer, renaming a func-id is deleting one functionality and adding another; rename only when the user asks, then rename `func_id:` in every test plain file bound to it and move the file to the new conventional path
28
+ - Never renumber or reorder IDs; the order of the headings in the file is the render order, the ID carries no order
29
+
30
+ ## How coding agents use IDs
31
+ - Name a functionality by its func-id (`<module>:<func-id>` when the module is not obvious) in questions to the user, in review snippets, in commit messages, and in render commands; never by position ("the third spec")
32
+ - Pick the func-id before writing the functional spec text, check that it is unique in the module, then write the heading and the body (see `func-specs.md`)
33
+ - A new functionality is finished only when its test plain file exists (by convention at `tests/<module>/<func-id>.plain`) with at least one conformance scenario (see `test-plain-files.md`)
34
+ - A generated conformance or acceptance test carries the scenario-id of the scenario it implements; when a test fails, the scenario-id in its name leads back to the scenario text
35
+ - Everything about one functionality is found through its func-id: the `# <func-id>` heading in the spec plain file, the test plain files whose frontmatter names it, and the generated tests labelled with its scenario-ids
36
+
37
+ ## Format
38
+
39
+ ```plain
40
+ ***functional specs***
41
+
42
+ # add-task
43
+ A :User: can add a :Task:. Only valid :Task: items are added.
44
+
45
+ # delete-task
46
+ A :User: can delete a :Task:.
47
+ ```
@@ -0,0 +1,67 @@
1
+ ---
2
+ description: Syntax and authoring rules for test plain files, which hold the conformance and acceptance scenarios of one functionality
3
+ ---
4
+
5
+ # Rules for test plain files
6
+
7
+ A test plain file holds the test scenarios of one functionality. Conformance scenarios test the core functionality, its expected use; acceptance scenarios catch the edge cases, the use that is not expected. The renderer generates conformance and acceptance tests from these scenarios and from nothing else: it never invents a scenario. Scenarios are written at authoring time and are reviewed like any other spec line. Always follow these rules when creating or editing one.
8
+
9
+ ## File skeleton
10
+ - A test plain file is a `.plain` file with YAML frontmatter and two sections, in this order: `***conformance tests***`, then `***acceptance tests***`
11
+ - Both sections are required; `***acceptance tests***` may be empty
12
+ - The frontmatter has exactly two keys, both required:
13
+ - `module:` the name of the module that holds the functionality (the spec plain file's name without `.plain`)
14
+ - `func_id:` the func-id of the functionality (see `semantic-ids.md`)
15
+ - The pair `(module, func_id)` must name a functionality that exists; a pair with no match is an error
16
+ - A test plain file must not have `***definitions***`, `***implementation reqs***`, `***test reqs***`, or `***functional specs***`
17
+ - Comment lines starting with `>` are allowed, as in a spec plain file
18
+
19
+ ## Location
20
+ - By convention a test plain file lives at `tests/<module>/<func_id>.plain`, with `tests/` next to the spec plain file
21
+ - The location and the file name are convention only: the renderer discovers test plain files by reading the frontmatter of every `.plain` file under its test folders
22
+ - plain-forge always writes to the conventional path, one file per functionality
23
+ - More than one test plain file may bind to the same functionality; their scenarios are merged, and scenario-ids must be unique across the merged set. Hand-written files may use this; plain-forge keeps one file per functionality
24
+
25
+ ## Scenarios
26
+ - A scenario is a `# <scenario-id>` heading (see `semantic-ids.md`) followed by free text that says what is done and what result is expected
27
+ - A scenario body line may be prose, a `- ` bullet, or any other text, as long as it does not start with `# ` (that starts a new scenario) or with `***`
28
+ - A scenario may reference every concept visible to its module: its own definitions, its `import` modules, and the `exported_concepts` of its `requires` modules. It defines no concepts
29
+ - Scenarios are language-agnostic: they describe behavior through the observable interface (CLI, HTTP, files, UI) and never name a function, class, or file of the implementation
30
+ - A scenario tests the functionality as a black box; the generated test never imports the implementation's internals
31
+ - A scenario is a direct consequence of the functional spec: it does not contradict, narrow, or extend the behavior the spec states
32
+ - Each scenario states one concrete, checkable outcome; "works correctly" is not an outcome
33
+ - Scenario text follows `concise-specs.md`: no narration, no rationale, no step a reader would assume
34
+
35
+ ## Wording
36
+ - plain-forge writes every scenario in plain English; hand-written scenarios may use any shape
37
+ - Values that matter to the check are concrete (`named "Buy milk"`, `exits with status 0`), never descriptive (`a valid name`)
38
+
39
+ ## Conformance scenarios
40
+ - `***conformance tests***` holds the scenarios of the expected use of the functionality: its main path, with valid parameters, the expected caller, and the data present.
41
+ - These scenarios gate the functionality: it is done only when every conformance scenario passes
42
+ - When conformance tests are enabled for the module (its `config.yaml` has a `conformance-tests-script`), every functionality has at least one conformance scenario; an empty section is an error
43
+ - Cover the main path first, then each variant of expected use the functional spec states (another valid input shape, an optional parameter); stop when every expected behavior has one scenario
44
+ - Do not write the same scenario twice in different words; one scenario per distinct outcome
45
+
46
+ ## Acceptance scenarios
47
+ - `***acceptance tests***` holds the scenarios of use that is not expected
48
+ - Acceptance scenarios are written only on the developer's explicit instruction, through a coding agent or by hand; the section may be empty
49
+ - An acceptance scenario is rendered after the conformance tests of its functionality pass
50
+ - A scenario that needs a dependency to fail (a backend that does not respond, a database that is unavailable) is written only when `***test reqs***` let the test cause that failure, for example with a local mock of that dependency; otherwise ask the user before writing it
51
+ - The kind of use decides the section, not the number of functionalities the scenario touches (see *Scenarios across functionalities*)
52
+
53
+ ## Scenarios across functionalities
54
+ - A scenario may use functionalities rendered before the one it is bound to, for its setup or as steps of a longer path
55
+ - Such a scenario is bound to the last functionality it exercises, because the earlier ones must exist when it runs
56
+ - It goes under `***conformance tests***` when every step is expected use, and under `***acceptance tests***` when any step is not; plain-forge writes one only when the user asks for it
57
+
58
+ ## Keeping test plain files in step with functional specs
59
+ - Every change to a functional spec is followed by a review of its test plain file: scenarios that no longer follow from the spec are removed or rewritten, and new behavior gets a scenario
60
+ - When a functionality is split, each new functionality gets its own test plain file; each scenario moves to the functionality it tests
61
+ - When a functionality is deleted, its test plain file is deleted
62
+ - When a functionality moves to another module, its test plain file moves to that module's folder and its `module:` key is updated
63
+ - When a func-id is renamed, `func_id:` is renamed in every test plain file bound to it and the file moves to the new conventional path
64
+
65
+ ## Relation to `***test reqs***`
66
+ - `***test reqs***` of the module say how `:ConformanceTests:` and `:AcceptanceTests:` are built and run (framework, command, network policy); the scenarios say what they check
67
+ - A fact about the framework or the run command never goes into a scenario, and a scenario never goes into `***test reqs***`
@@ -9,7 +9,7 @@ When writing or editing a `***test reqs***` section in a `.plain` file, always f
9
9
  ## Conformance tests only
10
10
  - Test reqs specify how **conformance tests** should be written and run
11
11
  - Unit test guidance goes in `***implementation reqs***`, not here
12
- - Acceptance tests are nested under individual functional specs, not here
12
+ - Test scenarios, conformance and acceptance, live in test plain files, not here — see `test-plain-files.md`
13
13
  - Behavioral requirements go in `***functional specs***`, not here
14
14
 
15
15
  ## `:ConformanceTests:` lives here (hard rule)
@@ -28,11 +28,11 @@ When writing or editing a `***test reqs***` section in a `.plain` file, always f
28
28
 
29
29
  ## Test type reference
30
30
 
31
- | Test type | Where to specify | Generated | Purpose |
32
- |-----------|-----------------|-----------|---------|
33
- | Unit tests | `***implementation reqs***` | Automatically | Test individual functionalities in isolation |
34
- | Conformance tests | `***test reqs***` | Automatically | Verify each functionality's implementation against its functional spec |
35
- | Acceptance tests | `***acceptance tests***` under a functional spec | Manually | Verify implementation of a functional spec through a specific end-to-end scenario |
31
+ | Test type | Where to specify | Generated from | Purpose |
32
+ |-----------|-----------------|----------------|---------|
33
+ | Unit tests | `***implementation reqs***` | the implementation, by the renderer | Test individual functionalities in isolation |
34
+ | Conformance tests | how: `***test reqs***`; what: `***conformance tests***` of the functionality's test plain file | the conformance scenarios, one test per scenario-id | Verify the expected use of one functionality, its main path |
35
+ | Acceptance tests | how: `***test reqs***`; what: `***acceptance tests***` of the functionality's test plain file | the acceptance scenarios, one test per scenario-id | Verify one functionality under use that is not expected: invalid parameters, wrong or missing authentication, missing data |
36
36
 
37
37
  ## No duplication
38
38
  - Do not duplicate guidance already present in the file or its imports
@@ -3,8 +3,8 @@ name: plain-healthcheck
3
3
  description: >-
4
4
  Verification gate for a ***plain project. Verifies that every `config.yaml`
5
5
  exists and points at scripts that actually live in `test_scripts/`, parses
6
- every top module with `plain-parser check`, and checks every module for what
7
- the parser can't judge (section ownership, bullets, linked resources). Run this whenever anything in the project is finalized —
6
+ every top module with `plain-parser check`, and checks every module and test plain file for
7
+ what the parser can't judge (section ownership, bullets, scenarios, linked resources). Run this whenever anything in the project is finalized —
8
8
  including (but not limited to) the end of `forge-plain`, the end of
9
9
  `add-feature`, after `debug-specs`, after any single-skill edit that
10
10
  finalizes a concept, functional spec, requirement, template, or config —
@@ -13,7 +13,7 @@ description: >-
13
13
 
14
14
  # Plain Healthcheck
15
15
 
16
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet. Step 3b checks every module against those rules, and they are needed to fix what `plain-parser` reports in Step 3a.
16
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation. Step 3b checks every module against those rules, and they are needed to fix what `plain-parser` reports in Step 3a.
17
17
 
18
18
  ## When to run
19
19
 
@@ -22,7 +22,7 @@ Run this skill **whenever anything in the ***plain project is finalized** and th
22
22
  - **End of `forge-plain`** (Phase 4) — before handing off the render target.
23
23
  - **End of `add-feature`** (Phase 3 final review) — before declaring the feature done.
24
24
  - **End of `debug-specs`** — after applying a fix, before telling the user to re-render.
25
- - **After finalizing any single edit** that changes the renderable surface — e.g. after `add-concept`, `add-functional-spec`, `add-functional-specs`, `add-implementation-requirement`, `add-test-requirement`, `add-acceptance-test`, `add-template`, `add-resource`, `resolve-spec-conflict`, `break-down-func-spec`, `consolidate-concepts`, `refactor-module`, `create-import-module`, `create-requires-module`, or any of the `implement-*-testing-script` skills.
25
+ - **After finalizing any single edit** that changes the renderable surface — e.g. after `add-concept`, `add-functional-spec`, `add-functional-specs`, `add-implementation-requirement`, `add-test-requirement`, `add-test-scenarios`, `add-template`, `add-resource`, `resolve-spec-conflict`, `break-down-func-spec`, `consolidate-concepts`, `refactor-module`, `create-import-module`, `create-requires-module`, or any of the `implement-*-testing-script` skills.
26
26
  - **After hand-editing** a `.plain` file, a `config.yaml`, or anything under `test_scripts/`.
27
27
  - **On demand** — whenever the user asks whether the project is in a renderable state.
28
28
 
@@ -40,9 +40,10 @@ The skill is a **detect → fix → re-run** loop. It does not stop at the first
40
40
  2. Identify **top modules** — every module that is not `requires`-ed by any other module. A single-stack project has one top module; a multi-part project (e.g. backend + frontend) has one top module per part.
41
41
  3. List every `config.yaml` in the repo (root and per-part directories such as `backend/`, `frontend/`).
42
42
  4. List every script under `test_scripts/`.
43
- 5. Pair each top module with the `config.yaml` that governs it. The pairing rule is: the config file in the same directory as the top module wins; failing that, the repo-root `config.yaml`. A multi-part project must have one config per part — record any top module that has no governing config as a failure.
43
+ 5. List every test plain file: each `.plain` file in the project whose frontmatter has `module:` and `func_id:` (by convention under `tests/`). Record the pair it binds to.
44
+ 6. Pair each top module with the `config.yaml` that governs it. The pairing rule is: the config file in the same directory as the top module wins; failing that, the repo-root `config.yaml`. A multi-part project must have one config per part — record any top module that has no governing config as a failure.
44
45
 
45
- Print a one-line inventory summary so the rest of the run is easy to follow, e.g. `Top modules: backend/api.plain (config: backend/config.yaml), frontend/web.plain (config: frontend/config.yaml). Scripts in test_scripts/: 4.`
46
+ Print a one-line inventory summary so the rest of the run is easy to follow, e.g. `Top modules: backend/api.plain (config: backend/config.yaml), frontend/web.plain (config: frontend/config.yaml). Scripts in test_scripts/: 4. Test plain files: 12.`
46
47
 
47
48
  ### Step 2 — Validate every `config.yaml`
48
49
 
@@ -77,24 +78,39 @@ Step 3 has two halves: a mechanical parse by `plain-parser`, then the checks tha
77
78
  [`plain-parser`](https://pypi.org/project/plain-parser/) is the ***plain parser. It parses a module together with its whole `import` / `requires` chain, so running it on every top module covers every module in the project.
78
79
 
79
80
  1. **Check it is installed.** Run `plain-parser --help`. If the command is not found, look for it where `plain-forge install` puts it before giving up: `~/.local/bin/plain-parser` (`%USERPROFILE%\.local\bin\plain-parser.exe` on Windows), or the directory printed by `uv tool dir --bin`. If it is there, run it by that full path for the rest of this step and tell the user to add the directory to `PATH`. If it is nowhere, stop and report `FAIL` with the install command (`pipx install plain-parser` or `uv tool install plain-parser`; it needs Python 3.11 or newer). Do **not** fall back to checking these rules by reading the files — without the parser there is no syntax gate.
80
- 2. **Run it from the top module's own directory**, once per top module:
81
+ 2. **Check that it parses the current syntax.** Write this probe module as `probe.plain` into a fresh temporary directory and run `plain-parser check probe.plain` there:
82
+
83
+ ```plain
84
+ ***implementation reqs***
85
+
86
+ - :Implementation: is written in Python 3.12.
87
+
88
+ ***functional specs***
89
+
90
+ # probe
91
+ :Implementation: starts.
92
+ ```
93
+
94
+ If it prints `OK`, continue. If it reports an error, the installed plain-parser predates the current syntax (`# func-id` headings, test plain files). Then record one failure against the project — `plain-parser <version> does not parse the current ***plain syntax; install the release that does and run plain-healthcheck again` — skip steps 3 and 4 of 3a, still run 3b, and report `FAIL`. Never rewrite the specs into an older syntax to satisfy the old parser.
95
+ 3. **Run it from the top module's own directory**, once per top module:
81
96
 
82
97
  ```bash
83
98
  cd <top-module-dir> && plain-parser check <top>.plain
84
99
  ```
85
100
 
86
101
  Add `--config-name <name>` when the governing config is not named `config.yaml`. `plain-parser` reads `template-dir` from the config next to the `.plain` file or in the working directory, and exits `2` when it finds one in both — running from the module's own directory avoids that in multi-part projects.
87
- 3. **Read the result.** Exit `0` prints `<file>: OK`. Exit `1` prints `Error: …` on stderr — record that message verbatim as a failure against the top module. Exit `2` is a usage or config error (ambiguous or malformed config) — record it against the config.
102
+ 4. **Read the result.** Exit `0` prints `<file>: OK`. Exit `1` prints `Error: …` on stderr — record that message verbatim as a failure against the top module. Exit `2` is a usage or config error (ambiguous or malformed config) — record it against the config.
88
103
 
89
- `plain-parser` checks, among other things: frontmatter, that every `import` / `requires` entry exists and the graph has no cycles, that `requires` modules have one fixed order, that imported modules have no functional specs, section headings (allowed, not duplicated, `***definitions***` first, `***acceptance tests***` nested under a functional spec), concepts (defined, exported and required correctly), that a module with functional specs has implementation reqs, and that every linked resource and template resolves to an existing, relative, non-`.plain` file. It does not always report every error in one run, so after fixing what it reported, run it again until it prints `OK`.
104
+ `plain-parser` checks, among other things: frontmatter, that every `import` / `requires` entry exists and the graph has no cycles, that `requires` modules have one fixed order, that imported modules have no functional specs, section headings (allowed, not duplicated, `***definitions***` first), `# func-id` headings in `***functional specs***` with unique func-ids, test plain files (frontmatter `module:` and `func_id:` naming an existing functionality, both sections present, unique scenario-ids), concepts (defined, exported and required correctly), that a module with functional specs has implementation reqs, and that every linked resource and template resolves to an existing, relative, non-`.plain` file. It does not always report every error in one run, so after fixing what it reported, run it again until it prints `OK`.
90
105
 
91
106
  #### 3b. Check what the parser can't judge
92
107
 
93
108
  Check every `.plain` module against the rules loaded by `load-plain-reference`:
94
109
 
95
110
  1. **Section ownership.** No fact sits in a section that doesn't own it — `:UnitTests:` facts only in `***implementation reqs***`, `:ConformanceTests:` facts only in `***test reqs***`, technology only in `***implementation reqs***`.
96
- 2. **Bullets.** Every line in every section is a valid `- ` list item or a correctly indented sub-bullet — no bare continuation lines.
111
+ 2. **Bullets and headings.** Every line in `***definitions***`, `***implementation reqs***`, and `***test reqs***` is a valid `- ` list item or a correctly indented sub-bullet — no bare continuation lines. Every functionality in `***functional specs***` is a `# <func-id>` heading followed by its body.
97
112
  3. **Linked resources.** Every linked resource is a single **text** file (not a binary), and no URL or folder path appears in the surrounding spec text unless it is a runtime value the generated software itself uses.
113
+ 4. **Test plain files.** Every test plain file binds to an existing functionality (`module:` names a module, `func_id:` one of its `# func-id` headings) and has both sections in order. Scenario-ids are unique per functionality across every file bound to it. When the module's `config.yaml` has a `conformance-tests-script`, every functionality has at least one conformance scenario; a functionality with none is a failure that names `add-test-scenarios`. A scenario under `***conformance tests***` that describes use that is not expected (invalid parameters, wrong or missing authentication, missing data), or one under `***acceptance tests***` that describes the expected use, is a failure that names `add-test-scenarios`.
98
114
 
99
115
  Functional-spec complexity is checked when a spec is authored (`add-functional-spec(s)` → `analyze-if-func-spec-too-complex`). Re-run `analyze-if-func-spec-too-complex` here only for a spec that was hand-edited since it was authored.
100
116
 
@@ -105,7 +121,7 @@ Treat 3a and 3b together as a hard gate: the healthcheck **only passes** when `p
105
121
  Iterate until it passes:
106
122
 
107
123
  1. Identify the offending `.plain` file, the line, and the kind of issue: missing or duplicated concept, cyclic definition, broken `import`/`requires`, misplaced fact, bare continuation line, missing resource or template, etc.
108
- 2. Fix only the `.plain` files (or the relevant `config.yaml` / template) using the appropriate edit skill — `add-concept`, `add-functional-spec`, `add-functional-specs`, `add-implementation-requirement`, `resolve-section-ownership`, `resolve-spec-conflict`, `break-down-func-spec`, `consolidate-concepts`, or an inline edit. **Never** modify generated code under `plain_modules/<module>/code/` or `plain_modules/<module>/tests/`.
124
+ 2. Fix only the `.plain` files (or the relevant `config.yaml` / template) using the appropriate edit skill — `add-concept`, `add-functional-spec`, `add-functional-specs`, `add-implementation-requirement`, `add-test-scenarios`, `resolve-section-ownership`, `resolve-spec-conflict`, `break-down-func-spec`, `consolidate-concepts`, or an inline edit. **Never** modify generated code under `plain_modules/<module>/code/` or `plain_modules/<module>/tests/`.
109
125
  3. If you are uncertain about ***plain syntax for the failing construct, re-load `load-plain-reference` before fixing.
110
126
  4. Re-run the failed checks — for a `plain-parser` failure, re-run `plain-parser check`. Repeat until they pass.
111
127
 
@@ -115,7 +131,7 @@ If the failure is something the healthcheck cannot reasonably fix on its own (e.
115
131
 
116
132
  Emit one of:
117
133
 
118
- - **`PASS`** — followed by a short summary of what was checked: `N config.yaml(s) validated`, `M module(s) checked (plain-parser OK for every top module)`, `K scripts referenced`. The caller (`forge-plain`, `add-feature`, `debug-specs`) can then continue to its hand-off step.
134
+ - **`PASS`** — followed by a short summary of what was checked: `N config.yaml(s) validated`, `M module(s) checked (plain-parser OK for every top module)`, `T test plain file(s) bound`, `K scripts referenced`. The caller (`forge-plain`, `add-feature`, `debug-specs`) can then continue to its hand-off step.
119
135
  - **`FAIL`** — followed by a numbered list of every unresolved problem. Each entry must include: the file (config / `.plain` / script) it applies to, the concrete issue, and what the user needs to decide if the healthcheck couldn't resolve it.
120
136
 
121
137
  The verdict goes on the first line so callers can pattern-match without parsing the whole report.
@@ -136,6 +152,8 @@ The verdict goes on the first line so callers can pattern-match without parsing
136
152
  - [ ] No `config.yaml` mixes stacks (e.g. Python + JS scripts in the same file)
137
153
  - [ ] No `config.yaml` declares `prepare-environment-script` without also declaring `conformance-tests-script`
138
154
  - [ ] Every `test_scripts/*` file is referenced by some `config.yaml` (or surfaced as a warning)
155
+ - [ ] The parser probe passed, or the report says 3a is suspended and names the plain-parser release that is needed
139
156
  - [ ] `plain-parser check` printed `OK` for every top module, run from that module's directory
140
- - [ ] Every module passes every check in Step 3b (section ownership, bullets, linked resources)
157
+ - [ ] Every module passes every check in Step 3b (section ownership, bullets and headings, linked resources, test plain files)
158
+ - [ ] Every test plain file binds to an existing functionality, and every functionality has at least one conformance scenario when conformance tests are enabled
141
159
  - [ ] Verdict (`PASS` / `FAIL`) is on the first line, with a numbered list of remaining problems if it failed
@@ -9,7 +9,7 @@ description: >-
9
9
 
10
10
  # Refactor Module
11
11
 
12
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
12
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
13
13
 
14
14
  ## When to Use
15
15
 
@@ -29,7 +29,7 @@ The `.plain` file to refactor, plus guidance from the user on the desired groupi
29
29
  ## Phase 1 — Analyze the Current Module
30
30
 
31
31
  1. **Read the entire `.plain` file** — frontmatter, definitions, implementation reqs, test reqs, and all functional specs. Also read any `import` and `requires` chains to understand the full context.
32
- 2. **Inventory the functional specs.** Number each spec and note which `:Concepts:` it references. Build a dependency map: which specs depend on earlier specs (by referencing behavior or state they introduced)?
32
+ 2. **Inventory the functional specs.** List each functionality by its func-id and note which `:Concepts:` it references. Build a dependency map: which specs depend on earlier specs (by referencing behavior or state they introduced)?
33
33
  3. **Inventory the definitions.** For each concept, note which functional specs reference it. Identify concepts that are used across multiple logical groups vs. concepts used only within one group.
34
34
  4. **Identify logical groups.** Look for natural seams — clusters of functional specs that share concepts, represent a cohesive domain, or describe a single feature area. Common groupings:
35
35
  - Data model setup and CRUD operations
@@ -50,7 +50,7 @@ The modules form a `requires` chain that preserves the original chronological or
50
50
  ```
51
51
  original-module
52
52
  ↓ splits into
53
- module-group-a (no requires — this is the new base)
53
+ module-group-a (no requires — this is the chain root)
54
54
  module-group-b (requires: module-group-a)
55
55
  module-group-c (requires: module-group-b)
56
56
  ```
@@ -86,7 +86,7 @@ If many concepts are shared across all modules, consider creating a new import m
86
86
 
87
87
  Summarize for the user:
88
88
  - Number of resulting modules and their names
89
- - Which functional specs go in each module (listed by number or short description)
89
+ - Which functional specs go in each module (listed by func-id)
90
90
  - The `requires` chain order
91
91
  - Any new import module being created
92
92
  - Which concepts are exported from each module
@@ -96,20 +96,20 @@ Get explicit user confirmation before proceeding.
96
96
 
97
97
  ## Phase 3 — Execute the Split
98
98
 
99
- Create the new modules in order, from the base of the chain upward.
99
+ Create the new modules in order, from the root of the chain upward.
100
100
 
101
101
  ### 3a. Create or update the import template (if needed)
102
102
 
103
103
  If shared definitions or reqs are being moved to a new import template, create it first using the `create-import-module` skill.
104
104
 
105
- ### 3b. Create the base module
105
+ ### 3b. Create the chain root
106
106
 
107
107
  Create the first module in the chain:
108
108
  1. Set the YAML frontmatter — inherit the original module's `import` references. Add `exported_concepts` for any concepts that downstream modules need.
109
109
  2. Add the `***definitions***` section with concepts used by this module's specs and concepts that need to be exported.
110
110
  3. Add `***implementation reqs***` and `***test reqs***` specific to this module (if not fully covered by the import template).
111
111
  4. Add the `***functional specs***` assigned to this module, preserving their original order and exact wording.
112
- 5. Carry over any `***acceptance tests***` nested under the moved functional specs.
112
+ 5. Set the `module:` key of the moved functionalities' test plain files to the new module name and move the files to the new module's conventional location; func-ids and scenario text stay unchanged.
113
113
 
114
114
  ### 3c. Create subsequent modules
115
115
 
@@ -119,7 +119,7 @@ For each subsequent module in the chain:
119
119
  3. Add `***definitions***` for concepts local to this module. Do **not** redefine concepts already available via `requires` (exported) or `import`.
120
120
  4. Add `***implementation reqs***` and `***test reqs***` specific to this module.
121
121
  5. Add the `***functional specs***` assigned to this module, preserving their original order and exact wording.
122
- 6. Carry over any `***acceptance tests***`.
122
+ 6. Move the test plain files of the moved functionalities the same way.
123
123
 
124
124
  ### 3d. Handle the original module file
125
125
 
@@ -135,12 +135,12 @@ This is the most critical verification. Walk through every functional spec from
135
135
 
136
136
  Checklist:
137
137
  - [ ] Total spec count across all new modules equals the original spec count
138
- - [ ] Each spec's text is identical to the original (no rewording)
139
- - [ ] Each spec's acceptance tests (if any) are carried over intact
138
+ - [ ] Each spec's text is identical to the original (no rewording) and keeps its func-id
139
+ - [ ] Each functionality's test plain file moved with it, with `module:` updated and scenarios intact
140
140
 
141
141
  ### 4b. Chronological ordering check
142
142
 
143
- Verify that the chronological order of all functional specs — when read across the requires chain from base to leaf — matches the original ordering exactly. A spec must not appear before a spec it depends on.
143
+ Verify that the chronological order of all functional specs — when read across the requires chain from root to leaf — matches the original ordering exactly. A spec must not appear before a spec it depends on.
144
144
 
145
145
  ### 4c. Concept availability check
146
146
 
@@ -169,7 +169,7 @@ Read each new `.plain` file in full and present the final structure to the user
169
169
  Creating many tiny modules with 1–2 specs each adds overhead without clarity. Aim for modules with 3–10 functional specs each, grouped around a cohesive theme.
170
170
 
171
171
  ### Breaking chronological order
172
- Specs that set up foundational behavior (entry point, database init, core CRUD) must stay in the base module even if they touch concepts from multiple domains. Only split when specs are cleanly separable.
172
+ Specs that set up foundational behavior (entry point, database init, core CRUD) must stay in the chain root even if they touch concepts from multiple domains. Only split when specs are cleanly separable.
173
173
 
174
174
  ### Forgetting exported_concepts
175
175
  If a concept defined in module A is referenced by a spec in module B (which requires A), the concept must be in A's `exported_concepts`. Missing exports cause rendering failures.
@@ -177,21 +177,21 @@ If a concept defined in module A is referenced by a spec in module B (which requ
177
177
  ### Modifying spec text during the split
178
178
  This is a refactoring, not a rewrite. Spec text must be copied verbatim. If a spec needs rewording to work in its new module context, that is a sign the split boundary is wrong — adjust the grouping instead.
179
179
 
180
- ### Losing acceptance tests
181
- Acceptance tests are nested under their parent functional spec. When moving a spec to a new module, its acceptance tests must move with it.
180
+ ### Losing test plain files
181
+ A test plain file binds to its functionality by `module:` and `func_id:`. When a functionality moves to a new module, its `module:` key changes and the file moves to the new module's conventional location; otherwise the renderer reports a pair that matches no functionality.
182
182
 
183
183
  ## Validation Checklist
184
184
 
185
185
  - [ ] User confirmed the split plan before execution
186
186
  - [ ] All original functional specs are present in exactly one new module — none lost
187
187
  - [ ] Spec text is identical to the original — no rewording
188
- - [ ] Acceptance tests moved with their parent specs
188
+ - [ ] Test plain files moved with their functionalities and rebound to the new module
189
189
  - [ ] Chronological order preserved across the requires chain
190
190
  - [ ] Every referenced `:Concept:` is available in each module (local, import, or exported)
191
191
  - [ ] `exported_concepts` are correctly set on each module
192
192
  - [ ] No concept name collisions
193
193
  - [ ] Each module has at least one functional spec and one implementation req
194
- - [ ] `requires` chain is correctly ordered (base → leaf)
194
+ - [ ] `requires` chain is correctly ordered (root → leaf)
195
195
  - [ ] Original module removed or updated
196
196
  - [ ] Downstream modules (if any) updated to require the chain tip, plus any earlier chain modules whose exported concepts they reference
197
197
  - [ ] User approved the final result
@@ -6,7 +6,7 @@ description: >-
6
6
 
7
7
  # Resolve Section Ownership
8
8
 
9
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
9
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
10
10
 
11
11
  This is the ownership counterpart to `break-down-func-spec`. That skill splits one functional spec into several because it is **too large**; this one moves facts between sections because they are in the **wrong place**. The two are unrelated: a correctly placed spec can be too large, and a one-line bullet can be misplaced.
12
12
 
@@ -36,7 +36,7 @@ The bullet, section, or `.plain` file to resolve.
36
36
  4. **Route each fact** by the *Section ownership* table in `module-structure.md`. Where a fact resists the table, apply the question it encodes: **would a caller of the finished software observe this?** Yes → `***functional specs***`. No, it is how the result is reached → `***implementation reqs***`. It says what a term means → `***definitions***`. It shapes `:ConformanceTests:` → `***test reqs***`.
37
37
  5. **Split a fact that carries both a mechanism and its consequence.** The consequence is observable and becomes the functional spec; the mechanism becomes the implementation req. *"Sends the same idempotency key on every retry, so a retried write creates at most one record"* is two facts, not one.
38
38
  6. **Give each moved fact a subject that exists in the built system.** A fact leaving a functional spec often loses its subject: name the component that owns the behavior, and add it to `***definitions***` if it is not defined yet. `:Implementation:` is the whole codebase — use it only for a fact that holds everywhere.
39
- 7. **Author each fact into its owning section** with the right edit skill — `add-concept`, `add-implementation-requirement`, `add-test-requirement`, `add-acceptance-test`. **Never hand-author `***functional specs***`**: a fact moving *into* that section goes through `add-functional-spec`, which runs the complexity and conflict analyzers for you.
39
+ 7. **Author each fact into its owning section** with the right edit skill — `add-concept`, `add-implementation-requirement`, `add-test-requirement`, `add-test-scenarios`. **Never hand-author `***functional specs***`**: a fact moving *into* that section goes through `add-functional-spec`, which runs the complexity and conflict analyzers for you.
40
40
  8. **Remove each fact from where it no longer belongs.** If a bullet is left stating nothing observable, delete the bullet; do not leave a stub. Deleting the last bullet of a section deletes the section.
41
41
  9. **Verify nothing was lost and nothing was duplicated.** Walk every fact from the original text and confirm it appears in exactly one section. A fact that now reads as obvious in its new home is still a cut decision — make it deliberately, per `concise-specs.md`.
42
42
  10. **Run `plain-healthcheck`.** Moving facts changes the renderable surface; do not finish on a `FAIL`.
@@ -48,7 +48,7 @@ The bullet, section, or `.plain` file to resolve.
48
48
  - **`add-functional-spec` reports a conflict** → resolve it with `resolve-spec-conflict` **before** removing the fact from its old section, so no version of it is lost in between.
49
49
  - **A fact appears to belong to two sections** → it is two facts; split it per step 5. If it still resists, it is a mechanism whose consequence has not been written down — write the consequence, and the split follows.
50
50
  - **The owning section does not exist in the file** → create it in canonical order. An import module carries no `***functional specs***` at all (see `import-modules.md`), so an observable fact found there belongs on the root module that imports it.
51
- - **The move empties a functional spec** → delete the spec rather than leaving a placeholder, and check whether any acceptance test nested under it must move or go with it.
51
+ - **The move empties a functional spec** → delete the spec rather than leaving a placeholder, and move or delete its test plain file with `add-test-scenarios`.
52
52
 
53
53
  ## Worked examples
54
54
 
@@ -9,7 +9,7 @@ description: >-
9
9
 
10
10
  # Resolve Spec Conflict
11
11
 
12
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
12
+ **Load the rules first.** Before you read, edit, or write any `.plain` file, invoke the `load-plain-reference` skill and read the rule files it routes you to. Skip this only if `load-plain-reference` already ran in this conversation.
13
13
 
14
14
  ## When This Applies
15
15
 
@@ -31,7 +31,7 @@ There are three possible outcomes — determine which one applies **before** mak
31
31
  | Outcome | Symptom | Fix |
32
32
  |---------|---------|-----|
33
33
  | **Implementation is incorrect** | Generated code doesn't match the spec's intent. The specs themselves are fine. | Clarify the ambiguous spec so the renderer interprets it correctly. Re-render. |
34
- | **Conformance tests are incorrect** | The tests don't accurately verify the spec. The implementation is actually correct. | Adjust `***test reqs***` or `***acceptance tests***` to guide better test generation. Re-render. |
34
+ | **Conformance tests are incorrect** | The tests don't accurately verify the spec. The implementation is actually correct. | Adjust `***test reqs***`, or the scenarios in the test plain file via `add-test-scenarios`, to guide better test generation. Re-render. |
35
35
  | **Requirements truly conflict** | The two specs are inherently contradictory — no implementation can satisfy both. | One or both specs must be revised. See Step 3. |
36
36
 
37
37
  **How to diagnose:**
@@ -49,25 +49,29 @@ Before (ambiguous):
49
49
  ```plain
50
50
  ***functional specs***
51
51
 
52
- - All :Resource: items are returned.
52
+ # list-resources
53
+ All :Resource: items are returned.
53
54
 
54
- - Only active :Resource: items are returned.
55
+ # list-active-resources
56
+ Only active :Resource: items are returned.
55
57
  ```
56
58
 
57
59
  After (disambiguated):
58
60
  ```plain
59
61
  ***functional specs***
60
62
 
61
- - All :Resource: items are returned when no filter is specified.
63
+ # list-resources
64
+ All :Resource: items are returned when no filter is specified.
62
65
 
63
- - When the "active" filter is specified, only active :Resource: items are returned.
66
+ # list-active-resources
67
+ When the "active" filter is specified, only active :Resource: items are returned.
64
68
  ```
65
69
 
66
70
  **Strategy B: Revise the newer spec.** If the new spec introduced the conflict, rewrite it to be compatible with the established behavior from earlier specs.
67
71
 
68
72
  **Strategy C: Revise the older spec.** If the older spec was under-specified and the new requirement reveals a better design, update the older spec. This is more disruptive — all conformance tests for that spec and everything after it may need re-rendering.
69
73
 
70
- **Strategy D: Merge into one spec.** If the two specs describe overlapping behavior, combine them into a single, clear spec. Remove the redundant one. Be mindful of the 200 LOC limit.
74
+ **Strategy D: Merge into one spec.** If the two specs describe overlapping behavior, combine them into a single, clear spec. Remove the redundant one and its test plain file, moving any still valid scenario into the kept functionality's file. Be mindful of the 200 LOC limit.
71
75
 
72
76
  ### Step 4: Validate the Resolution
73
77
 
@@ -75,7 +79,8 @@ After editing:
75
79
  1. Re-read the full `***functional specs***` section to confirm no new conflicts were introduced.
76
80
  2. Check that any revised spec still respects the 200 LOC limit.
77
81
  3. Check that chronological ordering still makes sense (earlier specs should not depend on later ones).
78
- 4. If resolving via test adjustments, verify the `***test reqs***` or `***acceptance tests***` changes are appropriate.
82
+ 4. If resolving via test adjustments, verify the `***test reqs***` or test plain file changes are appropriate.
83
+ 5. For every revised functionality, invoke `add-test-scenarios` to bring its test plain file in step with the new text.
79
84
 
80
85
  ## Prevention (for use during add-functional-spec / add-functional-specs)
81
86
 
@@ -95,3 +100,4 @@ Before adding a new spec, run through this quick conflict check:
95
100
  - [ ] No new conflicts introduced by the fix
96
101
  - [ ] Chronological ordering preserved
97
102
  - [ ] All referenced `:Concepts:` are still defined
103
+ - [ ] Test plain files of the revised functionalities brought in step via `add-test-scenarios`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plain-forge",
3
- "version": "1.0.23",
3
+ "version": "1.0.24-next.019bba8",
4
4
  "description": "Conversational spec-writing tool for ***plain specification language",
5
5
  "type": "module",
6
6
  "engines": {