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,40 @@
1
+ # Phase 1 — What are we building?
2
+
3
+ Translate the confirmed Phase 0 intent brief into the product model and observable behavior. Refine
4
+ the brief rather than repeating its discovery questions. Run the core loop (ask → author → review)
5
+ for each topic below, in order.
6
+
7
+ ## Author targets for this phase
8
+
9
+ The moment the user answers, write the resulting snippet to disk using the right skill:
10
+
11
+ - **Module structure** — create or update the `.plain` file(s) (single module, template + modules, or chained modules). Set up YAML frontmatter (`import`, `requires`, `description`) and the proposed module name. If a template is used, create it in `template/` **without** a `***functional specs***` section. Use the `create-import-module` skill where applicable.
12
+ - **`***definitions***`** — add or refine concepts (entities, attributes, relationships). Define every concept before it is referenced. Use the `add-concept` skill.
13
+ - **`***functional specs***`** — translate each answer into a single chronological, incremental spec (≤200 lines of code change, language-agnostic, no conflicts). Use `add-functional-spec` for one new spec; use `add-functional-specs` only when a single answer naturally decomposes into a tight cluster of specs flowing from the same answer (e.g. list / create / delete CRUD on one entity). **Never hand-author the `***functional specs***` section directly.**
14
+
15
+ Do **not** add `***implementation reqs***`, `***test reqs***`, or `***acceptance tests***` in this phase — they belong to later phases.
16
+
17
+ ## Topics (in order)
18
+
19
+ 1. **Product description** — propose a one-sentence description and module name from the confirmed
20
+ intent brief. Ask the user to approve or correct it, then author the stub `.plain` frontmatter.
21
+ 2. **Users and product shape** — refine the primary user and identify whether this is a CLI, web app,
22
+ API, desktop app, mobile app, library, or another shape. Author resulting concepts.
23
+ 3. **Scope** — translate the confirmed smallest-useful boundary and exclusions into a cohesive MVP,
24
+ prototype, or product module structure. Ask only about unresolved boundaries.
25
+ 4. **Core entities** — the main "things" in the system (Users, Tasks, Orders, Messages, …), their attributes, and relationships. Author one concept per entity in `***definitions***`. Review each concept snippet.
26
+ 5. **Key features** — every distinct thing the app should do. For each feature capture the trigger, the expected outcome, and edge cases / validation rules. Author one or more functional specs per feature, in chronological build order, each ≤200 LOC. Break large features into smaller specs together with the user. Review each new functional spec (or tight group of related specs).
27
+ 6. **User flows** — walk through the app from the user's perspective: what happens first, what happens next, and at each decision point. Author the ordering and any missing intermediate functional specs. Review the affected sequence of specs.
28
+ 7. **Constraints and rules** — business rules, validation, permissions, error-handling behavior. Fold these into the relevant functional specs, and add concepts where they are first-class entities (e.g. roles). Review the updated specs.
29
+ 8. **User interface (optional)** — skip entirely if the project has no UI. Otherwise ask, one question per iteration:
30
+ - How does the UI look and feel?
31
+ - Where are the key UI elements located?
32
+ - What do the key UI elements do?
33
+ - What is the layout and design of the UI?
34
+
35
+ Author UI-behavior functional specs (still language- and framework-agnostic). Review those specs.
36
+ 9. **Anything else** — anything the user wants to add or change that hasn't already been covered.
37
+
38
+ Keep asking follow-ups within a topic until every feature is specific enough to become a single functional spec (implying ≤200 lines of code change each). If a feature is too large, break it down together with the user before authoring.
39
+
40
+ When all topics are complete, summarize the full feature list and the final module/concept layout, and get an explicit overall confirmation before moving to Phase 2.
@@ -0,0 +1,24 @@
1
+ # Phase 2 — What technologies should it use?
2
+
3
+ Gather the technical stack **and** the project's structure/architecture. This phase affects only `***implementation reqs***` — testing concerns come later. Run the core loop (ask → author → review) from `SKILL.md` for each topic below, in order. When the user has no preference, propose a sensible default that fits earlier answers and ask them to confirm.
4
+
5
+ ## Author target for this phase
6
+
7
+ Write each requirement into `***implementation reqs***`:
8
+
9
+ - Shared, stack-wide reqs (language, framework, architecture, coding standards) go on the template module if one exists.
10
+ - Module-specific reqs (e.g. a data-storage choice or an external integration only one module uses) go on the module that needs them.
11
+
12
+ Do **not** add `***test reqs***` or `***acceptance tests***` in this phase — they belong to later phases.
13
+
14
+ ## Topics (in order)
15
+
16
+ 1. **Programming language** — e.g. Python, TypeScript, Java, Go. Author a language requirement at the appropriate scope (template if shared across modules, otherwise on the module). Review that requirement snippet.
17
+ 2. **Frameworks** — e.g. Flask, FastAPI, Next.js, Spring Boot, Express, React, Vue. Author framework requirement(s) and any framework-specific architectural conventions. Review the new framework reqs.
18
+ 3. **Data storage** — e.g. PostgreSQL, SQLite, file-based, in-memory, none. Author a storage requirement on the module that owns persistence (or the template if shared). Review that snippet.
19
+ 4. **External services or APIs** — anything the app talks to: auth providers, payment gateways, email/SMS, third-party APIs, internal services. Author one requirement per integration on the module that uses it. Review each integration snippet.
20
+ 5. **Project structure & architecture** — the architectural style and the layers/components the project should be organized into (managers, services, models, repositories, controllers, views, adapters, DTOs, …). Discuss naming conventions, directory layout, and the responsibilities/boundaries of each layer. If the user has no preference, propose a layout that fits the language, framework, and feature set, and confirm it. Author architecture/layering reqs in the template (if shared) and any module-specific deviations on the module. Review the architecture reqs and the resulting layer split.
21
+ 6. **Other constraints** — deployment target, OS requirements, performance needs, coding standards, security policies, observability — anything stack-wide that hasn't already been covered. Author each constraint as its own requirement at the appropriate scope. Review the new constraint snippets.
22
+ 7. **Anything else** — anything the user wants to add or change that hasn't already been covered.
23
+
24
+ When all topics are complete, summarize the full tech stack and the chosen architecture, and get an explicit overall confirmation before moving to Phase 3.
@@ -0,0 +1,66 @@
1
+ # Phase 3 — How should testing be done?
2
+
3
+ Gather the testing strategy. This phase covers `***test reqs***`, `***acceptance tests***`, the scripts under `test_scripts/`, and the `config.yaml` file(s) that wire them in. Run the core loop (ask → author → review) from `SKILL.md` for each topic below, in order. When the user has no preference, propose a default that fits the language and stack chosen in Phase 2 and ask them to confirm.
4
+
5
+ ## Hard partition (applies to every topic)
6
+
7
+ - **Everything about `:UnitTests:`** — framework, layout, packages, conventions, execution command, coverage, mocking policy (every fact) — is authored into `***implementation reqs***` via `add-implementation-requirement`. The unit-test generator reads only that section.
8
+ - **Everything about `:ConformanceTests:`** — framework, layout, packages, execution command, mocking policy, environment prereqs (every fact) — is authored into `***test reqs***` via `add-test-requirement`. The conformance-test generator reads only that section.
9
+ - A topic that mixes both kinds of facts is split: unit facts go to impl reqs, conformance facts go to test reqs. They never share a bullet.
10
+
11
+ ## Plan the `config.yaml` split (before topic 1)
12
+
13
+ Decide how many `config.yaml` files this project needs. The rule is **one `config.yaml` per part of the system that has its own testing scripts**:
14
+
15
+ - A single-stack project (e.g. one Python service) gets one `config.yaml` at the project root.
16
+ - A multi-part project gets one `config.yaml` **per part**. A Python/FastAPI backend and a React frontend end up with two: `backend/config.yaml` referencing the Python scripts and `frontend/config.yaml` referencing the JS scripts. Each config references only its own scripts; never mix them.
17
+ - The split follows the module boundaries from Phases 1–2: a module with its own language, framework, and test scripts gets its own `config.yaml` next to it.
18
+
19
+ State the planned split to the user (e.g. "I'll create `backend/config.yaml` and `frontend/config.yaml`") and confirm. The files need not exist yet — each is created the first time a script is generated for its part, and entries accumulate as the topics below are walked. Valid script keys:
20
+
21
+ ```yaml
22
+ unittests-script: test_scripts/run_unittests_<language>.<sh|ps1>
23
+ conformance-tests-script: test_scripts/run_conformance_tests_<language>.<sh|ps1>
24
+ prepare-environment-script: test_scripts/prepare_environment_<language>.<sh|ps1>
25
+ ```
26
+
27
+ Use `.sh` on macOS/Linux and `.ps1` on Windows, matching the generated testing scripts. Preserve any existing fields in a `config.yaml` being updated. Add a `template_dir` field when any import modules or templates have been added, e.g.:
28
+
29
+ ```yaml
30
+ template_dir: template
31
+ ```
32
+
33
+ ## Topics (in order)
34
+
35
+ 1. **Unit-test framework** — e.g. pytest, Jest, JUnit, Go's `testing` package. Suggest one that fits the Phase 2 language if the user has no preference.
36
+ - Author a `:UnitTests:` framework requirement in `***implementation reqs***` at the appropriate scope (template if shared, otherwise on the module) — e.g. "`:UnitTests:` should use pytest" plus "`:UnitTests:` are run via `pytest tests/`". Generate `run_unittests` (and any framework config it needs, e.g. `pytest.ini`, `jest.config.js`) via `implement-unit-testing-script`. Add the `unittests-script:` entry to the relevant `config.yaml`(s), creating each file if it doesn't exist yet.
37
+ - Review the framework req, the generated script paths, and the new `config.yaml` entry.
38
+ 2. **Unit-test types and architecture mapping** — which of unit tests and integration tests the user wants, and how tests map to the Phase 2 architectural layers (e.g. one test module per service, repository tests with an in-memory store). Author a `:UnitTests:` scope / architecture requirement in `***implementation reqs***`, phrased in terms of `:UnitTests:` so the partition is visible. Review that requirement.
39
+ 3. **Conformance testing** — explicitly ask whether conformance / end-to-end tests should be part of the project. This drives whether `run_conformance_tests` is generated and whether `***acceptance tests***` are authored. If the user is unsure, briefly explain the tradeoff (extra scripts + per-spec acceptance tests vs. lighter setup) and let them choose.
40
+ - If **yes**: author a conformance-testing requirement in `***test reqs***` (framework, execution command, any constraints); generate `run_conformance_tests` via `implement-conformance-testing-script`; add the `conformance-tests-script:` entry to the relevant `config.yaml`(s); then **walk every functional spec authored in Phase 1, one at a time** — for each spec, ask one `AskUserQuestion` whether it needs concrete verification, and if yes author one acceptance test under that spec via `add-acceptance-test`, then review that acceptance test as a snippet before moving to the next spec. Never bulk-write acceptance tests; never ask about more than one spec per call.
41
+ - If **no**: record the decision; skip the conformance script, its config entry, and acceptance-test authoring entirely.
42
+ - Review the conformance req (if any), the new script and config entry (if any), and each acceptance test snippet (if any).
43
+ 4. **Environment preparation script** — explicitly ask whether a `prepare_environment` script should be generated. It is the single entry point for installing dependencies and setting up fixtures/services before tests run. If the user is unsure, note it is recommended when there are dependencies to install or services to start, and skippable when the project genuinely has nothing to prepare.
44
+ - If **yes**: generate `prepare_environment` via `implement-prepare-environment-script`; add the `prepare-environment-script:` entry to the relevant `config.yaml`(s); if the script's responsibilities are non-trivial and worth pinning in the spec, add a brief `***test reqs***` entry describing what `prepare_environment` is responsible for.
45
+ - If **no**: record the decision; skip the script and the config entry.
46
+ - Review the script (if any), the new config entry (if any), and the test req (if any).
47
+ 5. **Test layout & conventions** — directory layout, naming conventions, fixtures / mocks strategy — anything that constrains the *shape* of test code beyond what topics 1–4 established. Ask about both kinds of tests where applicable; keep their facts in separate reqs in separate sections. Author `:UnitTests:` layout / convention requirements in `***implementation reqs***` and `:ConformanceTests:` layout / convention requirements in `***test reqs***` (only when conformance is enabled), each phrased with the predefined concept it shapes so the partition is visible. Review each requirement snippet.
48
+ 6. **Execution & tooling** — how tests are run (commands, runners, options), coverage targets, CI integration, any environment setup tests rely on beyond `prepare_environment`. Split by concept the same way as topic 5. If the agreed execution command or options differ from what a script generated in topic 1, 3, or 4 currently uses, update the affected script(s) now. Author `:UnitTests:` execution requirements in `***implementation reqs***` and `:ConformanceTests:` execution requirements in `***test reqs***`. Review each requirement snippet and any modified script.
49
+ 7. **Other testing constraints** — performance / load expectations, deterministic seeds, network isolation, secrets handling — anything stack-wide that constrains *how* tests are written and hasn't already been covered. Author each constraint as its own requirement at the appropriate scope. Review each constraint snippet.
50
+ 8. **Anything else** — anything the user wants to add or change that hasn't already been covered.
51
+
52
+ When all topics are complete, recap the full testing strategy: which `config.yaml`(s) exist, which scripts each points at, the framework, the test types in scope, the conformance and prepare-environment decisions, and any cross-cutting constraints. Get an explicit overall confirmation, then verify the environment.
53
+
54
+ ## Verify the environment
55
+
56
+ Delegate environment verification to the `check-plain-env` skill — do **not** probe the machine inline. It is the single source of truth for "can this machine render and test this project?" and derives the requirement list at runtime from the project's `.plain` files, `test_scripts/`, `config.yaml`(s), and `resources/`.
57
+
58
+ `check-plain-env` detects the host OS, builds the requirement list (language toolchains + their package managers, external services, system binaries that language packages wrap, hardware / drivers / accelerators, `codeplain` itself, credentials — the layers a package manager **cannot** install), probes each with a real version / availability command, and emits a `PASS` / `WARN` / `FAIL` report with OS-specific install commands for any gaps. It never probes individual language packages (`torch`, `numpy`, `FastAPI`, `react`, JARs, gems) — those are installed by the project's own `prepare_environment` / unit-test scripts the moment they run. It is read-only and installs nothing itself.
59
+
60
+ Act on the return value:
61
+
62
+ - **`PASS`** — the machine is ready. Continue to Phase 4.
63
+ - **`WARN`** — everything required is present but there is at least one soft warning (e.g. a service binary present but its daemon not running, a language-version mismatch). Show the warnings to the user; let them decide whether to address each one now or proceed knowing the corresponding scripts will surface the issue later.
64
+ - **`FAIL`** — at least one required item is missing. For every gap the report already gives what is missing, why the project needs it, and how to install it for the detected OS. Walk the gaps with the user: install now, swap to an alternative (which means revising the Phase 2 / Phase 3 decisions), or proceed knowing the corresponding scripts will fail. Re-invoke `check-plain-env` after the user installs anything so the report reflects the current state of the machine.
65
+
66
+ Do not move on to Phase 4 until `check-plain-env` returns `PASS`, or `WARN` / `FAIL` with the user's explicit acknowledgement of each remaining item.
@@ -0,0 +1,49 @@
1
+ # Phase 4 — Validate and hand off
2
+
3
+ Two halves. First **the agent** validates every spec end-to-end with a `codeplain` dry-run so the user never wastes a real render — or any debugging time — on a fixable static error. Only after that passes does the agent **hand off** the render command (plus any side-channel commands) to the user.
4
+
5
+ ## 4a. Identify the render target
6
+
7
+ Find the **last module in the dependency chain** — the module that is not `requires`-ed by any other module. If there is only one module, use it. Call this module `<module>`.
8
+
9
+ - Chain `base.plain → features.plain → integrations.plain` → render target is `integrations.plain`.
10
+ - Single module `my_app.plain` → render target is `my_app.plain`.
11
+
12
+ ## 4b. Build the final `config.yaml` with `init-config-file`
13
+
14
+ Finalize the project's `config.yaml` file(s) before validation. Phase 3 may have written provisional entries as scripts were generated; **this** is where they are consolidated into the canonical form the renderer expects. Invoke the `init-config-file` skill. It:
15
+
16
+ - enumerates every part of the project (one `config.yaml` per part — single-stack → root config; multi-part → one config per part),
17
+ - assembles only the **valid** config keys derived from the `codeplain` CLI parser,
18
+ - emits a clean YAML file per part (script paths first, then template/build folders, then copy/log settings),
19
+ - verifies every `*-script` value resolves to a real file on disk,
20
+ - refuses to write secrets (`api-key`) or per-invocation flags (`dry-run`, `full-plain`, `render-range`, `render-from`, `replay-with`) into the config.
21
+
22
+ If `init-config-file` stops because a precondition isn't met (e.g. a `prepare-environment-script` exists but no conformance script does), resolve the gap with the user before continuing — do **not** hand a known-broken config to `plain-healthcheck`.
23
+
24
+ ## 4c. Validate the project with `plain-healthcheck`
25
+
26
+ Run the `plain-healthcheck` skill — the single source of truth for "is this project ready to render?". Do **not** run the dry-run inline. It:
27
+
28
+ - inventories every `.plain` module and identifies every top module,
29
+ - validates every `config.yaml` (existence, parseability, script paths actually pointing at files in `test_scripts/`, no mixed stacks), and
30
+ - runs `codeplain <top>.plain --dry-run` for **every** top module with the correct `--config-name` for multi-part projects.
31
+
32
+ The skill runs the full detect → fix → re-run loop itself (syntax errors, undefined concepts, broken `import` / `requires` chains, cyclic definitions, missing templates, complexity violations, conflicting reqs, config drift, missing scripts) and returns only once everything passes or a gap genuinely needs the user. Then:
33
+
34
+ - **`PASS`** → move on to step 4d.
35
+ - **`FAIL`** → do **not** ask the user to render. Work through the numbered list it produced (each item references a specific `.plain` file, `config.yaml`, or script), resolve each one with the appropriate edit skill, and re-run `plain-healthcheck` until it returns `PASS`. Any item the skill could not auto-resolve will name the concrete question to put to the user.
36
+ - **Environment failure** (e.g. `codeplain` not on PATH, `CODEPLAIN_API_KEY` not set) → `plain-healthcheck` surfaces this as a clearly-marked environment failure. Tell the user exactly what's missing and how to fix it before continuing. Do not pretend the healthcheck passed.
37
+
38
+ ## 4d. Present the render command
39
+
40
+ Only after the dry-run passes, tell the user their specs are ready and present the render command:
41
+
42
+ ```
43
+ codeplain <module>.plain
44
+ ```
45
+
46
+ - Chain `base.plain → features.plain → integrations.plain` → `codeplain integrations.plain`.
47
+ - Single module `my_app.plain` → `codeplain my_app.plain`.
48
+
49
+ Also remind the user of any **side-channel commands** they may want to run themselves per the Phase 3 testing strategy — for example `./test_scripts/run_unittests.sh <module>`, `./test_scripts/prepare_environment.sh <module>`, or `./test_scripts/run_conformance_tests.sh <module> <conformance_tests_folder>`. Mention only the scripts that were actually generated in Phase 3.
@@ -43,7 +43,7 @@ Everything else — toolchain check, build staging, dependency isolation, exit c
43
43
 
