plain-forge 1.0.18 → 1.0.20

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 (50) hide show
  1. package/README.md +17 -10
  2. package/bin/cli.mjs +53 -24
  3. package/forge/rules/bullet-continuation.md +59 -0
  4. package/forge/rules/definitions.md +15 -0
  5. package/forge/rules/func-specs.md +52 -7
  6. package/forge/rules/impl-reqs.md +1 -1
  7. package/forge/rules/integration-embedded-testing.md +7 -4
  8. package/forge/rules/integration-embedded.md +4 -1
  9. package/forge/rules/linked-resources.md +7 -6
  10. package/forge/rules/requires-modules.md +1 -1
  11. package/forge/rules/test-reqs.md +1 -1
  12. package/forge/skills/add-acceptance-test/SKILL.md +3 -25
  13. package/forge/skills/add-concept/SKILL.md +3 -22
  14. package/forge/skills/add-feature/SKILL.md +71 -67
  15. package/forge/skills/add-feature/references/checklist.md +38 -0
  16. package/forge/skills/add-feature/references/phase-0-intent.md +29 -0
  17. package/forge/skills/add-functional-spec/SKILL.md +3 -23
  18. package/forge/skills/add-functional-specs/SKILL.md +3 -24
  19. package/forge/skills/add-implementation-requirement/SKILL.md +4 -23
  20. package/forge/skills/add-resource/SKILL.md +7 -8
  21. package/forge/skills/add-test-requirement/SKILL.md +4 -21
  22. package/forge/skills/analyze-2-func-specs/SKILL.md +10 -10
  23. package/forge/skills/analyze-func-specs/SKILL.md +10 -10
  24. package/forge/skills/analyze-if-func-spec-too-complex/SKILL.md +93 -31
  25. package/forge/skills/break-down-func-spec/SKILL.md +78 -29
  26. package/forge/skills/create-import-module/SKILL.md +7 -0
  27. package/forge/skills/create-requires-module/SKILL.md +3 -2
  28. package/forge/skills/debug-specs/SKILL.md +5 -5
  29. package/forge/skills/forge-plain/SKILL.md +80 -299
  30. package/forge/skills/forge-plain/references/checklist.md +66 -0
  31. package/forge/skills/forge-plain/references/phase-0-intent.md +29 -0
  32. package/forge/skills/forge-plain/references/phase-1-product.md +40 -0
  33. package/forge/skills/forge-plain/references/phase-2-tech.md +24 -0
  34. package/forge/skills/forge-plain/references/phase-3-testing.md +66 -0
  35. package/forge/skills/forge-plain/references/phase-4-validate-handoff.md +49 -0
  36. package/forge/skills/implement-conformance-testing-script/SKILL.md +2 -2
  37. package/forge/skills/implement-prepare-environment-script/SKILL.md +2 -2
  38. package/forge/skills/implement-unit-testing-script/SKILL.md +1 -1
  39. package/forge/skills/init-config-file/SKILL.md +4 -3
  40. package/forge/skills/init-plain-project/SKILL.md +4 -0
  41. package/forge/skills/init-plain-project/references/checklist.md +31 -0
  42. package/forge/skills/load-codeplain-reference/SKILL.md +188 -0
  43. package/forge/skills/load-plain-reference/SKILL.md +48 -678
  44. package/forge/skills/load-plain-reference/references/project-model.md +48 -0
  45. package/forge/skills/load-plain-reference/references/rendering-and-testing.md +57 -0
  46. package/forge/skills/plain-healthcheck/SKILL.md +3 -3
  47. package/forge/skills/resolve-spec-conflict/SKILL.md +13 -5
  48. package/forge/skills/run-codeplain/SKILL.md +15 -15
  49. package/package.json +2 -2
  50. package/forge/rules/line-length.md +0 -45
