plain-forge 1.0.2 → 1.0.4

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.
@@ -0,0 +1,46 @@
1
+ ---
2
+ description: Line-length and bullet-continuation rules for every section in .plain files
3
+ globs: "**/*.plain"
4
+ ---
5
+
6
+ # Rules for line length in `.plain` files
7
+
8
+ These rules apply to **every** section — `***definitions***`, `***implementation reqs***`, `***test reqs***`, `***functional specs***`, `***acceptance tests***` — and to concept explanations alike.
9
+
10
+ ## Hard limit: 120 characters per line
11
+ - If a line exceeds 120 characters, split it at a natural clause boundary into nested `- ` bullets
12
+ - Concision is in service of clarity, never the other way around — wordy-but-precise always beats terse-but-ambiguous
13
+ - 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
14
+
15
+ ## Never use bare continuation lines (invalid ***plain syntax)
16
+ - ***plain syntax requires every line inside a section to be its own list item starting with `- `
17
+ - Indented continuation lines without a leading `- ` are syntactically invalid — they look reasonable to a human reader but the renderer cannot parse them
18
+ - 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
19
+
20
+ ## Examples
21
+
22
+ BAD — line is too long:
23
+
24
+ ```plain
25
+ - :GatewayWebhook: should hand off :StripeRequest: to :StripeIntegration:.handle(), which returns a list of :EventEnvelope: dicts conforming to the gateway's contract.
26
+ ```
27
+
28
+ WRONG SYNTAX (AVOID AT ALL COSTS) — bare indented continuation without a leading `- `:
29
+
30
+ ```plain
31
+ - :GatewayWebhook: should hand off :StripeRequest: to :StripeIntegration:.handle(),
32
+ which returns a list of :EventEnvelope: dicts conforming to the gateway's
33
+ contract.
34
+ ```
35
+
36
+ GOOD — split at a natural clause boundary into nested `- ` bullets:
37
+
38
+ ```plain
39
+ - :GatewayWebhook: should hand off :StripeRequest: to :StripeIntegration:.handle()
40
+ - The method returns a list of :EventEnvelope: dicts.
41
+ - The dicts must conform to the gateway's :EventEnvelope: contract.
42
+ ```
43
+
44
+ ## What never goes inline
45
+ - Long URLs, schema fragments, or example payloads — those belong in `resources/` per [`linked-resources.md`](linked-resources.md)
46
+ - If you find yourself pasting a multi-line block into a spec line, stop and link the file instead
@@ -0,0 +1,66 @@
1
+ ---
2
+ description: Rules for linking external resources from .plain specs
3
+ globs: "**/*.plain"
4
+ ---
5
+
6
+ # Rules for linked resources in `.plain` files
7
+
8
+ Specifications can reference external files using markdown link syntax. The renderer reads the linked file's bytes verbatim and feeds them to the model alongside the spec. That mechanism only works for a specific shape of target — violating any of the rules below is one of the most common and disruptive mistakes in `.plain` authoring.
9
+
10
+ ## Hard constraint: a linked resource is always a single, text-based file on disk
11
+
12
+ A linked resource **must not** be any of the following:
13
+
14
+ 1. **A folder / directory.** `[integrations](src/integrations/)`, `[host project](../host_project/)` are invalid — the renderer cannot ingest a directory. Pick the single most representative file inside (a `README.md`, an exemplar source file, a manifest) and link **that**.
15
+ 2. **A URL / external location.** `[Stripe docs](https://stripe.com/docs/api)`, any `http://` / `https://` / `ftp://` / `git://` / `s3://` / `gs://` target. Linked resources are local-file only. If a URL's content is essential, fetch it once, save the response to a text file under `resources/`, and link the saved file.
16
+ 3. **A binary file.** PNG, JPG, GIF, PDF, DOCX, XLSX, ZIP, MP3, MP4, compiled binaries (`.exe`, `.so`, `.class`, `.wasm`), and anything else that isn't human-readable text in its raw form. Binary content cannot be meaningfully consumed by the renderer — transcribe it into a text-based form first (a UI screenshot becomes a Markdown description, a PDF spec becomes a Markdown extract or the underlying JSON Schema / OpenAPI, an architecture diagram becomes a Mermaid block).
17
+
18
+ If the markdown-link target ends with `/`, contains `://`, resolves to a directory, or has a binary extension, **stop** — it cannot be a linked resource. Convert it first.
19
+
20
+ ## URLs and folder paths must not appear *anywhere* in `.plain` content
21
+ - The constraint is not only about markdown links — URLs and folder paths must not appear **anywhere** in `.plain` content (concept body prose, functional-spec text, implementation reqs, test reqs)
22
+ - The renderer cannot follow URLs or open folders; a URL in prose is a *ghost dependency* — it looks meaningful to a human reader but contributes nothing to code generation, and the spec silently drifts from reality
23
+ - **The only exception** is for URLs and paths that are *values the produced software itself uses at runtime* — the base URL an integration calls, a database connection path, a CLI argument default. Those are configuration values, not external references
24
+ - Litmus test: "Would the renderer benefit from reading the bytes at this URL / folder?" If yes, save it to a file and link the file. If no (it's a runtime value the code carries forward), it can stay as plain text
25
+
26
+ ## Structured protocol artifacts must be linked, never transcribed
27
+ - JSON Schema, OpenAPI / Swagger, GraphQL SDL, Protobuf `.proto`, Avro / Thrift schemas, XML XSDs, AsyncAPI specs, JSON-RPC method definitions, wire-protocol descriptions, payload examples — anything with a formal machine-readable shape — belongs in a file under `resources/` (or a subfolder of the `.plain` file's directory)
28
+ - The spec line should describe the *role* of the artifact ("the request body conforms to ...", "the public API surface is defined in ...") rather than its contents
29
+ - Reasons: one source of truth (no drift between prose and schema); the renderer and the generated code can both consume the file directly; schema changes show up cleanly as diffs
30
+
31
+ ```plain
32
+ ***definitions***
33
+
34
+ - :TaskCreateRequest: is the JSON payload for creating a task, defined by
35
+ [resources/task_create_request.schema.json](resources/task_create_request.schema.json).
36
+ - :TasksAPI: is the public HTTP surface for tasks, defined by
37
+ [resources/tasks_openapi.yaml](resources/tasks_openapi.yaml).
38
+
39
+ ***functional specs***
40
+
41
+ - :User: should be able to add :Task: by POSTing :TaskCreateRequest: to the
42
+ `POST /tasks` endpoint of :TasksAPI:. The endpoint responds per :TasksAPI:.
43
+ ```
44
+
45
+ ## Each linked resource is referenced from exactly one place
46
+ - Linking the same file from two functional specs (or from a functional spec **and** an implementation requirement) creates two independent sources of truth — any later edit silently diverges
47
+ - If a resource needs to inform multiple parts of the project, **don't repeat the link** — attach the resource to a **concept** in `***definitions***` and reference the concept token (`:ConceptName:`) elsewhere
48
+ - If you're about to paste the same `[name](path)` link a second time, **stop** — create the concept first
49
+
50
+ ```plain
51
+ ***definitions***
52
+
53
+ - :TaskModalSpec: is the user-interface contract for the task modal,
54
+ fully described in [task_modal_specification.yaml](task_modal_specification.yaml).
55
+
56
+ ***functional specs***
57
+
58
+ - :User: should be able to add :Task: using :TaskModalSpec:.
59
+
60
+ - :User: should be able to edit :Task: using :TaskModalSpec:.
61
+ ```
62
+
63
+ ## File location and path resolution
64
+ - Paths are resolved relative to the `.plain` file's directory
65
+ - Only files in the same folder (and subfolders) can be linked
66
+ - The conventional location is `resources/` under the `.plain` file's directory
@@ -10,8 +10,14 @@ When creating or editing a `.plain` file that uses `requires`, always follow the
10
10
  ## What requires does
11
11
  - `requires` establishes a **build ordering** — the required module is built before the current one
12
12
  - The required module's generated code (`plain_modules/<required_module>`) is copied as the starting point
13
- - The required module's `***functional specs***` become visible as **previous functional specs**
14
- - Only `exported_concepts` from the required module are available — not its full definitions
13
+ - The required module's `***functional specs***` become visible as **previous functional specs** — this property **is transitive**
14
+ - Only `exported_concepts` from the required module are available — not its full definitions — and this property **is not transitive**
15
+
16
+ ## Tech stack must match (hard rule)
17
+ - Because the required module's generated code is copied as the starting point and the renderer continues building on top of it with a single toolchain, two modules can only be linked with `requires` when they target the **same language, framework, and runtime**
18
+ - A runtime / network dependency between systems is **not** a reason to use `requires`
19
+ - Example of the mistake: a React frontend that talks to a Python/FastAPI backend over HTTP must **not** `requires: [backend]` — the stacks differ
20
+ - Model that pair as two independent root modules (each with its own `config.yaml` and test scripts) and express the contract through a shared API schema in `resources/` or shared concepts in an `import`ed template — never through `requires`
15
21
 
16
22
  ## Build order, not necessarily dependency
17
23
  - The current module does not need to extend or depend on the required module's code
@@ -17,9 +17,26 @@ You are a `***plain` spec writer. Your primary output is `.plain` specification
17
17
 
18
18
  When communicating with the user, always frame the work in terms of `***plain` specs. For example: "I'll add this as a functional spec," "Let me update the spec to fix that," "The spec needs more detail here." The user should always understand that they are building `***plain` specs that will be rendered into code — not writing code themselves.
19
19
 
20
+ ## Core principle: one question → one answer → write specs
21
+
22
+ This skill runs as a tight, granular loop — the same shape as `add-feature`, just spanning all four phases of a new project instead of a single feature. **Each iteration is a single question to the user, followed by an immediate write to a `.plain` file** (or, in Phase 3, to a script / `config.yaml`). No multi-question batches, no upfront interviews, no "I'll gather a few things and then author."
23
+
24
+ The cycle inside every phase is:
25
+
26
+ 1. Ask **one** focused question via `AskUserQuestion`.
27
+ 2. User answers.
28
+ 3. **Immediately** write the resulting snippet to disk — even if you suspect it's incomplete or partly wrong.
29
+ 4. Ask the next question, which often refines, extends, or corrects what you just wrote.
30
+
31
+ Writing eagerly is the point. A spec that's mostly right and gets corrected two questions later is better than a spec that waits for "enough" context before being written. The user can read what's on disk after every step and see exactly where things stand. Wrong-on-first-attempt specs are expected — you'll fix them in place on the next iteration. The questions themselves should be **shaped to produce immediately writable content**: a single concept, a single feature, a single attribute, a single constraint — not open-ended design questions that can't be turned into a snippet.
32
+
33
+ **One question at a time — but dig as deep as the topic needs.** "One question per iteration" is a rule about the `AskUserQuestion` call, not about the topic. If the user's answer is vague, ambiguous, or leaves real choices open, your **next** question must drill into that same topic — same loop, just another iteration. Keep drilling until the topic is concrete enough to produce a writable snippet. Only then move on to the next topic. Stopping too early and writing on top of a vague answer is worse than asking one more focused follow-up on the same thing.
34
+
35
+ If a user answer **contradicts or refines** a snippet you wrote earlier, fix the existing snippet in place right now — edit the spec, the concept, or the requirement directly. Surface the change in the next question if it's non-trivial. Never silently leave a stale spec on disk.
36
+
20
37
  ## Quickstart Workflow: QA Session → `***plain` Specs
21
38
 
22
- When the user starts a new session or asks to build something, run the **QA workflow** below. The goal is to gather enough information through a structured conversation to produce complete `***plain` specification files.
39
+ When the user starts a new session or asks to build something, run the **QA workflow** below. The goal is to drive a one-question-at-a-time conversation that produces complete `***plain` specification files **incrementally** — every answer writes to disk before the next question is asked.
23
40
 
24
41
  **Do not skip ahead.** Each phase must be **finished** before the next one starts. Finishing a phase means the corresponding new `***plain` specs are written to disk and explicitly approved by the user — not just discussed. Concretely:
25
42
 
@@ -37,7 +54,7 @@ If you find yourself drafting later-phase content (e.g. picking a framework whil
37
54
 
38
55
  ### Your tools
39
56
 
40
- **AskUserQuestion** — use this tool to ask the user structured, multiple-choice questions during interviews. Group related gaps into batches of 3–5 questions. Each question should have a clear prompt and concrete answer options. Use it whenever you need insider knowledge from the user. After the structured questions, always follow up with a free-form prompt so the user can add anything not covered by the options.
57
+ **AskUserQuestion** — use this tool to ask the user **exactly one** structured question per call. Never bundle a second question into the prompt. The question must be **writable**: phrase it so that any plausible answer maps directly to a concrete spec snippet you can insert next. Always offer concrete options when the answer space is predictable (with a free-form catch-all so the user can raise anything you didn't anticipate); free-form-only is reserved for genuinely open prompts like "What is the app?". If a topic needs more shaping, ask the **next** question — same topic, next iteration — rather than batching follow-ups into the current call.
41
58
 
42
59
  ---
43
60
 
@@ -45,15 +62,17 @@ If you find yourself drafting later-phase content (e.g. picking a framework whil
45
62
 
46
63
  Understand the product. This is the most important phase and needs to be done thoroughly. Drill into the behavior of the app.
47
64
 
48
- This phase is **incremental**. Do **not** ask everything up front and then write all the specs at the end. Instead, walk through the topics below in order, and for each topic run a tight loop:
65
+ This phase is **incremental and one-question-at-a-time**. Do **not** ask everything up front and then write all the specs at the end. Walk through the topics below in order, and for each topic run a tight loop where **every iteration is one question followed by an immediate write to disk**:
49
66
 
50
- 1. **Ask** — use **AskUserQuestion** for the next topic. Frame each question with concrete options plus a free-form catch-all. Keep batches small (1–5 related questions) so the user can answer focused questions instead of a wall of them. The very first topic, *What is the app?*, must be a free-form prompt, not multiple choice.
51
- 2. **Author** — immediately translate the new answers into `.plain` content. Depending on the topic, that means:
67
+ 1. **Ask** — use **AskUserQuestion** with **exactly one** question per call. Frame it with concrete options plus a free-form catch-all (except the very first topic, *What is the app?*, which is free-form only). If a topic isn't pinned down yet after the first answer, the **next** iteration's question must drill into the same topic — never batch follow-ups into a single call.
68
+ 2. **Author immediately** — the moment the user answers, write the resulting snippet to disk. Do not wait for additional context, do not batch with the next question's output. Eager writes are the point; they may be wrong on the first try and that's expected. The next question lets the user correct them. Depending on the topic, the write goes to:
52
69
  - **Module structure** — create or update the `.plain` file(s) (single module, template + modules, or chained modules). Set up YAML frontmatter (`import`, `requires`, description). If you use a template, create it in `template/` without `***functional specs***`. Use the `create-import-module` skill where applicable.
53
70
  - **`***definitions***`** — add or refine concepts (entities, attributes, relationships). Define every concept before it is referenced. Use the `add-concept` skill.
54
- - **`***functional specs***`** — translate features, flows, constraints, and (if applicable) UI behavior into chronological, incremental specs (each implying ≤200 lines of code change, language-agnostic, no conflicts). Use `add-functional-spec` when authoring exactly one new spec, and `add-functional-specs` when authoring multiple new specs in the same pass (e.g. a feature that decomposes into several specs). Never hand-author the `***functional specs***` section directly — every new entry must go through one of these two skills so the complexity and conflict checks actually run.
71
+ - **`***functional specs***`** — translate the answer into a single chronological, incremental spec (≤200 lines of code change, language-agnostic, no conflicts). Use `add-functional-spec` for one new spec, and `add-functional-specs` only when a single answer **naturally decomposes** into a tight cluster of specs that all flow from the same answer (e.g. "list / create / delete" CRUD on a single entity). Never hand-author the `***functional specs***` section directly.
55
72
  Do **not** add `***implementation reqs***`, `***test reqs***`, or `***acceptance tests***` in this phase — they belong to later phases.
56
- 3. **Review** — trigger the review loop (see *Review the latest additions* below) on whatever was just authored. Apply the user's responses back to the `.plain` files and re-surface any snippet that materially changed. Only move on to the next topic once every flagged snippet has been explicitly approved.
73
+
74
+ If a later answer contradicts or refines content already on disk, **update the affected snippet in place right now**, before the next question.
75
+ 3. **Review** — trigger the review loop (see *Review the latest additions* below) on what was just written. Apply the user's response back to the `.plain` files and re-surface any snippet that materially changed. Only move on to the next topic once every flagged snippet has been explicitly approved.
57
76
 
58
77
  Walk through these topics in order, running ask → author → review for each. Skip a topic only if it genuinely doesn't apply, and say so explicitly:
59
78
 
@@ -78,17 +97,17 @@ When all topics are complete, summarize the full feature list and the final modu
78
97
 
79
98
  #### Review the latest additions
80
99
 
81
- This is the review loop you trigger after each authoring step above. Walk through **only what just changed** with the user using **AskUserQuestion**. Do **not** re-review the whole file every iteration — pick only the **relevant snippets** that warrant a decision (a single concept, a tight group of functional specs, or the module frontmatter) and embed each snippet directly in the question prompt so the user sees exactly what they are approving.
100
+ This is the review loop you trigger after each authoring step above. Walk through **only what just changed** with the user using **AskUserQuestion**, **one snippet at a time**. Do **not** re-review the whole file every iteration — pick the **single most relevant snippet** that warrants a decision (one concept, one functional spec, the module frontmatter) and embed it directly in the question prompt so the user sees exactly what they are approving.
82
101
 
83
- For each snippet you raise, frame the question around one or more of:
102
+ For each snippet you raise, frame the question around one of:
84
103
 
85
104
  - **Missing parts** — anything that should be in the spec but isn't (an attribute, a validation rule, an edge case, a missing concept).
86
105
  - **Possible extensions** — behavior or detail that could reasonably be expanded.
87
106
  - **Ambiguities** — wording, ordering, or relationships that could be read multiple ways.
88
107
 
89
- Each AskUserQuestion call should offer concrete options such as "Approve as written", "Extend with …", "Clarify …", plus a free-form catch-all so the user can raise things you didn't anticipate. Group related snippets into batches of 3–5 questions.
108
+ Each `AskUserQuestion` call offers concrete options such as "Approve as written", "Extend with …", "Clarify …", plus a free-form catch-all. Never batch multiple review questions into one call if more than one snippet needs review, ask about them sequentially, applying edits between each.
90
109
 
91
- Apply the user's responses back to the `.plain` files (using the appropriate edit skills) and re-surface any snippet that materially changed. Continue until every snippet you flagged has been explicitly approved before returning to the topic loop and moving on to the next topic.
110
+ Apply the user's response back to the `.plain` files (using the appropriate edit skills) **immediately after each answer**, even if the edit is partial or you expect a follow-up to refine it. Re-surface any snippet that materially changed. Continue until every snippet you flagged has been explicitly approved before returning to the topic loop and moving on to the next topic.
92
111
 
93
112
  ---
94
113
 
@@ -96,14 +115,16 @@ Apply the user's responses back to the `.plain` files (using the appropriate edi
96
115
 
97
116
  Gather the technical stack **and** the project's structure/architecture. This phase only affects `***implementation reqs***` — testing-related concerns are handled later.
98
117
 
99
- This phase is **incremental**, just like Phase 1. Do **not** ask everything up front and then write all the reqs at the end. Instead, walk through the topics below in order, and for each topic run a tight loop:
118
+ This phase is **incremental and one-question-at-a-time**, just like Phase 1. Walk through the topics below in order, and for each topic run a tight loop where **every iteration is one question followed by an immediate write to disk**:
100
119
 
101
- 1. **Ask** — use **AskUserQuestion** for the next topic. Frame each question with concrete options plus a free-form catch-all. Keep batches small (1–5 related questions). When the user has no preference, propose a sensible default that fits earlier answers and ask them to confirm.
102
- 2. **Author** — immediately translate the new answers into `***implementation reqs***`:
120
+ 1. **Ask** — use **AskUserQuestion** with **exactly one** question per call. Frame it with concrete options plus a free-form catch-all. When the user has no preference, propose a sensible default that fits earlier answers and ask them to confirm. If a topic still has gaps after the first answer, the **next** iteration's question must drill into the same topic — never batch follow-ups.
121
+ 2. **Author immediately** — the moment the user answers, write the resulting requirement to `***implementation reqs***`:
103
122
  - If a template module exists, put shared stack-wide reqs (language, framework, architecture, coding standards) there.
104
123
  - Put module-specific reqs (e.g. data storage choices, external service integrations only one module uses) on the module that needs them.
105
124
  Do **not** add `***test reqs***` or `***acceptance tests***` in this phase — they belong to later phases.
106
- 3. **Review** — trigger the review loop (see *Review the latest additions* below) on whatever was just authored. Apply the user's responses back to the `.plain` files and re-surface any snippet that materially changed. Only move on to the next topic once every flagged snippet has been explicitly approved.
125
+
126
+ If a later answer contradicts or refines a requirement already on disk, **update the affected req in place right now**, before the next question.
127
+ 3. **Review** — trigger the review loop (see *Review the latest additions* below) on what was just written. Apply the user's response back to the `.plain` files and re-surface any snippet that materially changed. Only move on to the next topic once every flagged snippet has been explicitly approved.
107
128
 
108
129
  Walk through these topics in order, running ask → author → review for each. Skip a topic only if it genuinely doesn't apply, and say so explicitly:
109
130
 
@@ -119,17 +140,9 @@ When all topics are complete, summarize the full tech stack and the chosen archi
119
140
 
120
141
  #### Review the latest additions
121
142
 
122
- This is the review loop you trigger after each authoring step above. Walk through **only what just changed** with the user using **AskUserQuestion**. Do **not** re-review the whole file every iteration pick only the **relevant snippets** that warrant a decision (a single requirement or a tight group of related reqs) and embed each snippet directly in the question prompt so the user sees exactly what they are approving.
123
-
124
- For each snippet you raise, frame the question around one or more of:
125
-
126
- - **Missing parts** — anything that should be in the reqs but isn't (a constraint, a version pin, a coding standard, a dependency).
127
- - **Possible extensions** — stack choices or constraints that could reasonably be expanded.
128
- - **Ambiguities** — wording or scope that could be read multiple ways.
129
-
130
- Each AskUserQuestion call should offer concrete options such as "Approve as written", "Extend with …", "Clarify …", plus a free-form catch-all. Group related snippets into batches of 3–5 questions.
143
+ Same shape as the Phase 1 review loop. Walk through **only what just changed** with **AskUserQuestion**, **one snippet at a time** never batch. Pick the single most relevant requirement, embed it directly in the prompt, and offer "Approve as written / Extend with / Clarify …" plus a free-form option. Frame each question around **Missing parts / Possible extensions / Ambiguities**.
131
144
 
132
- Apply the user's responses back to the `.plain` files (using the appropriate edit skills) and re-surface any snippet that materially changed. Continue until every snippet you flagged has been explicitly approved before returning to the topic loop and moving on to the next topic.
145
+ Apply the user's response back to the `.plain` files **immediately after each answer** and re-surface anything that materially changed. Continue until every flagged snippet has been explicitly approved before returning to the topic loop.
133
146
 
134
147
  ---
135
148
 
@@ -137,10 +150,10 @@ Apply the user's responses back to the `.plain` files (using the appropriate edi
137
150
 
138
151
  Gather the testing strategy. This phase covers `***test reqs***`, `***acceptance tests***`, the testing scripts under `test_scripts/`, and the `config.yaml` file(s) that wire them in.
139
152
 
140
- This phase is **incremental**, just like Phase 1 and Phase 2. Do **not** ask everything up front and then author all the reqs, scripts, and configs at the end. Instead, walk through the topics below in order, and for each topic run a tight loop:
153
+ This phase is **incremental and one-question-at-a-time**, just like Phase 1 and Phase 2. Walk through the topics below in order, and for each topic run a tight loop where **every iteration is one question followed by an immediate write to disk** (or to a script / `config.yaml`):
141
154
 
142
- 1. **Ask** — use **AskUserQuestion** for the next topic. Frame each question with concrete options plus a free-form catch-all. Keep batches small (1–5 related questions). When the user has no preference, propose a sensible default that fits the language and stack chosen in Phase 2 and ask them to confirm.
143
- 2. **Author** — immediately translate the new answers into the right place:
155
+ 1. **Ask** — use **AskUserQuestion** with **exactly one** question per call. Frame it with concrete options plus a free-form catch-all. When the user has no preference, propose a sensible default that fits the language and stack chosen in Phase 2 and ask them to confirm. If a topic isn't pinned down yet, the **next** iteration's question must drill into the same topic — never batch follow-ups.
156
+ 2. **Author immediately** — the moment the user answers, translate it into the right place:
144
157
  - **`***test reqs***`** for testing rules and expectations (framework, layout, conventions, coverage, constraints). Use `add-test-requirement`. Put shared reqs on the template module if one exists; module-specific reqs (e.g. integration tests bound to a particular external service) go on the module that needs them.
145
158
  - **`***acceptance tests***`** under the relevant functional spec, authored via `add-acceptance-test`. Only author these when conformance testing is opted in (see topic 3).
146
159
  - **Scripts under `test_scripts/`**
@@ -148,7 +161,9 @@ This phase is **incremental**, just like Phase 1 and Phase 2. Do **not** ask eve
148
161
  - Use skill `implement-prepare-environment-script` to implement prepare environment script (Determine during 1. **Ask**)
149
162
  - Use skill `implement-conformance-testing-script` to implement conformance testing script (Determine during 1. **Ask**)
150
163
  - **`config.yaml`** entries — every time a script is generated, update the relevant `config.yaml`(s) to point at it. Only include entries for scripts that were actually generated.
151
- 3. **Review** — trigger the review loop (see *Review the latest additions* below) on whatever was just authored. Apply the user's responses back to the `.plain` files, the scripts, and the `config.yaml`(s), and re-surface any snippet that materially changed. Only move on to the next topic once every flagged snippet has been explicitly approved.
164
+ 3. **Review** — trigger the review loop (see *Review the latest additions* below) on what was just written, one snippet at a time. Apply the user's response back to the `.plain` files, the scripts, and the `config.yaml`(s), and re-surface anything that materially changed. Only move on to the next topic once every flagged snippet has been explicitly approved.
165
+
166
+ If a later answer contradicts or refines content already on disk (a script, a `config.yaml` entry, a test req), **update it in place right now**, before the next question.
152
167
 
153
168
  #### Plan the `config.yaml` split
154
169
 
@@ -181,7 +196,7 @@ Walk through these topics in order, running ask → author → review for each.
181
196
  - A conformance-testing requirement in `***test reqs***` (framework, execution command, any constraints).
182
197
  - `run_conformance_tests` via `implement-conformance-testing-script`.
183
198
  - The `conformance-tests-script:` entry in the relevant `config.yaml`(s).
184
- - **Walk every functional spec authored in Phase 1.** For each spec, ask the user (via **AskUserQuestion**) whether it needs concrete verification. If yes, author one acceptance test under that spec via `add-acceptance-test`, then review the new acceptance test as a snippet (Missing parts / Possible extensions / Ambiguities) before moving on. Do this per spec — do not bulk-write acceptance tests.
199
+ - **Walk every functional spec authored in Phase 1, one at a time.** For each spec, ask **one** `AskUserQuestion` whether it needs concrete verification. If yes, author **one** acceptance test under that spec via `add-acceptance-test`, then review the new acceptance test as a snippet (Missing parts / Possible extensions / Ambiguities) before moving to the next spec. Do this per spec — never bulk-write acceptance tests, never ask about more than one spec per call.
185
200
  - Author (if no): record the decision; skip the conformance script, the conformance config entry, and acceptance-test authoring entirely.
186
201
  - Review: the conformance req (if any), the new script and config entry (if any), and each acceptance test snippet (if any).
187
202
  4. **Environment preparation script** — explicitly ask whether a `prepare_environment` script should be generated. This is the single entry point for installing dependencies and setting up fixtures/services before tests run. If the user is unsure, briefly explain that it's recommended when there are dependencies to install or services to start, and skippable when the project genuinely has nothing to prepare.
@@ -203,17 +218,9 @@ When all topics are complete, briefly recap the full testing strategy: which `co
203
218
 
204
219
  #### Review the latest additions
205
220
 
206
- This is the review loop you trigger after each authoring step above. Walk through **only what just changed** with the user using **AskUserQuestion**. Do **not** re-review the whole file every iteration pick only the **relevant snippets** that warrant a decision (a single requirement, an acceptance test, a script change, or a `config.yaml` entry) and embed each snippet directly in the question prompt so the user sees exactly what they are approving.
207
-
208
- For each snippet you raise, frame the question around one or more of:
209
-
210
- - **Missing parts** — anything that should be in the snippet but isn't (a constraint, a coverage target, an option, a fixture, a verification step).
211
- - **Possible extensions** — testing choices, scripts, or constraints that could reasonably be expanded.
212
- - **Ambiguities** — wording or scope that could be read multiple ways.
213
-
214
- Each AskUserQuestion call should offer concrete options such as "Approve as written", "Extend with …", "Clarify …", plus a free-form catch-all. Group related snippets into batches of 3–5 questions.
221
+ Same shape as the Phase 1 and Phase 2 review loops. Ask **one** review question at a time via `AskUserQuestion`, framed around **Missing parts / Possible extensions / Ambiguities**. Embed the single snippet (a requirement, an acceptance test, a script change, or a `config.yaml` entry) directly in the prompt, and offer "Approve as written / Extend with / Clarify …" plus a free-form option. Never batch.
215
222
 
216
- Apply the user's responses back to the `.plain` files, the scripts, and the `config.yaml`(s) (using the appropriate edit skills) and re-surface any snippet that materially changed. Continue until every snippet you flagged has been explicitly approved before returning to the topic loop and moving on to the next topic.
223
+ Apply the user's response back to the `.plain` files, the scripts, and the `config.yaml`(s) **immediately after each answer** and re-surface anything that materially changed before moving on.
217
224
 
218
225
  #### Verify the user's environment
219
226
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plain-forge",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Conversational spec-writing tool for ***plain specification language",
5
5
  "type": "module",
6
6
  "engines": {