44
44
  ### Why this split exists
45
45
 
46
- The conformance runner is invoked **once per functional spec** by the renderer. Each functional spec in a module has its own `conformance_tests/<module>/<spec>/` folder, and after the renderer finishes generating code for a new spec, it runs the conformance tests of **every previous spec** in the same module to detect regressions. For a module with N functional specs, this script is called **on the order of N times per render** — not once per render.
46
+ The conformance runner is invoked **once per functional spec** by the renderer. Each functional spec in a module has its own `plain_modules/<module>/tests/<spec>/` folder, and after the renderer finishes generating code for a new spec, it runs the conformance tests of **every previous spec** in the same module to detect regressions. For a module with N functional specs, this script is called **on the order of N times per render** — not once per render.
47
47
 
48
48
  That per-spec invocation pattern is what makes the install step expensive. A naive runner that does `pip install` / `npm ci` / `mvn install -DskipTests` / `cargo build` on every invocation pays the install cost N times per render. For anything beyond a toy project, that cost dominates wall-clock time.
49
49
 
@@ -123,7 +123,7 @@ A conformance script has **two** read-only inputs: the source build folder (`$1`
123
123
 
124
124
  Why each input is read-only:
125
125
 
126
- - **`$1` (build folder)** is shared with the renderer (`plain_modules/...` by default) and downstream tooling. Writing into it corrupts the renderer's view of "what was generated" and breaks subsequent renders. The whole point of staging into the system temp directory is so the source folder stays a clean, reproducible artifact of the render.
126
+ - **`$1` (build folder)** is shared with the renderer (`plain_modules/<module>/code` by default) and downstream tooling. Writing into it corrupts the renderer's view of "what was generated" and breaks subsequent renders. The whole point of staging into the system temp directory is so the source folder stays a clean, reproducible artifact of the render.
127
127
  - **`$2` (conformance tests folder)** is the user's authored test source — typically checked into version control. Writing into it pollutes the working tree, churns git status, and (with frameworks that auto-discover) can make subsequent runs pick up generated files as if they were tests.
128
128
 
129
129
  If you find yourself about to issue any command whose `cwd` is `$1` or `$2`, or whose target path starts with `$1/` or `$2/`, **stop**. Either move the operation into `<temp>/<lang>_<basename>`, or you're doing something the script must not do.
@@ -27,7 +27,7 @@ When this script exists for a project, the corresponding conformance script's ow
27
27
 
28
28
  ### Why this script exists at all (the structural reason)
29
29
 
30
- The conformance test runner is invoked **once per functional spec** by the renderer — not once per render. Each functional spec in a module has its own `conformance_tests/<module>/<spec>/` folder, and after the renderer finishes generating code for a new spec, it runs the conformance tests of **every previous spec** in the same module to detect regressions. For a module with N functional specs, the conformance script is invoked roughly N times on every render.
30
+ The conformance test runner is invoked **once per functional spec** by the renderer — not once per render. Each functional spec in a module has its own `plain_modules/<module>/tests/<spec>/` folder, and after the renderer finishes generating code for a new spec, it runs the conformance tests of **every previous spec** in the same module to detect regressions. For a module with N functional specs, the conformance script is invoked roughly N times on every render.
31
31
 
32
32
  Without a prepare script, every one of those N invocations does the full dependency install (Python venv + `pip install`, full Maven dependency tree, `npm ci`, `cargo build`, ...) from scratch. That cost — paid N times per render — dominates the wall-clock time of rendering a non-trivial project.
33
33
 
@@ -103,7 +103,7 @@ The source build folder passed in as `$1` is **input only**. Prepare reads from
103
103
  - pre-build into it (every compile output — `target/`, `build/`, `dist/`, native binaries, generated sources — lives inside `<temp>/<lang>_<basename>`),
104
104
  - create logs, caches, or temp files inside it.
105
105
 
106
- The build folder is shared with the renderer (`plain_modules/...` by default) and with the conformance script, which staging-checks the working folder via `if [ ! -d "/tmp/<lang>_$(basename "$1")" ]` and expects `$1` itself to look the same as it did right after rendering. Writing into `$1` corrupts the renderer's view of "what was generated", churns git status if the project commits `$1`, and (if the conformance script ever does an `rm -rf $1` during its own setup) silently destroys work prepare did.
106
+ The build folder is shared with the renderer (`plain_modules/<module>/code` by default) and with the conformance script, which staging-checks the working folder via `if [ ! -d "/tmp/<lang>_$(basename "$1")" ]` and expects `$1` itself to look the same as it did right after rendering. Writing into `$1` corrupts the renderer's view of "what was generated", churns git status if the project commits `$1`, and (if the conformance script ever does an `rm -rf $1` during its own setup) silently destroys work prepare did.
107
107
 
108
108
  The whole point of staging into `<temp>/<lang>_<basename>` is so the source build folder stays a clean, reproducible artifact of the render and no build debris lands inside the user's project. Every dependency, every compiled class, every binary, every cache must land inside the working folder — because that is exactly what the conformance script's activate-only variant attaches to.
109
109
 
@@ -47,7 +47,7 @@ The source build folder passed in as `$1` is **input only**. The script must nev
47
47
  - run the test command from inside it (every test command runs from inside `<temp>/<lang>_<basename>` after the `cd` in step 5),
48
48
  - create logs, caches, build outputs, or temp files inside it.
49
49
 
50
- The build folder is shared with the renderer (`plain_modules/...` by default) and downstream tooling. Writing into it corrupts the renderer's view of "what was generated" and breaks subsequent renders. Every write must go into `<temp>/<lang>_<basename>` — the whole point of staging into the system temp directory is so the source build folder stays a clean, reproducible artifact of the render and no build debris is left inside the user's project.
50
+ The build folder is shared with the renderer (`plain_modules/<module>/code` by default) and downstream tooling. Writing into it corrupts the renderer's view of "what was generated" and breaks subsequent renders. Every write must go into `<temp>/<lang>_<basename>` — the whole point of staging into the system temp directory is so the source build folder stays a clean, reproducible artifact of the render and no build debris is left inside the user's project.
51
51
 
52
52
  If you find yourself about to issue any command whose `cwd` is the source folder, or whose target path starts with `$1/`, **stop**. Either move the operation into `<temp>/<lang>_<basename>`, or you're doing something the script must not do.
53
53
 
@@ -13,6 +13,8 @@ description: >-
13
13
 
14
14
  # Init Config File
15
15
 
16
+ Always use the skill `load-codeplain-reference` to retrieve the full `codeplain` CLI reference (every flag, the `config.yaml` mapping, and the secrets / per-invocation keys that must never be written to config) — but only if you haven't done so yet. This skill assembles `config.yaml` from the valid CLI-derived keys, so the CLI reference is required.
17
+
16
18
  This skill is the **single authoritative writer** of `config.yaml` for a ***plain project. Anything that ends up in `config.yaml` should go through this skill. The renderer (`codeplain`) reads each key listed below into the same argparse namespace it uses for CLI flags — so a value set in `config.yaml` is exactly equivalent to passing the corresponding `--flag` on the command line.
17
19
 
18
20
  ## When to run
@@ -57,8 +59,7 @@ These keys reflect choices made in Phase 3 of `forge-plain` and are the bread an
57
59
  | `test-script-timeout` | int (seconds) | `120` | Include only when the user explicitly raised/lowered the default. |
58
60
  | `template-dir` | path (string) | — | Include whenever the project has an `import` module or a custom template directory (e.g. `template/`). Required for projects with shared templates. |
59
61
  | `logging-config-path` | path (string) | `logging_config.yaml` | Points at a **separate** YAML file consumed by Python's `logging.config.dictConfig`. This is the only knob that lets the user actually change log **levels** for the renderer and its dependencies. See [Logging configuration](#logging-configuration) below. Include the key explicitly whenever the project ships a non-default logging config; leave it out only when the user is happy with the renderer's defaults (`INFO` root, `WARNING` for `git`, `ERROR` for `transitions`). |
60
- | `conformance-tests-folder` | string | `conformance_tests` | Include only when the user picked a non-default folder name. |
61
- | `build-folder` | string | `plain_modules` | Include only when the user picked a non-default folder name. Must differ from `build-dest`. |
62
+ | `build-folder` | string | `plain_modules` | Include only when the user picked a non-default folder name. Must differ from `build-dest`. The renderer writes `<build-folder>/<module>/code` (implementation + unit tests) and `<build-folder>/<module>/tests` (conformance tests, one folder per functional spec). |
62
63
  | `build-dest` | string | `dist` | **Always include with the value `dist`.** This skill pins the copy destination explicitly so every project's `config.yaml` has the same, predictable target folder for the post-render copy. Even though `dist` matches the renderer's default, we still write it out so the choice is visible in the file and protected against future default changes. Must differ from `build-folder`. |
63
64
  | `base-folder` | string | — | Include when the user wants build output rooted somewhere other than the project root. |
64
65
 
@@ -70,7 +71,7 @@ These are useful but the defaults are almost always fine. Only include them when
70
71
  |---|---|---|---|
71
72
  | `copy-build` | bool | `true` | The renderer copies the rendered code to `build-dest` after a successful render. Set to `false` only when the user doesn't want this. |
72
73
  | `copy-conformance-tests` | bool | `false` | Requires `conformance-tests-script` to also be set. |
73
- | `conformance-tests-dest` | string | `dist_conformance_tests` | Target folder for the conformance-test copy. Must differ from `conformance-tests-folder`. |
74
+ | `conformance-tests-dest` | string | `dist_conformance_tests` | Target folder for the post-render copy of `plain_modules/<module>/tests`. Must differ from `build-folder`. |
74
75
  | `log-to-file` | bool | `true` | Disable only when the user explicitly does not want a log file. Controls whether logs are mirrored to disk — it does **not** set the log level (that's `logging-config-path`'s job). |
75
76
  | `log-file-name` | string | `codeplain.log` | If `log-to-file` is `false`, this key must be left out. A relative value set here resolves against the config file's directory; when the key is left out entirely, the default resolves against the `.plain` file's directory. |
76
77
  | `render-machine-graph` | bool | `false` | Include only when the user wants the state-machine graph rendered. |
@@ -121,6 +121,10 @@ Tell the user what was created and what's next:
121
121
  - Suggested next steps: add concepts with `add-concept`, add functional specs with `add-functional-spec` or `add-functional-specs`, or jump straight into `add-feature`.
122
122
  - Mention that `codeplain <project>.plain --dry-run` has not been run — they can run `plain-healthcheck` when they want validation.
123
123
 
124
+ ## Validation checklist
125
+
126
+ Before the recap, walk `references/checklist.md` and confirm every box is met. It is a self-audit of this workflow — never a substitute for it. A box only counts as met when the file is on disk as described; complete any unmet step before recapping.
127
+
124
128
  ## Question style
125
129
 
126
130
  Use simple grammatical structures: short direct sentences, one idea per sentence, plain words over jargon. Keep every constraint and edge case the user needs to answer accurately.
@@ -0,0 +1,31 @@
1
+ # Init Plain Project Workflow Checklist
2
+
3
+ Use this to verify the scaffold was produced correctly — never as a substitute for the workflow. Run it once before the recap. This skill is intentionally minimal: it writes a runnable skeleton, not a complete spec. If a box is unmet, go back and complete the step.
4
+
5
+ ## Setup
6
+
7
+ - [ ] Invoked `load-plain-reference` first (unless already loaded this session).
8
+
9
+ ## Ask the basics
10
+
11
+ - [ ] Asked project basics in one `AskUserQuestion` batch (project name, base technology, project kind) plus a free-form catch-all.
12
+ - [ ] Asked testing in one `AskUserQuestion` batch (unit-test framework, conformance on/off, and prepare-environment only if conformance was enabled).
13
+
14
+ ## Author the modules
15
+
16
+ - [ ] Created `template/base.plain` via `create-import-module` with `***implementation reqs***` (language/version, framework, package manager, project kind, and everything about `:UnitTests:` — framework + run command).
17
+ - [ ] Added `***test reqs***` to `template/base.plain` with the `:ConformanceTests:` rules **only** when conformance testing is enabled — and kept unit-test facts out of it.
18
+ - [ ] No `***definitions***`, no `***functional specs***`, and no project-specific concepts in `template/base.plain`; only predefined concepts (`:Implementation:`, `:ConformanceTests:`) used; no `required_concepts` declared.
19
+ - [ ] Created `<project>.plain` at the repo root with frontmatter only (`import: [base]`, `description`) and **no body sections** — the file exists on disk.
20
+
21
+ ## Generate scripts and config
22
+
23
+ - [ ] Generated `implement-unit-testing-script` (always).
24
+ - [ ] Generated `implement-conformance-testing-script` only if conformance was enabled (activate-only variant when a prepare-environment script will also exist, otherwise install-inline).
25
+ - [ ] Generated `implement-prepare-environment-script` only if conformance was enabled **and** the user opted in.
26
+ - [ ] Wrote `config.yaml` at the project root with only the keys for scripts actually generated, plus `template_dir: template`, using the correct `.sh`/`.ps1` extension for the host OS.
27
+ - [ ] Did **not** run `init-config-file`, `plain-healthcheck`, `check-plain-env`, or `codeplain --dry-run` (out of scope for this skill).
28
+
29
+ ## Recap
30
+
31
+ - [ ] Told the user what was written, suggested next steps (`add-concept`, `add-functional-spec(s)`, `add-feature`), and noted that no dry-run was run (they can run `plain-healthcheck` later).
@@ -0,0 +1,188 @@
1
+ ---
2
+ name: load-codeplain-reference
3
+ description: >-
4
+ Loads the full `codeplain` CLI reference into context: the render command and
5
+ its positional plain-file argument, every flag (render control, config,
6
+ folders, test-script wiring, output copying, API, logging, headless mode),
7
+ path-resolution rules, the CODEPLAIN_API_KEY environment variable, the
8
+ config.yaml mapping, and the success/failure render banners. Use whenever
9
+ running, configuring, resuming, or reasoning about a `codeplain` render or its
10
+ config.yaml. Not for the ***plain language syntax itself (use
11
+ load-plain-reference) or for supervising a live render (use run-codeplain).
12
+ ---
13
+
14
+ # CODEPLAIN_CLI_REFERENCE.md
15
+
16
+ `codeplain` is the CLI that renders `***plain` specification files into production-ready code. It reads a `.plain` module (and everything it `import`s / `requires`), calls the codeplain API, and writes generated code under `plain_modules/<module>/code/` and conformance tests under `plain_modules/<module>/tests/`. The `.plain` specs are the source of truth; the generated code is a read-only artifact.
17
+
18
+ This reference covers the CLI surface only. For the `***plain` language itself use `load-plain-reference`; to supervise a live render use `run-codeplain`; to assemble or validate `config.yaml` use `init-config-file` / `plain-healthcheck`.
19
+
20
+ ## Usage
21
+
22
+ ```text
23
+ codeplain [options] filename
24
+ ```
25
+
26
+ ```text
27
+ usage: codeplain [-h] [--verbose] [--base-folder BASE_FOLDER]
28
+ [--build-folder BUILD_FOLDER]
29
+ [--log-to-file | --no-log-to-file]
30
+ [--log-file-name LOG_FILE_NAME] [--config-name CONFIG_NAME]
31
+ [--render-range RENDER_RANGE | --render-from RENDER_FROM]
32
+ [--force-render] [--unittests-script UNITTESTS_SCRIPT]
33
+ [--conformance-tests-folder CONFORMANCE_TESTS_FOLDER]
34
+ [--conformance-tests-script CONFORMANCE_TESTS_SCRIPT]
35
+ [--prepare-environment-script PREPARE_ENVIRONMENT_SCRIPT]
36
+ [--test-script-timeout TEST_SCRIPT_TIMEOUT] [--api [API]]
37
+ [--api-key API_KEY] [--full-plain] [--dry-run]
38
+ [--replay-with REPLAY_WITH] [--template-dir TEMPLATE_DIR]
39
+ [--copy-build] [--build-dest BUILD_DEST]
40
+ [--copy-conformance-tests]
41
+ [--conformance-tests-dest CONFORMANCE_TESTS_DEST]
42
+ [--render-machine-graph]
43
+ [--logging-config-path LOGGING_CONFIG_PATH] [--headless]
44
+ filename
45
+ ```
46
+
47
+ ## Positional argument
48
+
49
+ - **`filename`** — path to the `.plain` file to render. The directory containing this file has the **highest precedence for template loading**, so custom templates placed there override the defaults (see `--template-dir`). Render the **top module** of the dependency chain — the module not `requires`-ed by any other; its `requires`/`import` graph is pulled in automatically.
50
+
51
+ ## Path resolution (read this before setting any path flag)
52
+
53
+ A path's meaning depends on **where it was written**:
54
+
55
+ - Values given **on the command line** resolve against the **current working directory**.
56
+ - Values read from **`config.yaml`** resolve against the **config file's directory**.
57
+ - **Default** values resolve against the **directory containing the `.plain` file**.
58
+ - **Absolute paths** (and paths starting with `~`) are used as-is.
59
+
60
+ ## Options
61
+
62
+ ### Render control
63
+
64
+ - **`--dry-run`** — preview code generation without making any changes. This is the static-validation gate; `plain-healthcheck` runs `codeplain <top>.plain --dry-run` for every top module before a real render. **Per-invocation only — never store in `config.yaml`.**
65
+ - **`--full-plain`** — full preview of the assembled `***plain` specification before code generation. Use to inspect the context of all `***plain` primitives that will be included to render the given module. **Per-invocation only — never in `config.yaml`.**
66
+ - **`--render-range RENDER_RANGE`** — render a range of functionalities (e.g. `1`, or `2,3`). A comma separates the start and end IDs; the range is inclusive of both. A single ID renders only that one functionality. Mutually exclusive with `--render-from`. **Per-invocation only — never in `config.yaml`.**
67
+ - **`--render-from RENDER_FROM`** — continue generation starting from this functionality ID (inclusive). The ID must match a functionality in the `.plain` file. This is how a run resumes after a spec fix — pass the **first functionality to re-render**. Mutually exclusive with `--render-range`. **Per-invocation only — never in `config.yaml`.**
68
+ - **`--force-render`** — force a re-render of all required modules, invalidating cached module renders. Use only when a backward dependency genuinely changed; it costs more credits.
69
+ - **`--replay-with REPLAY_WITH`** — replay a previous render. **Per-invocation only — never in `config.yaml`.**
70
+
71
+ ### Configuration
72
+
73
+ - **`--config-name CONFIG_NAME`** — name of the config file to look for. It is looked up in the `.plain` file's directory and in the current working directory. Defaults to `config.yaml`. Use it for multi-part projects (one config per part) or a non-default config file name.
74
+
75
+ ### Folders
76
+
77
+ - **`--base-folder BASE_FOLDER`** — base folder for the build files.
78
+ - **`--build-folder BUILD_FOLDER`** — folder for build files (generated code lands under here, per module: `plain_modules/<module>/code/` and `plain_modules/<module>/tests/`).
79
+ - **`--template-dir TEMPLATE_DIR`** — path to a custom template directory. Templates are searched in this order: 1) the directory containing the `.plain` file, 2) this custom template directory, 3) the built-in `standard_template_library` directory. In `config.yaml` the equivalent key is `template_dir` — set it whenever the project has import modules or templates.
80
+
81
+ ### Test-script wiring
82
+
83
+ - **`--unittests-script UNITTESTS_SCRIPT`** — shell script that runs unit tests on the generated code. Receives the build folder path as its first argument (default: `plain_modules`). `config.yaml` key: `unittests-script`.
84
+ - **`--conformance-tests-folder CONFORMANCE_TESTS_FOLDER`** — folder for conformance test files.
85
+ - **`--conformance-tests-script CONFORMANCE_TESTS_SCRIPT`** — path to the conformance-tests shell script. It must accept two arguments: 1) a folder containing generated source code (e.g. `plain_modules/module_name`), and 2) a subfolder of the conformance-tests folder containing the test files (e.g. `conformance_tests/subfoldername`). `config.yaml` key: `conformance-tests-script`.
86
+ - **`--prepare-environment-script PREPARE_ENVIRONMENT_SCRIPT`** — path to a shell script that prepares the testing environment. It must accept the source-code folder path as its first argument. It runs once per render, only to warm the environment the conformance runner attaches to. `config.yaml` key: `prepare-environment-script`. If this is declared, `conformance-tests-script` must be declared too.
87
+ - **`--test-script-timeout TEST_SCRIPT_TIMEOUT`** — timeout for test scripts, in seconds. Defaults to 120 seconds. Raise it if the project's test scripts are slow.
88
+
89
+ ### Output copying
90
+
91
+ - **`--copy-build`** — after a successful render, copy the rendered code in `--base-folder` to `--build-dest`.
92
+ - **`--build-dest BUILD_DEST`** — target folder for `--copy-build` (used only when `--copy-build` is set).
93
+ - **`--copy-conformance-tests`** — after a successful render, copy the conformance tests in `--conformance-tests-folder` to `--conformance-tests-dest`. Requires `--conformance-tests-script`.
94
+ - **`--conformance-tests-dest CONFORMANCE_TESTS_DEST`** — target folder for `--copy-conformance-tests` (used only when it is set).
95
+
96
+ ### API
97
+
98
+ - **`--api [API]`** — alternative base URL for the API. Default: `https://api.codeplain.ai`.
99
+ - **`--api-key API_KEY`** — API key used to access the API. If not provided, the `CODEPLAIN_API_KEY` environment variable is used. **Secret — never store it in `config.yaml`.**
100
+
101
+ ### Logging & output mode
102
+
103
+ - **`--verbose`, `-v`** — enable verbose output. Verbose logging captures each test script's stdout/stderr into the log file between the renderer's own wrapper lines, which is what makes a live render inspectable. Keep logging verbose.
104
+ - **`--log-to-file` / `--no-log-to-file`** — enable or disable logging to a file. Defaults to `True`; pass `--no-log-to-file` to disable.
105
+ - **`--log-file-name LOG_FILE_NAME`** — name of the log file. Defaults to `codeplain.log`. If a file already exists at the resolved path, it is **overwritten** by the current run's logs — the log is therefore per-run, and its default location is the `.plain` file's directory.
106
+ - **`--logging-config-path LOGGING_CONFIG_PATH`** — path to a logging configuration file.
107
+ - **`--headless`** — run without the TUI: no terminal output except a single render-started message; all logs are written to the log file. **Required for agent-supervised runs** — a terminal tool cannot drive the interactive TUI, so supervision reads `codeplain.log` instead.
108
+ - **`--render-machine-graph`** — render the state-machine graph. Use only on explicit request.
109
+ - **`-h`, `--help`** — show the help message and exit.
110
+
111
+ ## Environment variables
112
+
113
+ - **`CODEPLAIN_API_KEY`** — the API key used when `--api-key` is not passed on the command line. Export it before rendering (or pass `--api-key`). It is a secret and must never be written into `config.yaml`.
114
+
115
+ ## `config.yaml` relationship
116
+
117
+ `codeplain` reads persistent options from a `config.yaml` (or the file named by `--config-name`), looked up in the `.plain` file's directory and the current working directory. This avoids retyping stable options on every run.
118
+
119
+ - **One `config.yaml` per part of the system that has its own test scripts.** A single-stack project has one at the root; a multi-part project (e.g. a Python backend and a React frontend) has one per part, each referencing only its own scripts.
120
+ - **Established keys:** `unittests-script`, `conformance-tests-script`, `prepare-environment-script`, `template_dir`, `base-folder`, `build-folder`, plus copy/log settings. `init-config-file` is the canonical assembler and the source of truth for the full valid key set; treat it as authoritative.
121
+ - **Constraint:** if `prepare-environment-script` is declared, `conformance-tests-script` must be declared too — a prepare script only exists in service of conformance.
122
+ - **Never put in `config.yaml`:** secrets (`api-key`) and per-invocation flags (`dry-run`, `full-plain`, `render-range`, `render-from`, `replay-with`). Supply these on the command line only.
123
+ - Remember the path-resolution rule above: a script path written in `config.yaml` resolves against the config file's directory, not the working directory.
124
+
125
+ ## Render output
126
+
127
+ Generated artifacts (gitignored, read-only — never edit):
128
+
129
+ - `plain_modules/<module>/code/` — the generated project for each `.plain` spec (implementation + unit tests).
130
+ - `plain_modules/<module>/tests/<functionality>/` — generated conformance tests, one subfolder per functionality.
131
+ - `codeplain.log` — the per-run log (overwritten each run).
132
+
133
+ When a run ends, `codeplain` writes a result banner (to the log, and to the terminal outside headless mode):
134
+
135
+ - **Success:** `✓ rendering succeeded` (or `rendering complete`), followed by a metadata block: render id, input file, generated code folder, functionalities count, used credits, render time.
136
+ - **Failure:** `✗ rendering failed`, followed by the same metadata block.
137
+
138
+ ## Test-script exit-code contract
139
+
140
+ The three wired scripts (`unittests-script`, `conformance-tests-script`, `prepare-environment-script`) share an exit-code contract that `codeplain`, `plain-healthcheck`, and `check-plain-env` all branch on:
141
+
142
+ - **`69`** — unrecoverable error (missing toolchain, bad arguments, cannot enter the working folder, install failed).
143
+ - **`1`** — the "no tests discovered" guard in the conformance runner (and bad usage in the unit-test runner).
144
+ - **any other non-zero** — propagated verbatim from the underlying test command (a real test failure).
145
+
146
+ Author or modify these scripts only through the matching `implement-{unit-testing,conformance-testing,prepare-environment}-script` skill — never by hand.
147
+
148
+ ## Common invocation patterns
149
+
150
+ ```bash
151
+ # Static-validation gate before a real render (what plain-healthcheck runs)
152
+ codeplain <module>.plain --dry-run
153
+
154
+ # Full render of the top module
155
+ codeplain <module>.plain
156
+
157
+ # Multi-part project: render one part with its own config file
158
+ codeplain backend/api.plain --config-name config.yaml
159
+
160
+ # Agent-supervised render: background + headless, watch codeplain.log
161
+ nohup codeplain <module>.plain --headless > /dev/null 2>&1 &
162
+
163
+ # Resume after a spec fix: re-render from functionality N (inclusive)
164
+ codeplain <module>.plain --render-from <N>
165
+
166
+ # Re-render exactly one functionality
167
+ codeplain <module>.plain --render-range <N>
168
+
169
+ # Force a full re-render (backward dependency changed) — costs more credits
170
+ codeplain <module>.plain --force-render
171
+ ```
172
+
173
+ ## Common errors and signals
174
+
175
+ - **`codeplain: command not found`** — the CLI is not installed or not on `PATH`. Confirm with `command -v codeplain`.
176
+ - **`401` / `403` / `unauthorized`** — `CODEPLAIN_API_KEY` is unset or invalid; export it or pass `--api-key`. This is an API/auth problem, not a spec problem.
177
+ - **`429` / `rate limit` / `quota`** — API throttling or credit limit; not a spec problem.
178
+ - **`Functional spec too complex!`** — a single functional spec implies more than 200 lines of code; break it down (`break-down-func-spec`).
179
+ - **`missing concept` / `unknown definition` / `cyclic` / `not defined` / `cannot resolve`** — a spec-graph error (a concept used before it is defined, a cycle, or a broken `import`/`requires` chain). A `--dry-run` catches these before spending credits.
180
+ - **`Traceback (most recent call last):`** — the renderer itself crashed (a bug), not a spec error; capture the stack for a bug report.
181
+
182
+ ## See also
183
+
184
+ - `load-plain-reference` — the `***plain` language syntax and authoring rules.
185
+ - `run-codeplain` — supervising a live render (monitor loop, pathologies, resume).
186
+ - `plain-healthcheck` — the pre-render dry-run gate across every top module.
187
+ - `init-config-file` — canonical `config.yaml` assembly and the full valid key set.
188
+ - `implement-{unit-testing,conformance-testing,prepare-environment}-script` — authoring the wired test scripts.