@@ -0,0 +1,48 @@
1
+ # ***plain project model
2
+
3
+ Use this reference for project structure and language features not owned by a section-specific
4
+ authoring rule.
5
+
6
+ ## Source-of-truth model
7
+
8
+ `.plain` files are the source of truth. They describe observable behavior, implementation choices,
9
+ and testing requirements. The renderer produces generated implementation and test artifacts from
10
+ those specifications.
11
+
12
+ ## Typical repository structure
13
+
14
+ ```text
15
+ *.plain # Root specification modules
16
+ template/*.plain # Reusable import modules
17
+ resources/ # Linked text artifacts such as schemas and fixtures
18
+ plain_modules/ # Generated output, one directory per module
19
+ <module>/code/ # implementation and unit tests
20
+ <module>/tests/ # conformance tests, one folder per functional spec
21
+ test_scripts/ # Unit, environment-preparation, and conformance runners
22
+ config.yaml # codeplain CLI configuration
23
+ ```
24
+
25
+ The exact template directory can be configured. Follow the module and linked-resource rules for
26
+ what these directories may contain and how a spec refers to them.
27
+
28
+ ## Template inclusion
29
+
30
+ In addition to frontmatter `import`, ***plain supports parameterized template inclusion:
31
+
32
+ ```plain
33
+ {% include "python-console-app-template.plain", main_executable_file_name: "my_app.py" %}
34
+ ```
35
+
36
+ Parameters are key-value pairs. Templates access them with `{{ variable_name }}`. Only variable
37
+ substitution is supported; conditionals, loops, and other Liquid features are not available.
38
+
39
+ ## Comments
40
+
41
+ Lines beginning with `>` are ignored during rendering:
42
+
43
+ ```plain
44
+ > This is a comment in ***plain.
45
+ ```
46
+
47
+ Comments explain the specification to human authors. Do not use comments to carry requirements the
48
+ renderer must implement.
@@ -0,0 +1,57 @@
1
+ # Rendering and testing workflow
2
+
3
+ ## Incremental rendering
4
+
5
+ Functional specs render from top to bottom. When rendering one functional spec, the renderer knows
6
+ the previous specs but not future specs. A required module's functional specs also count as previous
7
+ specs according to the module rules.
8
+
9
+ Each functional spec receives its own conformance-test folder. After a new spec renders, the
10
+ renderer runs conformance tests for previous specs to detect regressions. A new failure can mean:
11
+
12
+ 1. The generated implementation does not satisfy the specification.
13
+ 2. The generated conformance test does not accurately test the specification.
14
+ 3. The new and previous specifications conflict.
15
+
16
+ Diagnose which case applies, then correct the `.plain` source. Use the dedicated conflict-analysis
17
+ and debugging skills rather than editing generated output.
18
+
19
+ ## Generated artifacts are read-only
20
+
21
+ Everything under `plain_modules/` is generated — both `<module>/code/` and `<module>/tests/`. It may be read, executed,
22
+ and debugged, but never edited directly. Apply fixes as follows:
23
+
24
+ - Behavior or implementation/unit-test guidance: edit definitions, functional specs, or
25
+ implementation requirements as appropriate.
26
+ - Conformance-test guidance: edit test requirements.
27
+ - Acceptance-test guidance: edit the acceptance tests nested under their owning functional spec.
28
+
29
+ Re-render after correcting the source specification.
30
+
31
+ ## Test-script roles
32
+
33
+ Test scripts are renderer entry points as well as developer utilities:
34
+
35
+ - `run_unittests_<lang>` receives the generated build folder and runs the complete generated unit
36
+ suite. It is self-contained and does not depend on environment preparation.
37
+ - `prepare_environment_<lang>` optionally prepares a reusable system-temporary environment for
38
+ conformance testing once per render.
39
+ - `run_conformance_tests_<lang>` receives the generated build folder and one functionality's
40
+ conformance-test folder (`plain_modules/<module_name>/tests/<functionality>`). It may run repeatedly during a render.
41
+
42
+ Invoke the corresponding `implement-*-script` skill when creating or changing a test script. Those
43
+ skills own exact staging, cleanup, dependency-installation, shell, and exit-code contracts.
44
+
45
+ ## Common invocation shape
46
+
47
+ Run project scripts from the repository root, using the filenames configured for that project:
48
+
49
+ ```bash
50
+ ./test_scripts/run_unittests.sh plain_modules/<module_name>/code
51
+ ./test_scripts/prepare_environment.sh plain_modules/<module_name>/code
52
+ ./test_scripts/run_conformance_tests.sh \
53
+ plain_modules/<module_name>/code plain_modules/<module_name>/tests/<functionality>
54
+ ```
55
+
56
+ The renderer resolves script arguments to absolute paths. Test scripts must treat input directories
57
+ as read-only and stage writes in their designated system-temporary working directory.
@@ -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.
16
+ Always use the skill `load-codeplain-reference` to retrieve the full `codeplain` CLI reference (every flag, path-resolution rules, `config.yaml` mapping, render banners, exit codes), and the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet. This skill runs `codeplain … --dry-run` and validates every `config.yaml`, so the CLI reference is required.
17
17
 
