@turri-dev/cli 0.1.16-next.b861614 → 0.1.16-next.ce2cd46

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 (54) hide show
  1. package/.pi/themes/turri-dark.json +1 -1
  2. package/dist/extension.js +2 -1
  3. package/dist/init-config.d.ts +1 -1
  4. package/dist/init-config.js +1 -1
  5. package/dist/loop-tools.js +1 -1
  6. package/dist/regenerate/cases.js +2 -2
  7. package/dist/regenerate/change-view.js +5 -3
  8. package/dist/regenerate/conform.js +0 -2
  9. package/dist/regenerate/delivery.d.ts +1 -5
  10. package/dist/regenerate/delivery.js +2 -9
  11. package/dist/regenerate/loop.js +1 -2
  12. package/dist/regenerate/regenerate.js +27 -9
  13. package/dist/regenerate/release.d.ts +3 -7
  14. package/dist/regenerate/release.js +59 -15
  15. package/dist/regenerate/testing.d.ts +7 -0
  16. package/dist/regenerate/testing.js +14 -0
  17. package/dist/regenerate-cli.js +1 -1
  18. package/dist/release-agent.d.ts +1 -1
  19. package/dist/release-agent.js +3 -3
  20. package/dist/release-tools.js +2 -1
  21. package/dist/skill-progress.d.ts +1 -1
  22. package/docs/authoring-plain.md +2 -2
  23. package/docs/config.md +1 -1
  24. package/docs/deploy.md +4 -6
  25. package/docs/hosting.md +1 -1
  26. package/docs/regenerating.md +3 -3
  27. package/docs/using.md +2 -2
  28. package/genome/rules/func-specs.md +30 -0
  29. package/genome/rules/impl-reqs.md +1 -1
  30. package/genome/rules/integration-embedded-testing.md +1 -1
  31. package/genome/rules/integration-embedded.md +1 -1
  32. package/genome/rules/integration-standalone.md +1 -1
  33. package/genome/rules/linked-resources.md +4 -0
  34. package/genome/rules/project-model.md +1 -1
  35. package/genome/rules/test-reqs.md +1 -1
  36. package/genome/rules/turri-regeneration.md +1 -1
  37. package/genome/skills/analyze-if-func-spec-too-complex/SKILL.md +5 -5
  38. package/genome/skills/break-down-func-spec/SKILL.md +1 -1
  39. package/genome/skills/brood/references/product.md +2 -2
  40. package/genome/skills/bud/SKILL.md +4 -4
  41. package/genome/skills/debug-specs/SKILL.md +6 -6
  42. package/genome/skills/mature/SKILL.md +1 -1
  43. package/genome/skills/resolve-section-ownership/SKILL.md +4 -4
  44. package/genome/skills/resolve-spec-conflict/SKILL.md +3 -3
  45. package/genome/skills/spawn/SKILL.md +2 -2
  46. package/package.json +1 -1
  47. package/genome/skills/add-acceptance-test/SKILL.md +0 -100
  48. package/genome/skills/add-concept/SKILL.md +0 -71
  49. package/genome/skills/add-functional-spec/SKILL.md +0 -93
  50. package/genome/skills/add-functional-specs/SKILL.md +0 -128
  51. package/genome/skills/add-implementation-requirement/SKILL.md +0 -85
  52. package/genome/skills/add-resource/SKILL.md +0 -105
  53. package/genome/skills/add-template/SKILL.md +0 -64
  54. package/genome/skills/add-test-requirement/SKILL.md +0 -73
@@ -148,7 +148,7 @@ Every time a review sends tests back, the agent that fixes them also leaves the
148
148
 
149
149
  ### Then
150
150
 
