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.
- package/bin/cli.mjs +86 -3
- package/forge/rules/definitions.md +16 -0
- package/forge/rules/func-specs.md +8 -1
- package/forge/rules/impl-reqs.md +8 -1
- package/forge/rules/integration-embedded.md +149 -0
- package/forge/rules/integration-standalone.md +134 -0
- package/forge/rules/integrations.md +91 -0
- package/forge/rules/line-length.md +46 -0
- package/forge/rules/linked-resources.md +66 -0
- package/forge/rules/requires-modules.md +8 -2
- package/forge/skills/forge-plain/SKILL.md +47 -40
- package/package.json +1 -1
- package/forge/skills/forge-integration/SKILL.md +0 -443
|
@@ -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
|
|
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
|
|
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.
|
|
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**
|
|
51
|
-
2. **Author** —
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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**
|
|
102
|
-
2. **Author** —
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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**
|
|
143
|
-
2. **Author** —
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|