18
18
  ## When to run
19
19
 
@@ -54,7 +54,7 @@ For each `config.yaml` in the inventory, check **all** of the following. Collect
54
54
  - The path is a string ending in `.sh` (macOS/Linux) or `.ps1` (Windows). The extension must match the rest of the project — do not mix `.sh` and `.ps1` in a single config.
55
55
  - The referenced file actually exists on disk, resolved the way the renderer resolves it: absolute / `~` paths as-is, relative paths against the **config file's directory** (typically landing under `test_scripts/`). There is no other fallback — the renderer fails fast with a `FileNotFoundError` on a script path that doesn't resolve, so a path that only "works" from some other directory is a failure here.
56
56
  - On Unix, the script has the executable bit set (`-x`). If not, that is a fixable failure.
57
- 4. **No mixed stacks per config.** Every script referenced from a single `config.yaml` must target the same language/stack. For example, `backend/config.yaml` should not reference `run_unittests_js.sh`. If a config crosses stacks, that is a failure — the project should have been split into multiple configs per the rule in `PLAIN_REFERENCE.md`.
57
+ 4. **No mixed stacks per config.** Every script referenced from a single `config.yaml` must target the same language/stack. For example, `backend/config.yaml` should not reference `run_unittests_js.sh`. If a config crosses stacks, that is a failure — the project should have been split into multiple configs per the applicable module rules loaded by `load-plain-reference`.
58
58
  5. **No dangling fields.** Any `*-script` field whose target file does not exist is a failure.
59
59
  6. **`prepare-environment-script` implies `conformance-tests-script`.** A `prepare-environment-script` only makes sense in service of conformance tests — the environment is what those tests run against. If a `config.yaml` declares `prepare-environment-script` but does **not** declare `conformance-tests-script`, that is a failure. Surface it to the user and offer to either (a) invoke `implement-conformance-testing-script` to add the missing script, or (b) remove the `prepare-environment-script` field if it was added in error. Do not auto-pick.
60
60
  7. **No orphan scripts.** Every script under `test_scripts/` should be referenced by *some* `config.yaml`. If a script is never referenced, surface it as a **warning** (not a hard failure — the user may be in the middle of authoring).
@@ -90,7 +90,7 @@ Treat the dry-run as a hard gate: the healthcheck **only passes** when every top
90
90
  Iterate until it passes:
91
91
 
92
92
  1. Read the error output. If the first run was not verbose, immediately re-run with `--verbose`. Identify the offending `.plain` file, the line (if reported), and the kind of issue: missing concept, syntax error, cyclic definition, complexity violation (`Functional spec too complex!`), conflicting reqs, missing template, broken `import`/`requires`, missing config field, etc.
93
- 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-spec-conflict`, `break-down-func-spec`, `consolidate-concepts`, or an inline edit. **Never** modify generated code under `plain_modules/` or `conformance_tests/`.
93
+ 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-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/`.
94
94
  3. If you are uncertain about ***plain syntax for the failing construct, re-load `load-plain-reference` before fixing.
95
95
  4. Re-run the same `codeplain <top_module>.plain --dry-run …` command with the same flags. Repeat until it exits successfully.
96
96
 
@@ -45,14 +45,22 @@ When the requirements truly conflict, choose a resolution strategy:
45
45
 
46
46
  **Strategy A: Add detail to disambiguate.** Often the specs aren't contradictory — they're just ambiguous enough that the renderer picks a conflicting interpretation. Adding explicit context to one or both specs eliminates the ambiguity.
47
47
 