151
- Once the unit tests pass and are reviewed, the job lands: the code record becomes the \*\*\*plain description the job ends on, and a commit is made to the module's history. The conformance tests are not run here: they are the conformance track's, and its job for what this one built runs next, before anything is built on it (see [conformance tests in the work loop](#conformance-tests-in-the-work-loop)). A job that does not pass is undone instead - see [below](#what-the-code-is-built-from). A job that lands ends its report with the offer to try it - "Want to try it? Just ask me" in the chat, `turri release <spec>` on the command line - and trying it is [deploy](deploy.md)'s, not the job's. Conformance jobs that land make the same offer.
151
+ Once the unit tests pass and are reviewed, the job lands: the code record becomes the \*\*\*plain description the job ends on, and a commit is made to the module's history. The conformance tests are not run here: they are the conformance track's, and its job for what this one built runs next, before anything is built on it (see [conformance tests in the work loop](#conformance-tests-in-the-work-loop)). A job that does not pass is undone instead - see [below](#what-the-code-is-built-from). Trying what it built is [deploy](deploy.md)'s, not the job's: on the command line, a run that landed ends with `turri release <spec>`.
152
152
 
153
153
  ## A whole module
154
154
 
@@ -276,14 +276,14 @@ Every job is a \*\*\*plain diff: the agent that regenerates it is given the \*\*
276
276
 
277
277
  **Every part of \*\*\*plain is given with its module.** A codebase is built from its whole requires chain's \*\*\*plain, and each module numbers its functional specs from 1, so every agent is shown each section grouped under the module each item belongs to - `<module name="base">`, then `<module name="app" role="current">` - as `<already implemented>` groups the functional specs (`moduleSection`, `functionalitiesByModule` in `prompt.ts`). A module's own items, and what it imports, are the current module's. `<spec change>` names a functional spec as "functionality 2 of module `app`", and a definition or req of a module below with its module; each case line does too ("fs 2 of module `app`"). The primer every agent reads first says that modules are how [\*\*\*plain](https://plainlang.org/docs/) is written, not how the code is laid out: the agent works only in the current module's codebase, which holds the code of every module it requires, and organises the code as the implementation reqs say.
278
278
 
279
- It is told, too, what to do with each functional spec the job touches, by its case (`src/regenerate/cases.ts`): a fresh project is set up first, with its unit tests where the unit testing script runs them; a new functional spec is built and unit tested; a changed one - its text, or a concept it uses - is changed in place, its code and tests to match, never built again from scratch; one regenerated again is replaced, not patched - rewritten or started over, what it replaces taken out; one taken out has its code and the tests only it had removed. A job holding several cases has a line for each. A job that touches no functional spec - implementation reqs, or definitions none uses - is mechanical: the code adapts, no new test is written, and an existing one may change only mechanically, never what it asserts. The unit test review holds each part to its case, and a mechanical job only to its reqs and to no test removed or weakened. A conformance job's agent and its reviewer are told the same, for the tests:
279
+ It is told, too, what to do with each functional spec the job touches, by its case (`src/regenerate/cases.ts`): a fresh project is set up first, with its unit tests where the unit testing script runs them; a new functional spec is built and unit tested; a changed one - its text, or a concept it uses - is changed in place, its code and tests to match, never built again from scratch; one regenerated again is built anew, not patched - its implementation taken out and built again, even where the old code already does what \*\*\*plain says, what it replaces taken out; one taken out has its code and the tests only it had removed. A job holding several cases has a line for each. A job that touches no functional spec - implementation reqs, or definitions none uses - is mechanical: the code adapts, no new test is written, and an existing one may change only mechanically, never what it asserts. The unit test review holds each part to its case, and a mechanical job only to its reqs and to no test removed or weakened. A conformance job's agent and its reviewer are told the same, for the tests:
280
280
 
281
281
  | case | when | code | conformance |
282
282
  | --- | --- | --- | --- |
283
283
  | fresh | the module requires none and nothing is built | set up the project and its unit tests where the unit testing script runs them, then build | set up `tests/` so the conformance testing script, which brings the tests together with `code/`, runs them, then write |
284
284
  | add | a functional spec is new | build it and write its unit tests | write its tests |
285
285
  | patch | its text changed, or a concept it uses did | change the existing code and tests to match - never build it again from scratch | rewrite its existing tests to match |
286
- | again | `regenerate` named it: it is built, and marked in the code record to be regenerated again | replace its implementation - rewrite it or start it over, doing what \*\*\*plain says now; no second implementation beside the old, nothing of it left unused; its unit tests may be rewritten | its tests were written against the code it replaced: run against the new code, what they check that \*\*\*plain says stays checked, and what they check that \*\*\*plain leaves open - a path, a field, a message the old code chose - is rewritten to what the new code does, or taken out |
286
+ | again | `regenerate` named it: it is built, and marked in the code record to be regenerated again | take its implementation out and build it anew, doing what \*\*\*plain says now - the old code already doing it is no reason to keep it; no second implementation beside the old, nothing of it left unused; its unit tests written anew. A coding agent that writes nothing is sent back twice to build it anew, and then the pulse does not land | its tests were written against the code it replaced: run against the new code, what they check that \*\*\*plain says stays checked, and what they check that \*\*\*plain leaves open - a path, a field, a message the old code chose - is rewritten to what the new code does, or taken out |
287
287
  | delete | a functional spec is gone | take out its code and the tests only it had | take out its tests |
288
288
  | mechanical | no functional spec is touched - only reqs, or definitions none uses | adapt the code; write no new test; an existing one may change only mechanically - an import, a fixture, its setup - never what it asserts | the same, for test reqs, definitions or implementation reqs alone |
289
289
 
package/docs/using.md CHANGED
@@ -21,7 +21,7 @@ Three skills you start yourself, by their commands or by picking them when turri
21
21
 
22
22
  Peeking is safe while a question is open - a skill's or the chat's: `ctrl+h` opens the side panel over the question, which waits under it as it was - the panel says `your question is waiting`, and `ctrl+h` or `esc` takes you back to answer it. (The question has the keys, so turri catches `ctrl+h` itself while one is open.) The dialog holds the question alone - no hint and no invitation; the `ctrl+h` under the job panel breathes until it is first pressed.
23
23
 
24
- While a skill runs, a line above the input shows its phases, every one by name - those done ticked, the one it is in marked, the rest to come - and where it is: the skill's name at the left edge, `phase 2 of 4` at the right, and its phases centred between them, `✓ intent ━━━━ ⠋ stack ──── ○ testing ──── ○ product`. Under it, dimmed, the phase it is in and what it does: `stack - the language, frameworks, storage and architecture`. The phases are the skill's own steps, read from its `SKILL.md`. A skill of one phase, or none, has nothing to be partway through: its line is the spinner and its name alone, `⠹ add-test-requirement`.
24
+ While a skill runs, a line above the input shows its phases, every one by name - those done ticked, the one it is in marked, the rest to come - and where it is: the skill's name at the left edge, `phase 2 of 4` at the right, and its phases centred between them, `✓ intent ━━━━ ⠋ stack ──── ○ testing ──── ○ product`. Under it, dimmed, the phase it is in and what it does: `stack - the language, frameworks, storage and architecture`. The phases are the skill's own steps, read from its `SKILL.md`. A skill of one phase, or none, has nothing to be partway through: its line is the spinner and its name alone, `⠹ analyze-func-specs`.
25
25
 
26
26
  `genome/skills/` holds the rest: adding a feature, a concept, a requirement, a resource; splitting a functional spec that is too big; resolving conflicts; checking the environment - see [authoring \*\*\*plain](authoring-plain.md#the-skills). A skill run that is interrupted can be resumed where it stopped. A project can have skills of its own, in `.turri/skills/` or `.agents/skills/` - see [skills and gates](skills-and-gates.md#a-projects-own-skills).
27
27
 
@@ -29,7 +29,7 @@ While a skill runs, a line above the input shows its phases, every one by name -
29
29
 
30
30
  | tool | |
31
31
  | --- | --- |
32
- | `regenerate` | regenerate a module and its chain from \*\*\*plain as it is now - after any change to it, by any means: what is left to regenerate is planned into pulses of one to three functional specs, each with the definitions and reqs it uses, and a pulse regenerating what \*\*\*plain no longer wants is stopped. With functionalities named, those are regenerated though their \*\*\*plain did not change - rewritten or started over, planned into pulses as any change is; with `from_scratch`, the whole module, its code deleted first - `"chain"` for every module of its requires chain too, built again from the bottom - only when you ask, or agree |
32
+ | `regenerate` | regenerate a module and its chain from \*\*\*plain as it is now - after any change to it, by any means: what is left to regenerate is planned into pulses of one to three functional specs, each with the definitions and reqs it uses, and a pulse regenerating what \*\*\*plain no longer wants is stopped. With functionalities named, those are regenerated though their \*\*\*plain did not change - their code taken out and built anew, planned into pulses as any change is; with `from_scratch`, the whole module, its code deleted first - `"chain"` for every module of its requires chain too, built again from the bottom - only when you ask, or agree |
33
33
  | `drift` | what is left to regenerate: how far the code and its conformance tests have drifted from \*\*\*plain, starting nothing |
34
34
  | `glimpse` | the pulse a module's codebases would start next, and the whole prompt its coding agent would get - starting nothing |
35
35
  | `steer` | say how the work is planned - which functional specs go together, what first - for the project or one module, for the session; the next plan follows it, beside what AGENTS.md says under a heading naming the queue |
@@ -73,6 +73,22 @@ GOOD — statements of fact with concrete subjects:
73
73
  - Before adding, review all existing specs and verify compatibility
74
74
  - If ambiguity exists, add explicit detail to eliminate any conflicting interpretation
75
75
 
76
+ ## Adding a functional spec
77
+ Every new functional spec - one or a batch - is checked before it is written into the file:
78
+ 1. Draft it, then trim it per `concise-specs.md` to the shortest wording that keeps every fact
79
+ 2. Check its size with `analyze-if-func-spec-too-complex`; when it is too complex, split it with `break-down-func-spec` and check each part from step 1
80
+ 3. Check it for conflicts with **one** `analyze-func-specs` call over the new spec and every existing functional spec in the file and its `requires` chain - never pair by pair. Resolve each conflicting pair it reports with `resolve-spec-conflict`, then run it again over what changed until it is compatible
81
+ 4. Only then write it in, where it belongs (see Placement)
82
+
83
+ A batch is checked one spec at a time, in order: each spec's conflict check includes the specs of the batch already written in. Never write the whole batch in first and check it afterwards - a bad spec already in the file skews every later check. A few specs are no reason to skip a check.
84
+
85
+ ## Placement
86
+ Put a new spec where it fits the module as it reads, not at the end by default:
87
+ - **Below every spec it builds on** - each one whose behaviour it references or extends, and the first to use each concept it relies on
88
+ - **Above every spec that builds on it** - one that already assumes what it adds
89
+ - **Within those bounds, beside the specs of its feature** - usually straight after the last one it extends
90
+ - **At the end** only when it starts something new or fits nowhere better
91
+
76
92
  ## Language agnosticism
77
93
  - Write in terms of behavior, concepts, and domain logic
78
94
  - Avoid language-specific terminology: generics syntax, framework annotations, language-specific collection types, decorator syntax, base-class keywords, framings like "POJO" or "dataclass"
@@ -112,6 +128,20 @@ GOOD — statements of fact with concrete subjects:
112
128
  - Acceptance tests must describe concrete, verifiable outcomes — not vague qualities
113
129
  - Acceptance tests must not contradict, narrow, or extend beyond the parent spec
114
130
 
131
+ ```plain
132
+ Functional spec:
133
+ - :Resource: items are returned sorted by creation date in descending order.
134
+
135
+ Good - follows from the spec:
136
+ - After three :Resource: items are created one after another, listing them returns the last one created first.
137
+
138
+ Bad - contradicts it (the spec says descending):
139
+ - The first :Resource: listed is the oldest.
140
+
141
+ Bad - extends it (the spec says nothing about a limit):
142
+ - At most 50 :Resource: items are listed.
143
+ ```
144
+
115
145
  ## Format
116
146
 
117
147
  ```plain
@@ -15,7 +15,7 @@ When writing or editing an `***implementation reqs***` section in a `.plain` fil
15
15
  - **Everything** about `:UnitTests:` goes in `***implementation reqs***` — paths, approach, packages, framework, conventions, fixtures, mocking policy, file layout, naming, lint / static-analysis gates
16
16
  - `:UnitTests:` are part of the generated codebase (they sit inside `plain_modules/<module>/code/` alongside the implementation), so requirements that shape them are implementation reqs by definition
17
17
  - The unit-test generator reads **only** `***implementation reqs***` — anything about `:UnitTests:` placed elsewhere (e.g. `***test reqs***`) is silently ignored
18
- - Author each `:UnitTests:` requirement via `add-implementation-requirement` and phrase it in terms of `:UnitTests:` so the partition stays visible at a glance
18
+ - Phrase each `:UnitTests:` requirement in terms of `:UnitTests:` so the partition stays visible at a glance
19
19
 
20
20
  ## What belongs here
21
21
  - Technology choices: language, framework, runtime version
@@ -31,7 +31,7 @@ The two scripts are generated from facts in the integration's spec. For an embed
31
31
  - **Everything about `:UnitTests:`** — paths, approach, packages, framework, conventions, fixtures, mocking policy — lives in `***implementation reqs***`. Unit tests are part of the generated codebase, so requirements that shape them are implementation reqs (see [`impl-reqs.md`](impl-reqs.md))
32
32
  - **Everything about `:ConformanceTests:`** — paths, approach, packages, framework, execution command, pass criteria, mocking policy — lives in `***test reqs***`. Conformance tests are external to the generated codebase, so requirements that shape them are test reqs (see [`test-reqs.md`](test-reqs.md))
33
33
 
34
- Authors use `add-implementation-requirement` for the first group and `add-test-requirement` for the second. The two groups are parallel — each predefined concept owns a complete authoring story in its own section.
34
+ The first group follows `impl-reqs.md`, the second `test-reqs.md`. The two groups are parallel — each predefined concept owns a complete authoring story in its own section.
35
35
 
36
36
  ### In `***implementation reqs***` — everything about `:UnitTests:`
37
37
 
@@ -70,7 +70,7 @@ The integration's `.plain` module lives **inside the host codebase** (per the "a
70
70
 
71
71
  - Every host file the integration touches (base classes, configuration modules, registries, exception classes, lifecycle hooks) is referenced from the relevant spec using `***linked resource***` syntax with the **path as it exists in the host codebase** — e.g. `[base.py](host_project/integrations/base.py)` if the `.plain` module sits next to `host_project/`
72
72
  - **Do NOT copy host files into `resources/host/`.** A copy creates a second source of truth that drifts the moment the host file is edited; the rendered code will then disagree with whatever the host actually ships
73
- - **Do NOT add host files via the `add-resource` skill's default copy behavior** when that behavior would duplicate the file — point at the existing host path directly
73
+ - **Do NOT copy host files into `resources/`** when that would duplicate them — link the existing host path directly
74
74
  - **Never inline a host file's contents** into a spec
75
75
  - **Never describe a host symbol's shape from memory** — the renderer reads the linked file's bytes at its host path and that is the source of truth
76
76
  - This still obeys the broader [`linked-resources.md`](linked-resources.md) rules: a directory is not a valid link, a URL is not a valid link, a binary is not a valid link. Only the *location* changes — host files live where the host put them, not under `resources/`
@@ -101,7 +101,7 @@ Capture as a contract-version concept; pin the version in every published schema
101
101
 
102
102
  ## Testing — live conformance, secrets from env, webhooks
103
103
 
104
- `:ConformanceTests:` for a standalone integration **run against the live provider** (see [`integrations.md`](integrations.md) → *`:ConformanceTests:` always run against the live integration*). The testing strategy is captured as `***test reqs***` entries authored via `add-test-requirement`:
104
+ `:ConformanceTests:` for a standalone integration **run against the live provider** (see [`integrations.md`](integrations.md) → *`:ConformanceTests:` always run against the live integration*). The testing strategy is captured as `***test reqs***` entries (`test-reqs.md`):
105
105
 
106
106
  - **Conformance is live by default.** No VCR cassettes, no prerecorded responses for the calls under test, no mock servers. A green conformance run that never touched the provider proves nothing. Recorded responses may back unit tests — never conformance
107
107
  - **Secrets come from environment variables.** Pin every credential as an env-var name (e.g. `<PROVIDER>_API_KEY`, `<PROVIDER>_CLIENT_ID` + `<PROVIDER>_CLIENT_SECRET`) in `***test reqs***` and in the auth concept. Use the names the provider's docs use so users don't have to translate
@@ -63,6 +63,10 @@ A linked resource **must not** be any of the following:
63
63
  - A :User: can edit a :Task: using :TaskModalSpec:.
64
64
  ```
65
65
 
66
+ ## When to link
67
+ - Link content too long or too structured to state inline, or used from more than one place (through a concept, as above); state a short fact in the text instead
68
+ - Never link generated code - it lives in `plain_modules/`, not `resources/`
69
+
66
70
  ## File location and path resolution
67
71
  - Paths are resolved relative to the directory where `turri` is run (the current working directory)
68
72
  - Relative paths may traverse into parent directories — `[resource](../../resources/resource.md)` is valid — as long as they resolve to a real text file on disk
@@ -54,7 +54,7 @@ Besides frontmatter `import`, a template can be included with parameters:
54
54
  {% include "python-console-app-template.plain", main_executable_file_name: "my_app.py" %}
55
55
  ```
56
56
 
57
- Parameters are key-value pairs; the template reads them as `{{ variable_name }}`.
57
+ Parameters are key-value pairs; the template reads them as `{{ variable_name }}`. Templates live in `template/`. One is worth writing only for text more than one `.plain` file repeats, differing only in values the parameters carry; text used once stays inline.
58
58
 
59
59
  ## When an earlier test fails after a render
60
60
 
@@ -16,7 +16,7 @@ When writing or editing a `***test reqs***` section in a `.plain` file, always f
16
16
  - **Everything** about `:ConformanceTests:` goes in `***test reqs***` — paths, approach, packages, framework, execution command, mocking / network policy, fixtures, pass criteria, environment prerequisites
17
17
  - `:ConformanceTests:` live outside the generated codebase, in one folder, `plain_modules/<module>/tests/` - the module's whole conformance suite, so requirements that shape them belong in test reqs by definition
18
18
  - The conformance-test generator reads **only** `***test reqs***` — anything about `:ConformanceTests:` placed elsewhere (e.g. `***implementation reqs***`) is silently ignored
19
- - Author each `:ConformanceTests:` requirement via `add-test-requirement` and phrase it in terms of `:ConformanceTests:` so the partition stays visible at a glance
19
+ - Phrase each `:ConformanceTests:` requirement in terms of `:ConformanceTests:` so the partition stays visible at a glance
20
20
  - Do not link the conformance testing script here (or anywhere in the specs; a link to it is ignored). turri finds it in the project root - `conformance-tests-script:` in `config.turri.yaml`, else the one `run_conformance_tests*.sh` in the root, else the one in `test_scripts/` - and shows it to the agents that write the conformance tests itself. Describe the framework and execution command here in words
21
21
 
22
22
  ## What belongs here
@@ -26,7 +26,7 @@ The other rules say what a spec means. This one says what turri does with a chan
26
26
  - A definition changed patches every functional spec that uses its concept, directly or through other definitions. So does a change to a linked resource: the spec or definition linking it is changed though its text is not. A widely used definition is the costly edit - not a spec's position
27
27
  - Implementation reqs alone, or definitions no functional spec uses, are a mechanical change: the code adapts, and no test is written or changes what it asserts
28
28
  - Test reqs and acceptance tests reach the conformance tests only, never the code
29
- - A functional spec regenerated again by name has its conformance tests written again once its new code lands: what they check that the spec leaves open - a path, a field, a message the old code chose - goes by the new code
29
+ - A functional spec regenerated again by name has its code taken out and built anew - never left as it was, even where it already does what the spec says; a pulse that changes nothing does not land. Its conformance tests are written again once its new code lands: what they check that the spec leaves open - a path, a field, a message the old code chose - goes by the new code
30
30
  - Definitions moved to a common module and reqs reordered are recorded, not rendered
31
31
  - A functional spec written on its happy path and hardened later - its validation, edge cases and errors added to it - is patched in place each time: growing a spec a step at a time costs no more than writing it whole up front
32
32
  - A module's first pulse, when it builds one functional spec - the project set up and the smallest thing that runs - lands on its unit tests with no review
@@ -3,9 +3,9 @@ name: analyze-if-func-spec-too-complex
3
3
  description: >-
4
4
  Analyze a functional spec to determine if it is too complex for the renderer.
5
5
  A spec is too complex if it would produce more than 200 lines of code changes.
6
- Use after drafting a new functional spec (during `add-functional-spec`, or
7
- per spec during `add-functional-specs`) to verify it fits within the
8
- complexity limit before inserting it.
6
+ Use after drafting a new functional spec (per `func-specs.md`, *Adding a
7
+ functional spec*) to verify it fits within the complexity limit before
8
+ inserting it.
9
9
  allowed-tools: [read, ls, grep, find]
10
10
  ---
11
11
 
@@ -198,9 +198,9 @@ TOO COMPLEX
198
198
 
199
199
  The internal analysis (checklist, LOC estimation, reasoning) informs the verdict but must not appear in the output. The caller decides what to do with the result.
200
200
 
201
- ## Integration with add-functional-spec / add-functional-specs
201
+ ## Where it is called
202
202
 
203
- This skill is called during step 3 of the `add-functional-spec` workflow (or per spec during `add-functional-specs`), after drafting a spec but **before** inserting it into the file. The caller acts on the one-word verdict:
203
+ This skill is step 2 of adding a functional spec (`func-specs.md`, *Adding a functional spec*) - for each spec of a batch, in order - after drafting a spec but **before** inserting it into the file. The caller acts on the one-word verdict:
204
204
 
205
205
  - **ACCEPTABLE** — proceed to insert the spec.
206
206
  - **TOO COMPLEX** — invoke `break-down-func-spec` to produce smaller specs, then insert each one individually (running conflict checks on each).
@@ -160,7 +160,7 @@ If the spec describes a full screen, split into layout + individual interactive
160
160
 
161
161
  Sometimes a spec is too complex not because it bundles many behaviors, but because it implies building one substantial technical component inline — an engine, parser, scheduler, layout algorithm, state machine, or sync mechanism. Splitting the behavior sideways does not help when the weight sits in that single component. Instead, pull the component out: define a concept for it, build it in its own dedicated spec placed **earlier** in the chain, then rewrite the original to use the component **by reference**. Because specs render incrementally top-to-bottom, the original now implies far less code — it wires up a component that already exists rather than implementing it from scratch.
162
162
 
163
- Define the component concept in `***definitions***` (via `add-concept`) before the first spec that references it.
163
+ Define the component concept in `***definitions***` (per `definitions.md`) before the first spec that references it.
164
164
 
165
165
  **Before:**
166
166
  ```plain
@@ -17,9 +17,9 @@ Every iteration is exactly this, at every questioning level:
17
17
 
18
18
  1. **Ask one question** with `ask_user`, about the product: a feature, its trigger and outcome, one of its edge cases or rules, the next step of a flow - as broad as the level says. Never bundle two, and never ask about a spec section ("what concepts are there?", "what reqs apply?") - ask about what the product does, and let the answer decide which sections change.
19
19
  2. **Turn the answer into a spec change** - one for each feature it covers - everything it calls for, across sections:
20
- - a concept the feature introduces, into `***definitions***`, following `add-concept`, defined in the same change as the functional spec that first uses it;
20
+ - a concept the feature introduces, into `***definitions***`, following `definitions.md`, defined in the same change as the functional spec that first uses it;
21
21
  - a technology-free policy the answer states, into `***implementation reqs***`;
22
- - the functional spec for the feature, or the change to one already written, following `add-functional-spec`. Write it as a git diff of the `.plain` file(s): `diff --git a/<file> b/<file>`, `--- a/<file>`, `+++ b/<file>`, then the hunks with a few lines of unchanged context. Paths are relative to the project root.
22
+ - the functional spec for the feature, or the change to one already written, following `func-specs.md` - its wording, and the checks of *Adding a functional spec*. Write it as a git diff of the `.plain` file(s): `diff --git a/<file> b/<file>`, `--- a/<file>`, `+++ b/<file>`, then the hunks with a few lines of unchanged context. Paths are relative to the project root.
23
23
  3. **Write it with `change_plain`.** It applies the diff and starts a render spec diff job for it in the same call - whatever the change touches, a definition alone included. Write every change the answer calls for before the next question - `ask_user` refuses it until then - and any you decide yourself beside them. Move straight on to the next question; never wait for a build.
24
24
 
25
25
  **One answer, at least one change.** A follow-up about the same feature - an edge case, a validation rule - is its own answer and its own change to that feature's spec. An answer that describes two features is two changes, both written before the next question. A change never carries both an answer and something you decided: what you decide is a change of its own.
@@ -87,10 +87,10 @@ The feature, walked question by question. Run this loop while the questioning le
87
87
  1. **Ask** one product question with `ask_user`.
88
88
  2. The user **answers**.
89
89
  3. **Make the spec change** the answer calls for, as one git diff of the `.plain` file(s) - across every section it needs:
90
- - a concept it introduces, into `***definitions***` - written the way `add-concept` says, and defined in the same change as the functional spec that first uses it;
91
- - a policy it states - error handling, a retry, a data format, a library not already in the module or its imports - into `***implementation reqs***`, the way `add-implementation-requirement` says;
92
- - the functional spec it adds, or the change to one already written, the way `add-functional-spec` says: its wording rules, its complexity check (`analyze-if-func-spec-too-complex` - at most 200 lines of code; a spec too big is split *with the user*, as the next question) and its conflict check (`analyze-func-specs`, over the new spec and every existing one in the chain). Follow those skills for what the text is; the diff is the only thing that writes it.
93
- - with conformance tests on - test reqs of the module's own or imported, and a conformance testing script turri finds - an acceptance test under its functional spec when the answer states one concrete verification (`add-acceptance-test`), and a test req only when the answer changes how conformance tests run (`add-test-requirement`). With conformance off, none. Write it as a git diff: `diff --git a/<file> b/<file>`, `--- a/<file>`, `+++ b/<file>`, then the hunks with a few lines of unchanged context, paths from the project root. A new functional spec goes where it belongs in build order - after what it builds on, usually at the end.
90
+ - a concept it introduces, into `***definitions***` - written the way `definitions.md` says, and defined in the same change as the functional spec that first uses it;
91
+ - a policy it states - error handling, a retry, a data format, a library not already in the module or its imports - into `***implementation reqs***`, the way `impl-reqs.md` says;
92
+ - the functional spec it adds, or the change to one already written, the way `func-specs.md` says: its wording rules, its complexity check (`analyze-if-func-spec-too-complex` - at most 200 lines of code; a spec too big is split *with the user*, as the next question) and its conflict check (`analyze-func-specs`, over the new spec and every existing one in the chain). Follow those rules and skills for what the text is; the diff is the only thing that writes it.
93
+ - with conformance tests on - test reqs of the module's own or imported, and a conformance testing script turri finds - an acceptance test under its functional spec when the answer states one concrete verification (`func-specs.md`, *Acceptance tests*), and a test req only when the answer changes how conformance tests run (`test-reqs.md`). With conformance off, none. Write it as a git diff: `diff --git a/<file> b/<file>`, `--- a/<file>`, `+++ b/<file>`, then the hunks with a few lines of unchanged context, paths from the project root. A new functional spec goes where it belongs in build order - after what it builds on, usually at the end.
94
94
  4. **Write it with `change_plain` at once**, before anything else. It applies the diff and starts a render spec diff job for it; with conformance on, its conformance tests follow it. An answer that covers several behaviours is a change for each: write them all. Then the changes for what you decide yourself around it, if any. Say in one line what went into the spec - "added `:Note:` and functional spec 7" - and what became of the build, as the tool says, then ask the next question. Never wait for a build, and never ask the user to approve a change.
95
95
 
96
96
  **One answer, at least one change.** A follow-up about the same behaviour - an edge case, a validation rule - is its own answer and its own change. An answer that describes two behaviours is two changes, both written before the next question. A change never carries both an answer and something you decided: what you decide is a change of its own.
@@ -70,10 +70,10 @@ Trace the issue from the generated code back to the specs. There are five possib
70
70
  | Root Cause | Symptom | Fix |
71
71
  |------------|---------|-----|
72
72
  | **Ambiguous spec** | The spec is correct in intent, but vague enough that the renderer interpreted it differently than intended. | Add explicit detail to the spec to eliminate the ambiguity. |
73
- | **Missing spec** | The desired behavior is not covered by any spec. The renderer had no guidance and either did nothing or made an arbitrary choice. | Add a new functional spec using the `add-functional-spec` skill. |
73
+ | **Missing spec** | The desired behavior is not covered by any spec. The renderer had no guidance and either did nothing or made an arbitrary choice. | Add a new functional spec, checked as `func-specs.md` says (*Adding a functional spec*). |
74
74
  | **Conflicting specs** | Two specs contradict each other, causing the renderer to produce inconsistent behavior. | Use the `resolve-spec-conflict` skill. |
75
75
  | **Incorrect spec** | The spec explicitly describes the wrong behavior. The renderer implemented it faithfully, but the spec itself is wrong. | Rewrite the spec to describe the correct behavior. |
76
- | **Missing implementation req** | The spec is correct, but the implementation req doesn't provide enough guidance for the renderer to produce the right code (e.g., missing library, missing architectural constraint, missing platform detail). | Add or update the implementation req using the `add-implementation-requirement` skill. |
76
+ | **Missing implementation req** | The spec is correct, but the implementation req doesn't provide enough guidance for the renderer to produce the right code (e.g., missing library, missing architectural constraint, missing platform detail). | Add or update the implementation req, per `impl-reqs.md`. |
77
77
 
78
78
  ### How to diagnose
79
79
 
@@ -90,15 +90,15 @@ Trace the issue from the generated code back to the specs. There are five possib
90
90
 
91
91
  ## Phase 4 — Fix the Specs
92
92
 
93
- Apply the fix based on the diagnosed root cause. Use the appropriate skill:
93
+ Apply the fix based on the diagnosed root cause:
94
94
 
95
- | Root Cause | Skill to Use |
95
+ | Root Cause | How |
96
96
  |------------|-------------|
97
97
  | Ambiguous spec | Edit the spec inline — add sub-bullets or reword for clarity |
98
- | Missing spec | `add-functional-spec` |
98
+ | Missing spec | `func-specs.md`, *Adding a functional spec* |
99
99
  | Conflicting specs | `resolve-spec-conflict` |
100
100
  | Incorrect spec | Edit the spec inline — rewrite the incorrect part |
101
- | Missing implementation req | `add-implementation-requirement` |
101
+ | Missing implementation req | `impl-reqs.md` |
102
102
 
103
103
  ### Fix guidelines
104
104
 
@@ -61,7 +61,7 @@ Run cycles until the goal is met - or you are stuck - and at most twenty. Each c
61
61
  - **Not the spec's** - a bug the agent is working through, a missing tool or package, a flaky service, turri itself. Leave the build to it, note it for the report, and keep watching. Stopping it would throw its work away for nothing.
62
62
  5. **When the builds finish**, read `spec_findings`, and write into the spec every assumption about what the software does that a user, a caller or a test can see - as the build assumed it, unless that is not what the spec meant - so the next build does not have to guess. An assumption about how it is built inside - a library, a file layout, a name - stays out. A diagnosis that says the fix is in the spec is written; one that says code, environment or turri is noted. Then the next cycle: what failed, and what the new diffs changed, is rendered again.
63
63
 
64
- **Writing a fix.** A git diff of the `.plain` file(s), paths from the project root, a few lines of context, with `change_plain`. One diff per concern - a functionality's missing rules together, a concept and what it means together - never one diff for everything. Put each where it belongs: a rule of one functionality into its functional spec, a policy for many into `***implementation reqs***`, a term into `***definitions***`, following `add-concept`, `add-functional-spec` and `add-implementation-requirement` for how it is written. Each diff is built as it is written: what is left to build is worked out again from the spec - only what it changes is rendered again.
64
+ **Writing a fix.** A git diff of the `.plain` file(s), paths from the project root, a few lines of context, with `change_plain`. One diff per concern - a functionality's missing rules together, a concept and what it means together - never one diff for everything. Put each where it belongs: a rule of one functionality into its functional spec, a policy for many into `***implementation reqs***`, a term into `***definitions***`, following `definitions.md`, `func-specs.md` and `impl-reqs.md` for how it is written. Each diff is built as it is written: what is left to build is worked out again from the spec - only what it changes is rendered again.
65
65
 
66
66
  **When you are stuck, stop.** The same functionality struggling three times after you clarified the spec for it is not something the spec can settle: stop maturing it, and report it. Two cycles in a row with nothing newly built and nothing newly settled: stop, and report what is open. Twenty cycles: stop, and report.
67
67
 
@@ -35,7 +35,7 @@ The bullet, section, or `.plain` file to resolve.
35
35
  4. **Route each fact** by the *Section ownership* table in `module-structure.md`. Where a fact resists the table, apply the question it encodes: **would a caller of the finished software observe this?** Yes → `***functional specs***`. No, it is how the result is reached → `***implementation reqs***`. It says what a term means → `***definitions***`. It shapes `:ConformanceTests:` → `***test reqs***`.
36
36
  5. **Split a fact that carries both a mechanism and its consequence.** The consequence is observable and becomes the functional spec; the mechanism becomes the implementation req. *"Sends the same idempotency key on every retry, so a retried write creates at most one record"* is two facts, not one.
37
37
  6. **Give each moved fact a subject that exists in the built system.** A fact leaving a functional spec often loses its subject: name the component that owns the behavior, and add it to `***definitions***` if it is not defined yet. `:Implementation:` is the whole codebase — use it only for a fact that holds everywhere.
38
- 7. **Author each fact into its owning section** with the right edit skill — `add-concept`, `add-implementation-requirement`, `add-test-requirement`, `add-acceptance-test`. **Never hand-author `***functional specs***`**: a fact moving *into* that section goes through `add-functional-spec`, which runs the complexity and conflict analyzers for you.
38
+ 7. **Write each fact into its owning section** by that section's rule — `definitions.md`, `impl-reqs.md`, `test-reqs.md`, the acceptance tests in `func-specs.md`. A fact moving *into* `***functional specs***` goes through `func-specs.md` (*Adding a functional spec*): its complexity and conflict checks run before it is written in.
39
39
  8. **Remove each fact from where it no longer belongs.** If a bullet is left stating nothing observable, delete the bullet; do not leave a stub. Deleting the last bullet of a section deletes the section.
40
40
  9. **Verify nothing was lost and nothing was duplicated.** Walk every fact from the original text and confirm it appears in exactly one section. A fact that now reads as obvious in its new home is still a cut decision — make it deliberately, per `concise-specs.md`.
41
41
  10. **Run `validate`** on the module. Moving facts changes the renderable surface; do not finish while it reports errors.
@@ -43,8 +43,8 @@ The bullet, section, or `.plain` file to resolve.
43
43
 
44
44
  ## Error Handling
45
45
 
46
- - **`add-functional-spec` reports the moved fact is too complex** → the fact was a whole spec in disguise; run `break-down-func-spec` on it, then place the resulting specs.
47
- - **`add-functional-spec` reports a conflict** → resolve it with `resolve-spec-conflict` **before** removing the fact from its old section, so no version of it is lost in between.
46
+ - **The complexity check finds the moved fact too complex** → the fact was a whole spec in disguise; run `break-down-func-spec` on it, then place the resulting specs.
47
+ - **The conflict check reports a conflict** → resolve it with `resolve-spec-conflict` **before** removing the fact from its old section, so no version of it is lost in between.
48
48
  - **A fact appears to belong to two sections** → it is two facts; split it per step 5. If it still resists, it is a mechanism whose consequence has not been written down — write the consequence, and the split follows.
49
49
  - **The owning section does not exist in the file** → create it in canonical order. An import module carries no `***functional specs***` at all (see `import-modules.md`), so an observable fact found there belongs on the root module that imports it.
50
50
  - **The move empties a functional spec** → delete the spec rather than leaving a placeholder, and check whether any acceptance test nested under it must move or go with it.
@@ -58,7 +58,7 @@ The bullet, section, or `.plain` file to resolve.
58
58
  - [ ] Every fact from the original text appears in exactly one section, or was deliberately cut
59
59
  - [ ] No fact was reworded into a different meaning while being moved
60
60
  - [ ] Each moved fact names a subject that exists in the built system
61
- - [ ] Every fact moved into `***functional specs***` went through `add-functional-spec`
61
+ - [ ] Every fact moved into `***functional specs***` passed the complexity and conflict checks of `func-specs.md`
62
62
  - [ ] No `:UnitTests:` fact outside `***implementation reqs***`, no `:ConformanceTests:` fact outside `***test reqs***`
63
63
  - [ ] Sections are in canonical order and every referenced concept is defined before use
64
64
  - [ ] Emptied bullets and sections were removed, not left as stubs
@@ -4,7 +4,7 @@ description: >-
4
4
  Resolve a conflict between two functional specs in a ***plain spec file. Use
5
5
  when conformance tests for a previously passing spec start failing after a new
6
6
  spec is rendered, or when a potential conflict is detected while adding a new
7
- functional spec (via `add-functional-spec` or `add-functional-specs`).
7
+ functional spec (the conflict check of `func-specs.md`).
8
8
  allowed-tools: [read, write, edit, bash, ls, grep, find]
9
9
  ---
10
10
 
@@ -14,7 +14,7 @@ allowed-tools: [read, write, edit, bash, ls, grep, find]
14
14
 
15
15
  A conflict exists (or is suspected) when:
16
16
  - Conformance tests for a **previously passing** functional spec begin to fail after a new spec is rendered.
17
- - A new spec being added (via the `add-functional-spec` or `add-functional-specs` skill) appears to contradict an existing spec.
17
+ - A new spec being added appears to contradict an existing spec.
18
18
  - Two specs make incompatible assertions about the same behavior, data, or state.
19
19
 
20
20
  ## Workflow
@@ -76,7 +76,7 @@ After editing:
76
76
  3. Check that chronological ordering still makes sense (earlier specs should not depend on later ones).
77
77
  4. If resolving via test adjustments, verify the `***test reqs***` or `***acceptance tests***` changes are appropriate.
78
78
 
79
- ## Prevention (for use during add-functional-spec / add-functional-specs)
79
+ ## Prevention (while adding a functional spec)
80
80
 
81
81
  Before adding a new spec, run through this quick conflict check:
82
82
 
@@ -64,7 +64,7 @@ Set the module up and start the first build - on your own, no questions.
64
64
  2. **Unit tests.** A `:UnitTests:` requirement - the framework, and how they are run - unless the imported stack already sets it, and the unit testing script. Keep one turri already finds (named in `config.turri.yaml`, or the one `run_unittests*.sh` in the root or `test_scripts/`); otherwise write `test_scripts/run_unittests_<language>.sh` by following the `implement-unit-testing-script` skill. Never link it from the specs. The script runs the stack's static checks with the unit tests - the formatter in check mode, the linter, the type checker - and they count as the tests do.
65
65
  3. **Conformance tests: off.** Keep a `conformance-tests:` decision the project's config already holds - `config.turri.yaml`, or the old `config.yaml`. Otherwise write `conformance-tests: false` into `config.turri.yaml`, changing nothing else in it - a project with only a `config.yaml` has it copied to `config.turri.yaml` first, and `config.yaml` is never written - and write no `***test reqs***`, import no standard library conformance template, and write no conformance testing script. Only when the user asked for conformance tests, turn them on instead: `conformance-tests: true`, the `***test reqs***` - `:ConformanceTests:` requirements following `genome/rules/test-reqs.md`, or the stack's standard library conformance template imported when the stack is from it - and `test_scripts/run_conformance_tests_<language>.sh`, by following the `implement-conformance-testing-script` skill, unless turri already finds one.
66
66
  4. Run `validate` on every module you wrote, and fix what it finds.
67
- 5. **The first spec.** Write the module's first functional spec with `change_plain`: the smallest thing that runs and shows something - the server answers one request (`GET /` with the app's name), the command-line tool prints its usage, the page shows the app's name, the library exposes one call with a fixed result. It holds no product logic, so its build only sets the project up and lands fast - and its pulse is not reviewed. Follow `add-functional-spec` for its wording, and keep it to that one observable result.
67
+ 5. **The first spec.** Write the module's first functional spec with `change_plain`: the smallest thing that runs and shows something - the server answers one request (`GET /` with the app's name), the command-line tool prints its usage, the page shows the app's name, the library exposes one call with a fixed result. It holds no product logic, so its build only sets the project up and lands fast - and its pulse is not reviewed. Follow `func-specs.md` for its wording, and keep it to that one observable result.
68
68
 
69
69
  `change_plain` takes a git diff of the `.plain` file(s): `diff --git a/<file> b/<file>`, `--- a/<file>`, `+++ b/<file>`, then the hunks with a few lines of context, paths from the project root. It applies the change and queues its build. Go straight on to the next step - never wait for a build.
70
70
 
@@ -74,7 +74,7 @@ Write the first slices of what the user described, each a spec diff, while the f
74
74
 
75
75
  **Only what the user described.** Every slice comes from something the user said the software does. When they said only what kind of software it is, write no slice: the step writes nothing, and the handover invites them to say what it should do first.
76
76
 
77
- 1. **The main slice.** The one thing the user said the software is for, on its happy path - the half-built main function a developer writes first and runs. Its concepts go into `***definitions***` in the same change, following `add-concept`; its functional spec follows `add-functional-spec`, placed where it fits.
77
+ 1. **The main slice.** The one thing the user said the software is for, on its happy path - the half-built main function a developer writes first and runs. Its concepts go into `***definitions***` in the same change, following `definitions.md`; its functional spec follows `func-specs.md`, placed where it fits.
78
78
  2. **One more slice at most** - the next thing the user described, also on its happy path. Stop there: two slices beyond the first spec. What the user says once they have tried the first ones decides the rest, and slices written far ahead are slices to rework.
79
79
  3. **Write each with `change_plain`**, one after another - never wait for a build. Never change a `.plain` file in this step by any other means. Correct a change you find wrong once written with a diff and `fixes_earlier`, never by editing the file.
80
80
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turri-dev/cli",
3
- "version": "0.1.16-next.b861614",
3
+ "version": "0.1.16-next.ce2cd46",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,100 +0,0 @@
1
- ---
2
- name: add-acceptance-test
3
- description: >-
4
- Add acceptance tests under a functional spec in a ***plain spec file. Use
5
- when the user wants to add verification criteria for a specific functional
6
- spec, or after adding a functional spec that needs testable success criteria.
7
- allowed-tools: [read, write, edit, bash, ls, grep, find]
8
- ---
9
-
10
- # Add Acceptance Test
11
-
12
- ## Workflow
13
-
14
- 1. **Identify the target `.plain` file and the functional spec** to attach the acceptance test to. If ambiguous, ask the user.
15
- 2. **Read the file** to understand the functional spec, existing acceptance tests (if any), and the `***test reqs***` section (acceptance tests are implemented according to test reqs).
16
- 3. **Draft the acceptance test(s)** following the rules below.
17
- 4. **Nest them** under the target functional spec using a `***acceptance tests***` subsection.
18
- 5. **Read the file again** to confirm correct placement, indentation, and syntax.
19
-
20
- ## When to Add Acceptance Tests
21
-
22
- - The functional spec's correct behavior is **non-obvious** or easily misinterpreted.
23
- - The spec involves **edge cases**, boundary conditions, or specific numeric outcomes.
24
- - The user explicitly requests verification criteria.
25
- - The spec was added via the `add-functional-spec` skill and warrants testable success criteria.
26
-
27
- ## Format
28
-
29
- Acceptance tests are nested under the functional spec they verify, using a `***acceptance tests***` subsection:
30
-
31
- ```plain
32
- ***functional specs***
33
-
34
- - :Task: items are processed in batches of 100.
35
-
36
- ***acceptance tests***
37
- - Processing 250 :Task: items should result in 3 batches.
38
-
39
- - Each batch should contain at most 100 items.
40
- ```
41
-
42
- Key formatting rules:
43
- - The `***acceptance tests***` header is indented under the functional spec it belongs to.
44
- - Each test bullet is indented under the `***acceptance tests***` header.
45
- - Multiple acceptance tests can be listed under a single functional spec.
46
-
47
-
48
- ## Rules
49
-
50
- ### Conformance with the Functional Spec
51
-
52
- An acceptance test is essentially an **example that illustrates** the functional spec — it clarifies intent by showing a concrete scenario. It may imply minor code changes, but those should not be substantial. The acceptance test **must be consistent with** the functional spec it is nested under. If the acceptance test asserts behavior that contradicts, narrows, or extends the functional spec in ways not implied by it, the system will reject it as a conflicting acceptance test. Before writing, re-read the parent functional spec and ensure every assertion in the acceptance test is a direct, logical consequence of what the spec states.
53
-
54
- ```
55
- Functional spec:
56
- - :Resource: items are returned sorted by creation date in descending order.
57
-
58
- Good (consistent):
59
- - The first :Resource: in the response should have the most recent creation date.
60
-
61
- Bad (contradicts the spec — the spec says descending, not ascending):
62
- - The first :Resource: in the response should have the oldest creation date.
63
-
64
- Bad (extends beyond the spec — the spec says nothing about limiting results):
65
- - The response should contain at most 50 :Resource: items.
66
- ```
67
-
68
- ### Scope
69
-
70
- Each acceptance test verifies a specific, observable aspect of the functional spec it's nested under. Do not test behavior from other functional specs.
71
-
72
- ### Testability
73
-
74
- Every acceptance test must describe a concrete, verifiable outcome — not a vague quality. The test should be implementable as an automated conformance test.
75
-
76
- ```
77
- Good: - The response should contain exactly 3 items.
78
- Bad: - The response should be correct.
79
- ```
80
-
81
- ### Language Agnosticism
82
-
83
- Like functional specs, acceptance tests must be written in terms of behavior and outcomes — not language-specific constructs.
84
-
85
- ### Relationship to Test Reqs
86
-
87
- Acceptance tests extend conformance tests and are implemented according to the `***test reqs***` specification. They do not replace test reqs — they add spec-specific verification on top of the general testing framework defined there.
88
-
89
- ## Validation Checklist
90
-
91
- - [ ] Every assertion is a direct logical consequence of the parent functional spec
92
- - [ ] No assertion contradicts, narrows, or extends beyond the parent spec
93
- - [ ] Acceptance test illustrates the spec via example, not introducing substantial new behavior
94
- - [ ] Nested under the correct functional spec
95
- - [ ] Indentation is correct (`***acceptance tests***` indented under the spec)
96
- - [ ] Each test describes a concrete, verifiable outcome
97
- - [ ] Trimmed per `concise-specs.md`: plain words, no obvious steps, no restatement of the parent spec
98
- - [ ] Tests are scoped to the parent functional spec only
99
- - [ ] Written in language-agnostic terms
100
- - [ ] No duplication with existing acceptance tests on the same spec
@@ -1,71 +0,0 @@
1
- ---
2
- name: add-concept
3
- description: >-
4
- Add a concept to the ***definitions*** section of a ***plain spec file. Use
5
- when the user wants to define a new concept, entity, or domain term in a
6
- .plain file.
7
- allowed-tools: [read, write, edit, bash, ls, grep, find]
8
- ---
9
-
10
- # Add Concept
11
-
12
- ## Workflow
13
-
14
- 1. **Identify the target `.plain` file.** If ambiguous, ask the user.
15
- 2. **Read the file** to understand existing definitions, imports, and concepts.
16
- 3. **Validate the concept name** against the syntax rules below.
17
- 4. **Check for uniqueness** — the concept name must not already exist in the file or its imports.
18
- 5. **Check referenced concepts** — any `:ConceptName:` used in the definition must already be defined above it (in this file or via `import`/`requires`). Concept references must not form cycles (e.g., A references B and B references A).
19
- 6. **Check for circular references** — if the new concept references `:B:`, then `:B:` must not reference the new concept (directly or indirectly). Example of a circular definition to avoid:
20
- ```plain
21
- - :Order: is placed by :Customer: and contains :OrderItem: entries.
22
- - :Customer: is a user who has placed at least one :Order:.
23
- ```
24
- Fix by removing the back-reference:
25
- ```plain
26
- - :Customer: is a user of the system.
27
- - :Order: is placed by :Customer: and contains :OrderItem: entries.
28
- ```
29
- 7. **Insert the concept** into the `***definitions***` section, after any concepts it references.
30
- 8. **Read the file again** to confirm correct placement and syntax.
31
-
32
- ## Concept Syntax Rules
33
-
34
- - Wrapped in colons: `:ConceptName:`
35
- - CamelCase, starting with an uppercase letter
36
- - Valid characters: letters, digits, `+`, `-`, `.`, `_`
37
- - Must be globally unique across the spec and all its imports
38
- - Exported concepts from `requires` modules are **not transitive** — to reference an ancestor's export, list that ancestor in `requires`; if a concept is shared across branches, define it in a common import module instead
39
-
40
- ## Definition Format
41
-
42
- A concept definition is a bullet in `***definitions***` that starts with the concept name:
43
-
44
- ```plain
45
- ***definitions***
46
-
47
- - :ConceptName: is a description of what it represents.
48
- ```
49
-
50
- Attributes and constraints are nested sub-bullets:
51
-
52
- ```plain
53
- ***definitions***
54
-
55
- - :Task: describes an activity that needs to be done by :User:. :Task: has:
56
- - Name - a short description (required)
57
- - Notes - additional details (optional)
58
- - Due Date - completion deadline (optional)
59
- ```
60
-
61
-
62
- ## Validation Checklist
63
-
64
- - [ ] Name uses `:CamelCase:` notation
65
- - [ ] Name is globally unique (not defined elsewhere in the file or imports)
66
- - [ ] Definition starts with the concept name
67
- - [ ] All referenced concepts (`:OtherConcept:`) are already defined above
68
- - [ ] No circular references between concepts
69
- - [ ] Description is clear, concise, and language-agnostic
70
- - [ ] Trimmed per `concise-specs.md`: one plain sentence, no restatement of the name, no rationale
71
- - [ ] Placed inside a `***definitions***` section