48
- ```
49
48
  Before (ambiguous):
50
- - The system should return all :Resource: items.
51
- - The system should return only active :Resource: items.
49
+ ```plain
50
+ ***functional specs***
51
+
52
+ - All :Resource: items are returned.
53
+
54
+ - Only active :Resource: items are returned.
55
+ ```
52
56
 
53
57
  After (disambiguated):
54
- - The system should return all :Resource: items when no filter is specified.
55
- - When the "active" filter is specified, the system should return only active :Resource: items.
58
+ ```plain
59
+ ***functional specs***
60
+
61
+ - All :Resource: items are returned when no filter is specified.
62
+
63
+ - When the "active" filter is specified, only active :Resource: items are returned.
56
64
  ```
57
65
 
58
66
  **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.
@@ -12,7 +12,7 @@ description: >-
12
12
 
13
13
  # Run Codeplain
14
14
 
15
- Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
15
+ Always use the skill `load-codeplain-reference` to retrieve the full `codeplain` CLI reference (every flag, path-resolution rules, `config.yaml` mapping, render banners, exit codes), and the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet. This skill drives the `codeplain` CLI, so the CLI reference is required before launching or resuming any render.
16
16
 
17
17
  ## What this skill is
18
18
 
@@ -21,7 +21,7 @@ A **supervisor** around a live `codeplain` render. The renderer itself is the co
21
21
  1. Launches `codeplain <module>.plain` (or attaches to an in-flight run).
22
22
  2. Watches three signal sources in a tight loop, in priority order:
23
23
  - **`codeplain.log`** — the primary signal. Everything the renderer is doing, deciding, retrying, or failing at gets written here. This is the file you stare at.
24
- - the generated **code outputs** under `plain_modules/<module>/` and `conformance_tests/<module>/` — a secondary signal, used to corroborate or contradict what the log says.
24
+ - the generated **code outputs** under `plain_modules/<module>/` and `plain_modules/<module>/tests/` — a secondary signal, used to corroborate or contradict what the log says.
25
25
  - the **process / TUI** itself (alive? exited? exit code?) — a tertiary signal, used only to know whether to keep monitoring.
26
26
  3. Surfaces what is happening to the user in plain English, in near-real-time.
27
27
  4. On pathology, stops the renderer (with user approval), hands off to the right edit skill, and resumes from the last completed functionality.
@@ -76,7 +76,7 @@ Before launching anything:
76
76
  - **What "pass" means**, exit-code-wise. Some scripts combine multiple checks (e.g. `unit_testing_typescript.sh` here runs `tsc --noEmit` *and* `vitest`, and its final exit code is the worst of the two — so a type error alone fails the unit-test gate).
77
77
  - **What "fail" means**, including any failures that the script deliberately downgrades to warnings (e.g. `prepare_environment_typescript.sh` here treats a failed `npm run build` as a non-fatal warning). Failures the script swallows are failures the renderer will **never see**, so a spec defect that depends on them will silently slip through.
78
78
  - **Where the scripts materialize their working environment** (current-convention scripts stage into the system temp directory, e.g. `/tmp/typescript_<build_folder_basename>/`; older scripts used project-local folders like `.tmp/typescript_<build_folder>/`, `build/`, `target/`). This is where the renderer's iteration actually runs; if you need to look at what is breaking, this is the directory — not `plain_modules/<module>/` directly.
79
- - **How conformance tests are discovered and staged** (glob, naming convention, alias setup, etc.). Some scripts stage tests into the source tree (this repo flattens `conformance_tests/<module>/<fname>/` into `src/<module>/`); some run them in place; some require a specific file extension. This tells you exactly which conformance test file is in play for a given functionality.
79
+ - **How conformance tests are discovered and staged** (glob, naming convention, alias setup, etc.). Some scripts stage tests into the source tree (this repo flattens `plain_modules/<module>/tests/<fname>/` into `src/<module>/`); some run them in place; some require a specific file extension. This tells you exactly which conformance test file is in play for a given functionality.
80
80
  - **Toolchain prerequisites** the script asserts (Node version, Python version, specific binaries). If any are missing on the user's machine, stop now and tell them — the renderer will burn credits on phantom failures otherwise.
81
81
 
82
82
  Keep this synthesis short (5–10 bullets, project-specific). It is the single most important reference for the classifier in [Spec-deviation classification](#spec-deviation-classification). The healthcheck only checks that the scripts *exist* and are *referenced correctly*; this step is the only place that reads what they actually *do*.
@@ -132,7 +132,7 @@ All patterns below are taken from the actual codeplain runtime. Treat them as th
132
132
  | `Implementing conformance tests...` / `Implementing test requirements:` | Conformance phase starting for the current functionality. | Routine. |
133
133
  | `Running testing environment preparation script .* for build folder` | `prepare-environment-script` is running. | Routine. |
134
134
  | `\[#79FC96\]All Testing Environment Preparation scripts have passed successfully.\[/#79FC96\]` | Env prep green. | Routine. |
135
- | `Running conformance tests script .* for conformance_tests/<m>/<fname> \(functionality <N> in module <m>\)` | Conformance tests starting for functionality `<N>`. | Note `<fname>` — that is the on-disk folder where the latest conformance test lives. |
135
+ | `Running conformance tests script .* for plain_modules/<m>/tests/<fname> \(functionality <N> in module <m>\)` | Conformance tests starting for functionality `<N>`. | Note `<fname>` — that is the on-disk folder where the latest conformance test lives. |
136
136
  | `Running conformance tests attempt <N>.` | Conformance retry loop. **Watch `<N>` carefully.** | Increment `ATTEMPT_COUNTER = <N>`. At `>=5`, trigger Pathology A. |
137
137
  | `Fixing conformance test for functionality <N> in module <m>.` | Renderer is patching its own conformance test between attempts. | On its own, routine. Combined with climbing `<N>`, smoking gun for Pathology A. |
138
138
  | `Functional spec too complex!` | Single spec implies >200 LOC. Renderer aborts. | Pathology B. |
@@ -199,7 +199,7 @@ What to extract from the framework output — stay framework-agnostic, look for
199
199
  - **Individual test names that failed**: lines beginning with `×`, `FAIL`, `✗`, `× should ...`, `FAIL src/.../foo.test.ts > <name>`. The *same* test failing across attempts is the smoking gun for an under-specified spec.
200
200
  - **Assertion bodies**: `expected X, got Y`. The values reveal exactly what the test expects vs what the implementation produced — the cleanest input to the classifier below.
201
201
  - **Compile / type errors** (when the script wraps a type-checker): `error TS<NNNN>`, `cannot find module`, `is not assignable to`. A unit-test gate that keeps re-failing on the same type error means the implementation req or the type-level spec is wrong, not the code.
202
- - **Stack traces**: which file under the prepared working folder threw, and at which line. Map the file back to `plain_modules/<module>/src/...` to find the code the spec is supposed to be governing.
202
+ - **Stack traces**: which file under the prepared working folder threw, and at which line. Map the file back to `plain_modules/<module>/code/...` to find the code the spec is supposed to be governing.
203
203
  - **"No test files found" / "No tests collected"**: the script ran but discovered nothing. Almost always a path/glob mismatch in the staged working folder, not a spec problem. Treat as Pathology F.
204
204
 
205
205
  Always set the logs to be verbose in `config.yaml`.
@@ -232,8 +232,8 @@ The inputs to the classifier are:
232
232
  1. The **spec** that governs the failing functionality — the functional spec and its acceptance test(s) in the `.plain` file.
233
233
  2. The **test-script output** for the most recent attempt, from `codeplain.log` per the section above.
234
234
  3. The renderer's own **`.memory/conformance_test_memory/<id>.json`** for this functionality (when present).
235
- 4. The newest **conformance test file** the renderer just edited under `conformance_tests/<module>/<fname>/`.
236
- 5. The newest **implementation file(s)** the renderer just edited under `plain_modules/<module>/`.
235
+ 4. The newest **conformance test file** the renderer just edited under `plain_modules/<module>/tests/<fname>/`.
236
+ 5. The newest **implementation file(s)** the renderer just edited under `plain_modules/<module>/code/`.
237
237
 
238
238
  With these in hand, place the current iteration into one of four buckets:
239
239
 
@@ -320,15 +320,15 @@ If the process is gone but you haven't yet seen a `✓` or `✗` banner in the l
320
320
 
321
321
  This is a secondary signal — it confirms what the log already said. Don't go on a fishing trip here.
322
322
 
323
- For the current module, the renderer drops generated code into `plain_modules/<module>/` and conformance tests into `conformance_tests/<module>/<functionality_name>/`. Each pass, inspect what is new:
323
+ For the current module, the renderer drops generated code into `plain_modules/<module>/` and conformance tests into `plain_modules/<module>/tests/<functionality_name>/`. Each pass, inspect what is new:
324
324
 
325
- - New files under `plain_modules/<module>/src/` confirm the functionality is being implemented.
326
- - New folders under `conformance_tests/<module>/` confirm the functionality has reached the conformance phase.
325
+ - New files under `plain_modules/<module>/code/` confirm the functionality is being implemented.
326
+ - New folders under `plain_modules/<module>/tests/` confirm the functionality has reached the conformance phase.
327
327
  - Files that were rewritten between passes are the renderer's "fix" attempts — diffing them across iterations is what reveals whether the renderer is converging or thrashing.
328
328
 
329
329
  Read **only the newest** file(s) (the ones that changed since last pass), and read them to understand *what the renderer chose to do*, not just *that* it did something. This is the first line of defense against "the spec is ambiguous and the renderer guessed wrong" — you can often spot the wrong guess in the generated code long before tests fail.
330
330
 
331
- Generated code under `plain_modules/` and `conformance_tests/` is **read-only**. Never edit it. Edits go in the `.plain` files.
331
+ Generated code under `plain_modules/<module>/code/` and `plain_modules/<module>/tests/` is **read-only**. Never edit it. Edits go in the `.plain` files.
332
332
 
333
333
  ### 1d. Cadence
334
334
 
@@ -384,7 +384,7 @@ Symptom: log shows the unit-test or conformance-test **script** itself failing (
384
384
 
385
385
  ```
386
386
  ImportError: Start directory is not importable
387
- /Users/x/project//Users/x/project/conformance_tests/module/spec
387
+ /Users/x/project//Users/x/project/plain_modules/module/tests/spec
388
388
  ```
389
389
 
390
390
  The render then gets stuck "fixing" tests that can never pass. The fix is never a spec edit: stop the render and regenerate the affected scripts via the matching `implement-*-testing-script` skill (current convention: system-temp working folder from `basename "$1"`, `$2` resolved to absolute before any `cd`).
@@ -434,7 +434,7 @@ If the fix required regenerating a module's earlier output (e.g. a definition ch
434
434
  When the renderer exits successfully:
435
435
 
436
436
  1. Read the success banner from the log: render id, generated code folder, functionalities count, used credits, render time. Report it to the user verbatim — these are the numbers they actually care about.
437
- 2. List the top-level files/folders that appeared (or changed) under `plain_modules/<module>/` and `conformance_tests/<module>/` so the user knows where to look.
437
+ 2. List the top-level files/folders that appeared (or changed) under `plain_modules/<module>/` and `plain_modules/<module>/tests/` so the user knows where to look.
438
438
  3. Remind the user of the **side-channel commands** they may want to run themselves, based on the config:
439
439
  - `./test_scripts/<unittests-script>` for unit tests,
440
440
  - `./test_scripts/<prepare-environment-script>` to set up the test env,
@@ -446,7 +446,7 @@ When the renderer exits with a failure that wasn't intercepted by Phase 2 (e.g.
446
446
 
447
447
  ## Anti-patterns
448
448
 
449
- - **Editing generated code to "fix" a render.** Never. Generated files under `plain_modules/` and `conformance_tests/` exist as evidence only; they are overwritten every render. All fixes go in `.plain` files.
449
+ - **Editing generated code to "fix" a render.** Never. Generated files under `plain_modules/<module>/code/` and `plain_modules/<module>/tests/` exist as evidence only; they are overwritten every render. All fixes go in `.plain` files.
450
450
  - **Reading the test scripts' source code to understand what's failing.** Don't. The scripts run real frameworks (vitest, pytest, etc.) and the *output* of those frameworks — captured in `codeplain.log` and in `.memory/conformance_test_memory/*.json` — is what tells you what is failing and why. Reading the script source tells you nothing the log doesn't already say.
451
451
  - **Treating every conformance loop as under-specification.** Run the classifier. The renderer sometimes drifts (Bucket 3) by silently weakening its own tests; that is the opposite problem and the fix is different.
452
452
  - **Re-reading the whole log on every pass.** It grows. Track the byte offset and read only what was appended since the last pass. Full reads are reserved for "I just saw an error and need backstory."
@@ -480,4 +480,4 @@ When the renderer exits with a failure that wasn't intercepted by Phase 2 (e.g.
480
480
  - [ ] Spec fixes were delegated to the right edit skill, not done inside this skill
481
481
  - [ ] Resumes use `--render-from <N+1>` (or `--render-range`) — `--force-render` only with user approval
482
482
  - [ ] On success, final render id / credits / time were reported and side-channel test commands were surfaced
483
- - [ ] No generated code under `plain_modules/` or `conformance_tests/` was modified
483
+ - [ ] No generated code under `plain_modules/<module>/code/` or `plain_modules/<module>/tests/` was modified
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plain-forge",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "description": "Conversational spec-writing tool for ***plain specification language",
5
5
  "type": "module",
6
6
  "engines": {
@@ -33,7 +33,7 @@
33
33
  "scripts": {
34
34
  "build": "tsx bin/forge-build.ts",
35
35
  "clean": "tsx bin/forge-build.ts --clean",
36
- "test": "node --test \"test/**/*.test.mjs\""
36
+ "test": "node --test test/*.test.mjs"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^22.10.0",
@@ -1,45 +0,0 @@
1
- ---
2
- description: Line-length and bullet-continuation rules for every section in .plain files
3
- ---
4
-
5
- # Rules for line length in `.plain` files
6
-
7
- These rules apply to **every** section — `***definitions***`, `***implementation reqs***`, `***test reqs***`, `***functional specs***`, `***acceptance tests***` — and to concept explanations alike.
8
-
9
- ## Hard limit: 120 characters per line
10
- - If a line exceeds 120 characters, split it at a natural clause boundary into nested `- ` bullets
11
- - Concision is in service of clarity, never the other way around — wordy-but-precise always beats terse-but-ambiguous
12
- - Prefer short, direct sentences and plain words; if a 10-cent word and a 50-cent word say the same thing, use the 10-cent one
13
-
14
- ## Never use bare continuation lines (invalid ***plain syntax)
15
- - ***plain syntax requires every line inside a section to be its own list item starting with `- `
16
- - Indented continuation lines without a leading `- ` are syntactically invalid — they look reasonable to a human reader but the renderer cannot parse them
17
- - When a sentence is too long, **break it into multiple bullet items**, each on its own line, nested under the parent bullet so the meaning stays grouped
18
-
19
- ## Examples
20
-
21
- BAD — line is too long:
22
-
23
- ```plain
24
- - :GatewayWebhook: should hand off :StripeRequest: to :StripeIntegration:.handle(), which returns a list of :EventEnvelope: dicts conforming to the gateway's contract.
25
- ```
26
-
27
- WRONG SYNTAX (AVOID AT ALL COSTS) — bare indented continuation without a leading `- `:
28
-
29
- ```plain
30
- - :GatewayWebhook: should hand off :StripeRequest: to :StripeIntegration:.handle(),
31
- which returns a list of :EventEnvelope: dicts conforming to the gateway's
32
- contract.
33
- ```
34
-
35
- GOOD — split at a natural clause boundary into nested `- ` bullets:
36
-
37
- ```plain
38
- - :GatewayWebhook: should hand off :StripeRequest: to :StripeIntegration:.handle()
39
- - The method returns a list of :EventEnvelope: dicts.
40
- - The dicts must conform to the gateway's :EventEnvelope: contract.
41
- ```
42
-
43
- ## What never goes inline
44
- - Long URLs, schema fragments, or example payloads — those belong in `resources/` per [`linked-resources.md`](linked-resources.md)
45
- - If you find yourself pasting a multi-line block into a spec line, stop and link the file instead