@turri-dev/cli 0.1.27 → 0.1.28-next.d5f2680

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 (216) hide show
  1. package/README.md +6 -6
  2. package/dist/advisor-chat.d.ts +63 -0
  3. package/dist/advisor-chat.js +290 -0
  4. package/dist/background-skills.d.ts +53 -0
  5. package/dist/background-skills.js +121 -0
  6. package/dist/bedrock-region.d.ts +66 -0
  7. package/dist/bedrock-region.js +144 -0
  8. package/dist/btw.d.ts +1 -1
  9. package/dist/btw.js +1 -1
  10. package/dist/change-plain-cli.js +20 -13
  11. package/dist/chat-idle.d.ts +7 -0
  12. package/dist/chat-idle.js +20 -0
  13. package/dist/chats.d.ts +10 -0
  14. package/dist/chats.js +23 -0
  15. package/dist/cli-options.d.ts +1 -2
  16. package/dist/cli-options.js +2 -7
  17. package/dist/cli.js +11 -3
  18. package/dist/config-command.d.ts +14 -0
  19. package/dist/config-command.js +35 -15
  20. package/dist/config-edit.d.ts +3 -3
  21. package/dist/config-edit.js +16 -12
  22. package/dist/config.d.ts +54 -34
  23. package/dist/config.js +40 -44
  24. package/dist/conform-cli.js +12 -10
  25. package/dist/conformance-switch.d.ts +34 -0
  26. package/dist/conformance-switch.js +108 -0
  27. package/dist/cultivate-cli.js +15 -5
  28. package/dist/drift-cli.js +2 -0
  29. package/dist/extension.d.ts +15 -0
  30. package/dist/extension.js +260 -83
  31. package/dist/host-session.d.ts +26 -0
  32. package/dist/host-session.js +30 -2
  33. package/dist/host.d.ts +5 -2
  34. package/dist/host.js +7 -1
  35. package/dist/init-config.d.ts +1 -1
  36. package/dist/init-config.js +20 -11
  37. package/dist/loop-cli.d.ts +3 -3
  38. package/dist/loop-cli.js +13 -16
  39. package/dist/loop-tools.js +18 -10
  40. package/dist/model-check.d.ts +8 -3
  41. package/dist/model-check.js +13 -8
  42. package/dist/new-project.js +12 -8
  43. package/dist/{validate-cli.js → parse-cli.js} +11 -5
  44. package/dist/parse-tool.d.ts +9 -0
  45. package/dist/parse-tool.js +33 -0
  46. package/dist/pi-launch.js +1 -1
  47. package/dist/plain/check.d.ts +53 -6
  48. package/dist/plain/check.js +217 -24
  49. package/dist/plain/concepts.d.ts +8 -0
  50. package/dist/plain/concepts.js +66 -23
  51. package/dist/plain/cycles.d.ts +21 -0
  52. package/dist/plain/cycles.js +190 -0
  53. package/dist/plain/errors.d.ts +4 -0
  54. package/dist/plain/errors.js +7 -0
  55. package/dist/plain/files.d.ts +18 -1
  56. package/dist/plain/files.js +39 -2
  57. package/dist/plain/graph.d.ts +33 -4
  58. package/dist/plain/graph.js +60 -12
  59. package/dist/plain/highlight.d.ts +3 -2
  60. package/dist/plain/highlight.js +4 -3
  61. package/dist/plain/index.d.ts +8 -5
  62. package/dist/plain/index.js +8 -5
  63. package/dist/plain/liquid.js +1 -6
  64. package/dist/plain/markdown.d.ts +32 -3
  65. package/dist/plain/markdown.js +146 -24
  66. package/dist/plain/module-concepts.js +2 -2
  67. package/dist/plain/parser.d.ts +83 -28
  68. package/dist/plain/parser.js +381 -260
  69. package/dist/plain/plain.tmLanguage.json +29 -3
  70. package/dist/plain/project.d.ts +48 -0
  71. package/dist/plain/project.js +155 -0
  72. package/dist/plain/spec.d.ts +90 -28
  73. package/dist/plain/spec.js +107 -133
  74. package/dist/plain/test-plain-file.d.ts +59 -0
  75. package/dist/plain/test-plain-file.js +232 -0
  76. package/dist/regenerate/activity.d.ts +20 -9
  77. package/dist/regenerate/activity.js +11 -4
  78. package/dist/regenerate/advisor-records.d.ts +93 -0
  79. package/dist/regenerate/advisor-records.js +110 -0
  80. package/dist/regenerate/advisor-runs.d.ts +87 -0
  81. package/dist/regenerate/advisor-runs.js +327 -0
  82. package/dist/regenerate/base-folder.d.ts +68 -0
  83. package/dist/regenerate/base-folder.js +168 -0
  84. package/dist/regenerate/cases.d.ts +9 -6
  85. package/dist/regenerate/cases.js +70 -14
  86. package/dist/regenerate/change-view.d.ts +8 -3
  87. package/dist/regenerate/change-view.js +71 -22
  88. package/dist/regenerate/chunk-plan.d.ts +36 -15
  89. package/dist/regenerate/chunk-plan.js +165 -59
  90. package/dist/regenerate/conform.d.ts +3 -0
  91. package/dist/regenerate/conform.js +6 -5
  92. package/dist/regenerate/conformance-agents.d.ts +18 -39
  93. package/dist/regenerate/conformance-agents.js +60 -88
  94. package/dist/regenerate/conformance.d.ts +23 -13
  95. package/dist/regenerate/conformance.js +119 -82
  96. package/dist/regenerate/diff-view.d.ts +1 -1
  97. package/dist/regenerate/diff-view.js +20 -4
  98. package/dist/regenerate/drift.d.ts +47 -15
  99. package/dist/regenerate/drift.js +101 -30
  100. package/dist/regenerate/jobs.d.ts +2 -2
  101. package/dist/regenerate/jobs.js +1 -1
  102. package/dist/regenerate/ledger.d.ts +19 -0
  103. package/dist/regenerate/loop.d.ts +62 -43
  104. package/dist/regenerate/loop.js +472 -341
  105. package/dist/regenerate/paths.d.ts +4 -0
  106. package/dist/regenerate/paths.js +7 -1
  107. package/dist/regenerate/plain-palette.js +2 -0
  108. package/dist/regenerate/prompt.d.ts +57 -19
  109. package/dist/regenerate/prompt.js +157 -122
  110. package/dist/regenerate/records.d.ts +43 -12
  111. package/dist/regenerate/records.js +102 -88
  112. package/dist/regenerate/regenerate.js +29 -11
  113. package/dist/regenerate/regression.d.ts +4 -4
  114. package/dist/regenerate/regression.js +14 -10
  115. package/dist/regenerate/renames.d.ts +42 -0
  116. package/dist/regenerate/renames.js +185 -0
  117. package/dist/regenerate/requires.d.ts +1 -1
  118. package/dist/regenerate/requires.js +10 -3
  119. package/dist/regenerate/resources.d.ts +5 -3
  120. package/dist/regenerate/resources.js +4 -4
  121. package/dist/regenerate/scripts-being-written.d.ts +19 -0
  122. package/dist/regenerate/scripts-being-written.js +30 -0
  123. package/dist/regenerate/spec-map-view.d.ts +2 -2
  124. package/dist/regenerate/spec-map-view.js +46 -15
  125. package/dist/regenerate/spec-map.d.ts +27 -5
  126. package/dist/regenerate/spec-map.js +92 -60
  127. package/dist/regenerate/spec-steps.d.ts +48 -5
  128. package/dist/regenerate/spec-steps.js +213 -28
  129. package/dist/regenerate/state.d.ts +4 -3
  130. package/dist/regenerate/stop-report.d.ts +1 -1
  131. package/dist/regenerate/stop-report.js +10 -10
  132. package/dist/regenerate/test-advisor.d.ts +101 -0
  133. package/dist/regenerate/test-advisor.js +379 -0
  134. package/dist/regenerate/test-kinds.d.ts +71 -28
  135. package/dist/regenerate/test-kinds.js +110 -63
  136. package/dist/regenerate/test-scripts.d.ts +2 -0
  137. package/dist/regenerate/test-scripts.js +4 -0
  138. package/dist/regenerate/testing-steps.d.ts +41 -0
  139. package/dist/regenerate/testing-steps.js +110 -0
  140. package/dist/regenerate/testing.d.ts +1 -1
  141. package/dist/regenerate/testing.js +5 -4
  142. package/dist/regenerate/unit-review.d.ts +1 -1
  143. package/dist/regenerate/unit-review.js +3 -3
  144. package/dist/regenerate-cli.js +11 -12
  145. package/dist/release-agent.js +4 -0
  146. package/dist/release-cli.js +2 -0
  147. package/dist/release-tools.js +2 -0
  148. package/dist/run-report.d.ts +2 -2
  149. package/dist/run-report.js +4 -3
  150. package/dist/self-invocation.d.ts +1 -1
  151. package/dist/self-invocation.js +1 -1
  152. package/dist/sentinel.js +1 -1
  153. package/dist/setup.d.ts +10 -0
  154. package/dist/setup.js +52 -4
  155. package/dist/skill.d.ts +10 -0
  156. package/dist/skill.js +6 -0
  157. package/dist/skills.js +3 -1
  158. package/dist/spec-tools.js +21 -31
  159. package/dist/test-plain-files.d.ts +41 -0
  160. package/dist/test-plain-files.js +177 -0
  161. package/docs/README.md +3 -1
  162. package/docs/authoring-plain.md +46 -13
  163. package/docs/chats.md +3 -1
  164. package/docs/config.md +20 -15
  165. package/docs/deploy.md +1 -1
  166. package/docs/development.md +2 -1
  167. package/docs/headless.md +15 -18
  168. package/docs/hosting.md +28 -12
  169. package/docs/installation.md +1 -0
  170. package/docs/parser.md +88 -27
  171. package/docs/regenerating.md +87 -52
  172. package/docs/sentinel.md +1 -1
  173. package/docs/skills-and-gates.md +3 -1
  174. package/docs/test-advisor.md +110 -0
  175. package/docs/theming.md +1 -1
  176. package/docs/using.md +17 -15
  177. package/genome/rules/bullet-continuation.md +8 -8
  178. package/genome/rules/concise-specs-examples.md +111 -80
  179. package/genome/rules/concise-specs-integration-examples.md +56 -41
  180. package/genome/rules/concise-specs.md +17 -16
  181. package/genome/rules/definitions.md +5 -5
  182. package/genome/rules/examples/integration-embedded-testing/run_conformance_tests_java.sh +1 -1
  183. package/genome/rules/func-specs.md +69 -74
  184. package/genome/rules/impl-reqs.md +4 -4
  185. package/genome/rules/integration-embedded-testing.md +20 -20
  186. package/genome/rules/integration-embedded.md +31 -31
  187. package/genome/rules/integration-standalone.md +9 -9
  188. package/genome/rules/integrations.md +18 -18
  189. package/genome/rules/linked-resources.md +19 -16
  190. package/genome/rules/module-structure.md +21 -14
  191. package/genome/rules/project-model.md +18 -17
  192. package/genome/rules/required-concepts.md +1 -1
  193. package/genome/rules/requires-modules.md +6 -5
  194. package/genome/rules/semantic-ids.md +49 -0
  195. package/genome/rules/stdlib.md +4 -5
  196. package/genome/rules/test-plain-files.md +130 -0
  197. package/genome/rules/test-reqs.md +8 -8
  198. package/genome/rules/turri-regeneration.md +23 -8
  199. package/genome/skills/analyze-2-func-specs/SKILL.md +36 -21
  200. package/genome/skills/analyze-func-specs/SKILL.md +46 -32
  201. package/genome/skills/break-down-func-spec/SKILL.md +91 -67
  202. package/genome/skills/consolidate-concepts/SKILL.md +10 -10
  203. package/genome/skills/convert-old-syntax/SKILL.md +68 -0
  204. package/genome/skills/convert-old-syntax/references/rubric.md +11 -0
  205. package/genome/skills/debug-specs/SKILL.md +62 -56
  206. package/genome/skills/implement-conformance-testing-script/SKILL.md +19 -15
  207. package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +2 -2
  208. package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +2 -2
  209. package/genome/skills/implement-unit-testing-script/SKILL.md +14 -10
  210. package/genome/skills/refactor-module/SKILL.md +35 -35
  211. package/genome/skills/resolve-section-ownership/SKILL.md +9 -9
  212. package/genome/skills/resolve-spec-conflict/SKILL.md +35 -29
  213. package/package.json +7 -6
  214. package/dist/regenerate/choose-conformance.d.ts +0 -32
  215. package/dist/regenerate/choose-conformance.js +0 -117
  216. /package/dist/{validate-cli.d.ts → parse-cli.d.ts} +0 -0
@@ -1,16 +1,16 @@
1
1
  ---
2
- description: Conciseness and plain-language rules that keep .plain specs reviewable by a human
2
+ description: Conciseness and plain-language rules that keep ***plain reviewable by a human
3
3
  ---
4
4
 
5
- # Rules for keeping `.plain` specs concise
5
+ # Rules for keeping `.plain` files concise
6
6
 
7
- These rules apply to every section, to concept explanations, and to acceptance tests. `concise-specs-examples.md` holds a worked BAD to GOOD pair for each failure mode named here, and `concise-specs-integration-examples.md` covers the failure modes specific to integration specs.
7
+ These rules apply to every section, to concept explanations, and to scenarios in test plain files. `concise-specs-examples.md` holds a worked BAD to GOOD pair for each failure mode named here, and `concise-specs-integration-examples.md` covers the failure modes specific to integration specs.
8
8
 
9
9
  ## Why this matters
10
10
 
11
- - A spec is the source of truth, so a human has to be able to review it
12
- - A long, dense, or ornate spec is skipped rather than reviewed — an unreviewed spec is an unverified spec, however correct it happens to be
13
- - Length is not a proxy for rigor: a spec earns trust by being checkable, not by being thorough-looking
11
+ - ***plain is the source of truth, so a human has to be able to review it
12
+ - Long, dense, or ornate ***plain is skipped rather than reviewed — unreviewed ***plain is unverified ***plain, however correct it happens to be
13
+ - Length is not a proxy for rigor: ***plain earns trust by being checkable, not by being thorough-looking
14
14
  - Conciseness is about removing what carries no information, never about removing required detail — the deterministic-interface, disambiguation, and testability rules always win (see `func-specs.md`)
15
15
 
16
16
  ## Do not write the obvious
@@ -21,11 +21,11 @@ Do not write:
21
21
 
22
22
  - Restatements of a concept's own name (`:UserEmail: is the email address of a :User:.` adds nothing beyond what `definitions.md` already requires the concept to carry)
23
23
  - Universal software defaults: that invalid input is rejected, that errors are reported, that data is saved when saving is the point of the operation
24
- - Rationale, motivation, benefits, or background — the spec states what is, not why it was chosen
24
+ - Rationale, motivation, benefits, or background — ***plain states what is, not why it was chosen
25
25
  - Standard behavior of a technology already named in `***implementation reqs***` (an HTTP framework parses HTTP; a database driver opens connections)
26
26
  - Restatements of a nearby bullet in different words, or of anything already stated in an `import`ed or `require`d module
27
- - Anything about work the spec is not about ("no changes to the existing UI")
28
- - Meta-commentary about the spec itself ("this spec is intentionally small", "as described above")
27
+ - Anything about work the ***plain is not about ("no changes to the existing UI")
28
+ - Meta-commentary about the ***plain itself ("this spec is intentionally small", "as described above")
29
29
 
30
30
  Worked pairs for every item above — padding, rationale, defaults, technology behavior, meta-commentary, and duplication of an `import` — are in `concise-specs-examples.md`.
31
31
 
@@ -35,7 +35,7 @@ Worked pairs for every item above — padding, rationale, defaults, technology b
35
35
  - Write short sentences: one clause plus, at most, one qualifier
36
36
  - Use the same word for the same thing every time — synonym variety reads as two different things
37
37
  - Do not use adverbs and adjectives that no test can check: `robust`, `seamless`, `efficient`, `scalable`, `comprehensive`, `modern`, `properly`, `gracefully`, `as appropriate`, `where applicable`, `best practices`. Either state the checkable fact (`a response is returned within 200 ms`) or delete the word
38
- - Do not hedge: `should ideally`, `may optionally`, `typically`, `generally`, `if possible`. A spec states one behavior; a hedge tells the renderer to guess
38
+ - Do not hedge: `should ideally`, `may optionally`, `typically`, `generally`, `if possible`. A functional spec states one behavior; a hedge tells the coding agent to guess
39
39
 
40
40
  | Do not write | Write |
41
41
  |---|---|
@@ -52,20 +52,21 @@ Worked pairs for every item above — padding, rationale, defaults, technology b
52
52
 
53
53
  ## Keep the shape small
54
54
 
55
+ - The bullet rules here apply to `***definitions***`, `***implementation reqs***`, and `***test reqs***`; the body of a functional spec and of a scenario is free text
55
56
  - One statement per bullet, one bullet per fact (see `bullet-continuation.md`)
56
57
  - Nest a sub-bullet only to remove a real ambiguity; a sub-bullet that merely elaborates is filler
57
- - Consecutive specs that share a subject are usually one spec: if a top-level bullet only tells part of the story of one operation, merge the set, lead with the operation's result, and demote the steps and failure modes to sub-bullets (see *One operation fragmented into several specs* in `concise-specs-integration-examples.md`)
58
+ - Consecutive functional specs that share a subject are usually one: if a functional spec only tells part of the story of one operation, merge the set, lead with the operation's result, and demote the steps and failure modes to detail under it (see *One operation fragmented into several functional specs* in `concise-specs-integration-examples.md`)
58
59
  - Tables, prose paragraphs, and code blocks do not belong in a section; external artifacts are linked from `resources/` (see `linked-resources.md`)
59
- - A bullet that answers more than one of *what is it*, *what does it do*, *how is it built*, and *how is it tested* is not one fact — split it across the sections that own those facts, which reads better and is the only way the renderer sees each part (see `module-structure.md`, and *Split one crowded bullet across its owning sections* in `concise-specs-examples.md`)
60
+ - A bullet that answers more than one of *what is it*, *what does it do*, *how is it built*, and *how is it tested* is not one fact — split it across the sections that own those facts, which reads better and is the only way each part is read where it belongs (see `module-structure.md`, and *Split one crowded bullet across its owning sections* in `concise-specs-examples.md`)
60
61
 
61
62
  ## Terse is not a defect
62
63
 
63
- A finished spec usually reads as abrupt: clipped bullets, no connective tissue, no lead-ins. That is the intended shape, not something to smooth out afterwards.
64
+ Finished ***plain usually reads as abrupt: clipped bullets, no connective tissue, no lead-ins. That is the intended shape, not something to smooth out afterwards.
64
65
 
65
66
  - Add a word only to make a line correct, unambiguous, or checkable — never to make it read better
66
67
  - Do not merge short bullets into one sentence for rhythm, and do not open a section or a bullet with a lead-in
67
- - The bar is the other rules — correct, intent intact, reviewable, testable. A spec that clears them is finished however clipped it sounds
68
- - Filler is not neutral: the renderer reads every line as a requirement, so a line written for flow can invent one
68
+ - The bar is the other rules — correct, intent intact, reviewable, testable. ***plain that clears them is finished however clipped it sounds
69
+ - Filler is not neutral: the coding agent reads every line as a requirement, so a line written for flow can invent one
69
70
 
70
71
  ## Review pass before writing to disk
71
72
 
@@ -76,4 +77,4 @@ Read the drafted lines once more and apply, in order:
76
77
  3. **The duplication test** — cut anything already stated in this file, an `import`, or a `requires` chain
77
78
  4. **The read-aloud test** — a line you cannot read aloud in one breath is either two facts or one padded one
78
79
 
79
- If a cut would remove an interface detail, a boundary case, or a disambiguation, keep the fact and shorten the wording instead — see *Do not over-cut* in `concise-specs-examples.md` for what a spec cut past its content looks like.
80
+ If a cut would remove an interface detail, a boundary case, or a disambiguation, keep the fact and shorten the wording instead — see *Do not over-cut* in `concise-specs-examples.md` for what ***plain cut past its content looks like.
@@ -12,12 +12,12 @@ When writing or editing a `***definitions***` section in a `.plain` file, always
12
12
  - Valid characters: letters, digits, `+`, `-`, `.`, `_`
13
13
 
14
14
  ## Uniqueness
15
- - Concept names must be globally unique across the spec and all its imports
15
+ - Concept names must be globally unique across the module and all its imports
16
16
  - Check for collisions with concepts coming from `import` and `requires` modules before adding
17
17
 
18
18
  ## Predefined concepts (do not redefine)
19
19
  - ***plain ships several predefined concepts that are available in every module without being defined
20
- - Never add a `***definitions***` entry for any of them — the renderer treats redefinitions as conflicts
20
+ - Never add a `***definitions***` entry for any of them — turri treats redefinitions as conflicts
21
21
 
22
22
  | Predefined concept | Meaning |
23
23
  |--------------------|---------|
@@ -27,9 +27,9 @@ When writing or editing a `***definitions***` section in a `.plain` file, always
27
27
  | `:plainTestReqs:` | Content of the `***test reqs***` section |
28
28
  | `:Implementation:` | The system implementing `:plainFunctionality:` |
29
29
  | `:plainImplementationCode:` | The generated implementation code |
30
- | `:UnitTests:` | Auto-generated unit tests for individual functionalities |
31
- | `:ConformanceTests:` | Auto-generated tests verifying conformance to the spec |
32
- | `:AcceptanceTest:` / `:AcceptanceTests:` | Tests validating specific aspects of the implementation |
30
+ | `:UnitTests:` | The unit tests the coding agent writes with each functional spec's code |
31
+ | `:ConformanceTests:` | The black-box tests written from the functional specs' conformance scenarios, run by the conformance testing script |
32
+ | `:AcceptanceTest:` / `:AcceptanceTests:` | The black-box tests written from the functional specs' acceptance scenarios, run by the conformance testing script |
33
33
 
34
34
  ## Conciseness
35
35
  - A definition is one plain sentence plus, where needed, its attributes — see `concise-specs.md`
@@ -22,7 +22,7 @@ fi
22
22
  current_dir=$(pwd)
23
23
 
24
24
  # Resolve the conformance tests folder to an absolute path ($2 may be relative
25
- # on older renderers; newer renderers pass it as an absolute path).
25
+ # on older harnesses; turri passes it as an absolute path).
26
26
  case "$2" in
27
27
  /*) CONFORMANCE_TESTS_SOURCE="$2" ;;
28
28
  *) CONFORMANCE_TESTS_SOURCE="$current_dir/$2" ;;
@@ -1,16 +1,22 @@
1
1
  ---
2
- description: Rules for writing ***functional specs*** and ***acceptance tests*** in .plain files
2
+ description: Rules for writing ***functional specs*** in .plain files
3
3
  ---
4
4
 
5
5
  # Rules for writing `***functional specs***`
6
6
 
7
7
  When writing or editing a `***functional specs***` section in a `.plain` file, always follow these rules:
8
8
 
9
+ ## Shape
10
+ - Each functional spec is a `# <func-id>` heading followed by its body; the func-id follows `semantic-ids.md`
11
+ - The body is free text that describes the behaviour: its first line states it, and prose or `- ` bullets under that line add the detail
12
+ - No body line starts with `# ` (that starts the next functional spec) or with `***`
13
+ - A functional spec's test scenarios live in its test plain file, never in this section (see `test-plain-files.md`)
14
+
9
15
  ## Voice
10
16
  - Write each functional spec as a **statement of fact** — present tense, indicative mood — describing what the software *is* or *does* once built, not as a command telling a developer what to build
11
17
  - **Name a concrete subject**: an actor (`A :User: can …`), a named component or concept (`:PdfRenderer: lays out …`, `:Order: processing depends on …`), or the affected data in passive voice (`All :Resource: items are returned`)
12
18
  - **Avoid the vague subject "The system …"** — it says nothing about *which* part does the work. Prefer the concrete component/concept, or passive voice with the affected concept as the subject
13
- - **Never open a spec with an imperative** like "Implement …", "Add …", "Create …", "Show …", "Display …", "Build …" — those read as instructions, not specifications
19
+ - **Never open a functional spec with an imperative** like "Implement …", "Add …", "Create …", "Show …", "Display …", "Build …" — those read as instructions, not as what the software does
14
20
  - Do **not** use "should" / "should be able to" in a functional spec — that is requirement-modal voice; state the fact directly
15
21
 
16
22
  BAD — imperative commands, or the vague "The system":
@@ -18,11 +24,14 @@ BAD — imperative commands, or the vague "The system":
18
24
  ```plain
19
25
  ***functional specs***
20
26
 
21
- - Implement the entry point for :App:.
27
+ # entry-point
28
+ Implement the entry point for :App:.
22
29
 
23
- - The system shows :TaskList:.
30
+ # show-task-list
31
+ The system shows :TaskList:.
24
32
 
25
- - Add :Task:.
33
+ # add-task
34
+ Add :Task:.
26
35
  ```
27
36
 
28
37
  GOOD — statements of fact with concrete subjects:
@@ -30,71 +39,75 @@ GOOD — statements of fact with concrete subjects:
30
39
  ```plain
31
40
  ***functional specs***
32
41
 
33
- - :App: has an entry point.
42
+ # entry-point
43
+ :App: has an entry point.
34
44
 
35
- - The :TaskList: is displayed.
45
+ # show-task-list
46
+ The :TaskList: is displayed.
36
47
 
37
- - A :User: can add a :Task:. Only valid :Task: items are added.
48
+ # add-task
49
+ A :User: can add a :Task:. Only valid :Task: items are added.
38
50
  ```
39
51
 
40
52
  ## Conciseness
41
- - A functional spec that a human will not read is not reviewed, so every spec must be as short as its content allows — see `concise-specs.md`
53
+ - A functional spec that a human will not read is not reviewed, so every one must be as short as its content allows — see `concise-specs.md`
42
54
  - Cut anything obvious, any rationale, and every uncheckable adjective; keep every interface detail, boundary case, and disambiguation
43
55
  - Shorten the wording, never the facts: the rules below always win over brevity
44
56
 
45
57
  ## Complexity limit
46
58
  - The complexity limit is about breaking software into small, independently understandable behavior slices that people and AI can reason about, implement, and test reliably
47
59
  - The current mechanism for enforcing the complexity limit is that each functional spec must imply a **maximum of 200 changed lines of code**.
48
- - Smaller slices produce focused test failures, reduce hidden coupling and regression surface, and make review and incremental rendering more predictable
49
- - If a spec is too large, use `break-down-func-spec` to split it into multiple smaller, independent specs
50
- - Judge a spec's size yourself before inserting it: estimate the code it implies - new files, functions, data model changes, UI components, error paths, boilerplate, its unit tests - and treat more than ~150 lines as too big, leaving the renderer headroom
51
- - Signs a spec is too big - one is not proof, several are:
60
+ - Smaller slices produce focused test failures, reduce hidden coupling and regression surface, and make review and incremental regeneration more predictable
61
+ - If a functional spec is too large, use `break-down-func-spec` to split it into multiple smaller, independent ones
62
+ - Judge a functional spec's size yourself before inserting it: estimate the code it implies - new files, functions, data model changes, UI components, error paths, boilerplate, its unit tests - and treat more than ~150 lines as too big, leaving the coding agent headroom
63
+ - Signs a functional spec is too big - one is not proof, several are:
52
64
  - more than one independently testable behavior ("create, edit, delete and archive")
53
65
  - more than three new constructs at once - data structures, UI components, endpoints
54
66
  - several modes or conditional paths, each with its own behavior
55
67
  - core behavior bundled with cross-cutting concerns - retries, pagination, caching, logging
56
68
  - a whole screen with several interactive elements and state transitions
57
69
  - multi-step transformations, joins or aggregations across entities
58
- - a substantial technical component it must build as well as use - an engine, parser, scheduler, layout algorithm, state machine, sync mechanism; it counts toward the limit, and goes in a spec of its own before the one that uses it
59
- - Use `analyze-func-specs` to check a spec (or a batch of specs) against all relevant existing specs in a single batched call; use `resolve-spec-conflict` for each conflicting pair it reports
70
+ - a substantial technical component it must build as well as use - an engine, parser, scheduler, layout algorithm, state machine, sync mechanism; it counts toward the limit, and goes in a functional spec of its own before the one that uses it
71
+ - Use `analyze-func-specs` to check a functional spec (or a batch of them) against all relevant existing ones in a single batched call; use `resolve-spec-conflict` for each conflicting pair it reports
60
72
 
61
73
  ## First-spec bootstrap cost
62
74
  - The first functional spec in a new root module carries implicit implementation cost even when its text describes little behavior
63
- - The renderer may need to create the project structure, package metadata, framework configuration, entry point, initial source files, and unit-test infrastructure before implementing the behavior
64
- - Count that bootstrap work toward the 200-changed-line limit; it is not free setup outside the spec
65
- - Make the first spec the module's simplest useful, independently observable capability
66
- - The first spec must still imply a testable outcome; setup alone is not a functional spec
75
+ - The coding agent may need to create the project structure, package metadata, framework configuration, entry point, initial source files, and unit-test infrastructure before implementing the behavior
76
+ - Count that bootstrap work toward the 200-changed-line limit; it is not free setup outside the functional spec
77
+ - Make the first functional spec the module's simplest useful, independently observable capability
78
+ - The first functional spec must still imply a testable outcome; setup alone is not a functional spec
67
79
  - Prefer one minimal entry point or public operation with a deterministic result that can be invoked and verified
68
- - Defer persistence, integrations, multiple interfaces, branching workflows, and cross-cutting behavior until later specs can build on the generated baseline
69
- - A spec may start on its happy path and be hardened later - validation, edge cases and errors added to it by changing it - once the software has been tried; it must still say exactly what it does for the input it covers
80
+ - Defer persistence, integrations, multiple interfaces, branching workflows, and cross-cutting behavior until later functional specs can build on the generated baseline
81
+ - A functional spec may start on its happy path and be hardened later - validation, edge cases and errors added to it by changing it - once the software has been tried; it must still say exactly what it does for the input it covers
70
82
  - This extra bootstrap cost applies when no previous implementation baseline exists; a module that continues from a `requires` module may already inherit the necessary scaffold
71
83
 
72
84
  ## Chronological ordering
73
- - Specs are rendered incrementally, top to bottom
74
- - The renderer has **no knowledge of future specs** — only previously rendered specs are in context
75
- - A new spec can reference behavior from earlier specs but cannot assume anything about specs that come after it
85
+ - Functional specs are regenerated incrementally, top to bottom
86
+ - The coding agent has **no knowledge of later functional specs** — only those before it are in context
87
+ - A new functional spec can reference behavior from earlier ones but cannot assume anything about those that come after it
76
88
  - Functional specs from `requires` modules are treated as previous requirements — transitively, across the whole ancestor chain
77
- - This order is about what a spec may assume, not what a change costs: turri regenerates a change as a spec diff wherever it sits (`turri-regeneration.md`)
89
+ - This order is about what a functional spec may assume, not what a change costs: turri regenerates a change as a ***plain diff wherever it sits (`turri-regeneration.md`)
78
90
 
79
91
  ## No conflicts
80
- - The new spec must not contradict any existing functional spec
81
- - Before adding, review all existing specs and verify compatibility
92
+ - A new functional spec must not contradict any existing one
93
+ - Before adding, review all existing functional specs and verify compatibility
82
94
  - If ambiguity exists, add explicit detail to eliminate any conflicting interpretation
83
95
 
84
96
  ## Adding a functional spec
85
97
  Every new functional spec - one or a batch - is checked before it is written into the file:
86
98
  1. Draft it, then trim it per `concise-specs.md` to the shortest wording that keeps every fact
87
99
  2. Judge its size against the complexity limit; when it is too big, split it with `break-down-func-spec` and check each part from step 1
88
- 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
89
- 4. Only then write it in, where it belongs (see Placement)
100
+ 3. Check it for conflicts with **one** `analyze-func-specs` call over the new functional spec and every existing one 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
101
+ 4. Pick its func-id per `semantic-ids.md`, unique in the module - and in the batch
102
+ 5. Only then write it in, where it belongs (see Placement), as its `# <func-id>` heading and body - with no test plain file, unless the person asks for its tests (see `test-plain-files.md`)
90
103
 
91
- 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.
104
+ A batch is checked one functional spec at a time, in order: each one's conflict check includes those of the batch already written in. Never write the whole batch in first and check it afterwards - a bad functional spec already in the file skews every later check. A few functional specs are no reason to skip a check.
92
105
 
93
106
  ## Placement
94
- Put a new spec where it fits the module as it reads, not at the end by default:
95
- - **Below every spec it builds on** - each one whose behaviour it references or extends, and the first to use each concept it relies on
96
- - **Above every spec that builds on it** - one that already assumes what it adds
97
- - **Within those bounds, beside the specs of its feature** - usually straight after the last one it extends
107
+ Put a new functional spec where it fits the module as it reads, not at the end by default:
108
+ - **Below every functional spec it builds on** - each one whose behaviour it references or extends, and the first to use each concept it relies on
109
+ - **Above every functional spec that builds on it** - one that already assumes what it adds
110
+ - **Within those bounds, beside the functional specs of its feature** - usually straight after the last one it extends
98
111
  - **At the end** only when it starts something new or fits nowhere better
99
112
 
100
113
  ## Language agnosticism
@@ -102,68 +115,50 @@ Put a new spec where it fits the module as it reads, not at the end by default:
102
115
  - Avoid language-specific terminology: generics syntax, framework annotations, language-specific collection types, decorator syntax, base-class keywords, framings like "POJO" or "dataclass"
103
116
  - General technical terms that are not language-specific are fine: null values, JSON types, HTTP status codes, REST endpoints, etc.
104
117
  - **Naming concrete components is encouraged.** Functional specs can and should refer to concrete domain components, services, or entities (e.g., `:PaymentProcessor:`, `:UserRepository:`, `:DataConverter:`) and their operations (e.g., `:ChargeCard:`, `:FindById:`), pinning down their inputs, outputs, and error behavior. Those names are part of the public contract and survive a language switch. What they must **not** do is bake in how the contract is realized (`@staticmethod`, `class Foo extends Bar`, `List<T>`, `async def`, etc.)
105
- - **Litmus test:** if the project switched from Python to Java (or vice versa), would the functional spec read correctly with only `***implementation reqs***` updated? If yes, the spec is language-agnostic. If the spec itself would need rewording, the construct belongs in implementation reqs.
118
+ - **Litmus test:** if the project switched from Python to Java (or vice versa), would the functional spec read correctly with only `***implementation reqs***` updated? If yes, it is language-agnostic. If the functional spec itself would need rewording, the construct belongs in implementation reqs.
106
119
 
107
120
  ## Disambiguation
108
- - Each functional spec must be unambiguous — the renderer should have only one reasonable interpretation
109
- - If a single line is not enough to fully disambiguate the behavior, use **nested sub-bullets** to add detail
110
- - Nested lines clarify the parent spec — they do not introduce separate functionality
111
- - Even with nested detail, the spec must still imply ≤ 200 lines of code
121
+ - Each functional spec must be unambiguous — the coding agent should have only one reasonable interpretation
122
+ - If the statement line is not enough to fully disambiguate the behavior, add `- ` bullets or sentences under it to add detail
123
+ - The detail clarifies the statement - it does not introduce separate behaviour
124
+ - Even with the detail, the functional spec must still imply ≤ 200 lines of code
112
125
 
113
126
  ## Testability
114
127
  - Every functional spec must describe behavior that can be verified through an observable interface
115
128
  - State the triggering input or action and the deterministic outcome a test can observe
116
129
  - Include relevant outputs, state changes, errors, or externally visible side effects
117
130
  - Do not rely on generated implementation details as the only way to verify the behavior
118
- - If a black-box conformance test cannot be derived from the spec, make the behavior more explicit
119
- - Testability does not require an acceptance test; acceptance tests are reserved for full workflows
131
+ - If a black-box conformance scenario could not be written from the functional spec, make the behavior more explicit
120
132
 
121
133
  ## Deterministic interface
122
- - Specs must be detailed enough that a developer can use the built software without reading the generated code
134
+ - Functional specs must be detailed enough that a developer can use the built software without reading the generated code
123
135
  - All external interfaces must be explicit: REST endpoint paths and HTTP methods, CLI command names and arguments, file formats, message schemas, etc.
124
- - Never leave interface details up to the renderer's discretion
136
+ - Never leave interface details up to the coding agent's discretion
125
137
 
126
138
  ## Encapsulation
127
- - Functionality must be self-contained in the spec text
139
+ - Behaviour must be self-contained in the functional spec's text
128
140
  - `requires` modules only pass on functional specs and `exported_concepts` — never implementation reqs, so do not rely on implementation reqs to convey behavior
129
141
  - Behavior that downstream modules need must be expressed in functional specs, not elsewhere
130
142
 
131
- ## Acceptance tests
132
- - Nest `***acceptance tests***` under a functional spec when verification criteria are needed
133
- - Each acceptance test must be a **full workflow test** — a specific scenario that exercises the functional spec end-to-end, not a unit-level check of a single field or condition
134
- - Do not restate the obvious behavior from the functional spec — simple, direct verifications are already auto-generated as conformance tests. Acceptance tests must go beyond that: multi-step workflows, interactions between concepts, edge-case scenarios, or end-to-end sequences that prove the feature works in a realistic context
135
- - Each acceptance test must be a direct logical consequence of the parent spec — it illustrates, not extends
136
- - Acceptance tests must describe concrete, verifiable outcomes — not vague qualities
137
- - Acceptance tests must not contradict, narrow, or extend beyond the parent spec
138
-
139
- ```plain
140
- Functional spec:
141
- - :Resource: items are returned sorted by creation date in descending order.
142
-
143
- Good - follows from the spec:
144
- - After three :Resource: items are created one after another, listing them returns the last one created first.
145
-
146
- Bad - contradicts it (the spec says descending):
147
- - The first :Resource: listed is the oldest.
148
-
149
- Bad - extends it (the spec says nothing about a limit):
150
- - At most 50 :Resource: items are listed.
151
- ```
143
+ ## Test scenarios live in test plain files
144
+ - A module never holds a `***conformance tests***` or `***acceptance tests***` section, nested or top-level
145
+ - A functional spec's conformance and acceptance scenarios go into its test plain file, `tests/<module>/<func-id>.plain`, and are written only when the person asks for tests (see *Writing scenarios* in `test-plain-files.md`)
146
+ - A functional spec and its test plain file change together, in the same ***plain diff: a new one gets none, unless its tests are asked for; a changed one has its scenarios, if any, reviewed; a split, moved, renamed or deleted one takes its test plain file, if it has one, with it (see *Keeping test plain files in step* in `test-plain-files.md`)
152
147
 
153
148
  ## Format
154
149
 
155
150
  ```plain
156
151
  ***functional specs***
157
152
 
158
- - :App: has an entry point.
159
-
160
- - A :User: can add a :Task:. Only valid :Task: items are added.
153
+ # entry-point
154
+ :App: has an entry point.
161
155
 
162
- - A :User: can send a :Message: to a :Conversation:.
163
- - A :Message: must have non-empty content.
164
- - The :Message: is appended to the end of the :Conversation:.
165
- - All :Participant: members of the :Conversation: can see the new :Message:.
156
+ # add-task
157
+ A :User: can add a :Task:. Only valid :Task: items are added.
166
158
 
167
- ***acceptance tests***
168
- - Sending a :Message: to a :Conversation: with three participants should make the message visible to all three.
159
+ # send-message
160
+ A :User: can send a :Message: to a :Conversation:.
161
+ - A :Message: must have non-empty content.
162
+ - The :Message: is appended to the end of the :Conversation:.
163
+ - All :Participant: members of the :Conversation: can see the new :Message:.
169
164
  ```
@@ -14,7 +14,7 @@ When writing or editing an `***implementation reqs***` section in a `.plain` fil
14
14
  ## `:UnitTests:` lives here (hard rule)
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
- - The unit-test generator reads **only** `***implementation reqs***` — anything about `:UnitTests:` placed elsewhere (e.g. `***test reqs***`) is silently ignored
17
+ - The coding agent reads how to write the unit tests **only** from `***implementation reqs***` — anything about `:UnitTests:` placed elsewhere (e.g. `***test reqs***`) is silently ignored
18
18
  - Phrase each `:UnitTests:` requirement in terms of `:UnitTests:` so the partition stays visible at a glance
19
19
 
20
20
  ## What belongs here
@@ -32,13 +32,13 @@ When writing or editing an `***implementation reqs***` section in a `.plain` fil
32
32
  - Behavior and features → `***functional specs***`
33
33
  - Concept definitions → `***definitions***`
34
34
  - **Conformance-test guidance** → `***test reqs***`
35
- - **Acceptance-test scenarios** → `***acceptance tests***` nested under the relevant functional spec
35
+ - **Test scenarios**, conformance and acceptance → the functional spec's test plain file (see `test-plain-files.md`)
36
36
 
37
37
  ## Unit tests vs conformance tests (common mistake)
38
38
  - Unit-test guidance (`:UnitTests:` framework, structure, mocking) goes **here**, not in `***test reqs***`
39
39
  - `***test reqs***` is exclusively for `:ConformanceTests:` — framework, execution command, mocking policy, environment setup
40
- - Putting unit-test guidance in `***test reqs***` is one of the most common authoring mistakes; the rendered code will silently miss those requirements because the unit-test generator only reads `***implementation reqs***`
41
- - Do not link the unit testing script here (or anywhere in the specs; a link to it is ignored). turri finds it in the project root - `unittests-script:` in `config.turri.yaml`, else the one `run_unittests*.sh` in the root, else the one in `test_scripts/` - and shows it to the coding agent itself. Describe the framework and run command here in words
40
+ - Putting unit-test guidance in `***test reqs***` is one of the most common authoring mistakes; the regenerated code will silently miss those requirements because the coding agent reads unit-test guidance only from `***implementation reqs***`
41
+ - Do not link the unit testing script here (or anywhere in the ***plain; a link to it is ignored). turri finds it in the project root - `unittests-script:` in `config.turri.yaml`, else the one `run_unittests*.sh` in the root, else the one in `test_scripts/` - and shows it to the coding agent itself. Describe the framework and run command here in words
42
42
 
43
43
  ## Encapsulation warning
44
44
  - `requires` modules only pass on functional specs and `exported_concepts` — never implementation reqs
@@ -4,7 +4,7 @@ description: Rules for authoring the two test scripts that an embedded ***plain
4
4
 
5
5
  # Rules for embedded-integration test scripts
6
6
 
7
- When an embedded integration ships its two `test_scripts/` (unit, conformance), these rules apply on top of the contracts in the corresponding `implement-*-testing-script` skills. `project-model.md` covers the rendering and testing workflow.
7
+ When an embedded integration ships its two `test_scripts/` (unit, conformance), these rules apply on top of the contracts in the corresponding `implement-*-testing-script` skills. `project-model.md` covers the regenerating and testing workflow.
8
8
 
9
9
  ## Staging model (read this first)
10
10
 
@@ -24,7 +24,7 @@ This deliberately writes into the host's `src/main/...` and `src/test/...` (or t
24
24
 
25
25
  This rule covers the **mechanics each script must obey** regardless of language: argument handling, exit codes, idempotency, path resolution, output parsing, and the "what NOT to put here" guard rails. The language-specific install / test commands come from the skills; the contract below is invariant.
26
26
 
27
- ## What the `.plain` spec must declare
27
+ ## What the `.plain` file must declare
28
28
 
29
29
  The two scripts are generated from facts in the integration's spec. For an embedded integration, those facts cannot be inferred — they have to be **declared explicitly** in the right section, partitioned by which predefined concept they describe:
30
30
 
@@ -77,7 +77,7 @@ These reqs feed `run_conformance_tests_<lang>`. At minimum, declare:
77
77
  2. **`:ConformanceTests:` framework and execution command** — `mvn test --no-transfer-progress`, `pytest`, `npm test`, `go test ./...`, etc., with any flags / profiles the project requires
78
78
  3. **Fully qualified `:ConformanceTests:` package** (or path / pattern) used to scope discovery, if the runner needs one
79
79
  4. **`:ConformanceTests:` network and secrets policy** — by default the suite runs against the **live provider** (see [`integrations.md`](integrations.md) → *`:ConformanceTests:` always run against the live integration*). Declare the env-var names the script reads (e.g. `<PROVIDER>_API_KEY`), whether the script loads a `.env` file before running, and any specific endpoints that are mocked because they can't be exercised live safely (429, forced 5xx)
80
- 5. **`:ConformanceTests:` pass criteria** — the strict criteria from [*Pass criteria (strict)*](#pass-criteria-strict): at least one test ran AND zero failures / errors / skipped. Reaffirm this in the spec so the renderer knows the runner must parse the test tool's stdout
80
+ 5. **`:ConformanceTests:` pass criteria** — the strict criteria from [*Pass criteria (strict)*](#pass-criteria-strict): at least one test ran AND zero failures / errors / skipped. Reaffirm this in the ***plain so the script's author knows the runner must parse the test tool's stdout
81
81
  6. **`:ConformanceTests:` build / install needs** — anything the conformance project needs before `mvn test` (or equivalent) will work: the host build / install command the script runs first, dependencies, fixtures, schema files, generated stubs
82
82
 
83
83
  Author the conformance facts as one or more entries, phrased in terms of `:ConformanceTests:`:
@@ -115,10 +115,10 @@ output=$(mvn test --no-transfer-progress 2>&1)
115
115
 
116
116
  - **The paths must agree across reqs.** The `:UnitTests:` source path, the `:UnitTests:` package, and the integration source path describe the same module from three angles. Same for the `:ConformanceTests:` location and its package. A mismatch (e.g. test path `src/test/java/com/example/foo` but test package `com.example.bar`) silently produces a green build with stale or zero tests
117
117
  - **Paths are host-relative**, not absolute. `MAIN_PROJECT_FOLDER` comes from `HOST_CODEBASE_ROOT` (declared in the configuration concept); the paths above join onto it
118
- - **The renderer's output folder `$1` mirrors the same layout.** `$1/<integration source path>/*` exists because the renderer emits the generated code into the same package directories it'll be copied into — the `cp -R` is a straight overlay, not a path translation
119
- - **Each fact lives in one place.** If two `***implementation reqs***` entries declare slightly different `:UnitTests:` paths (or two `***test reqs***` entries declare slightly different `:ConformanceTests:` packages), the renderer can't tell which to use. Author each group as a tight cluster (one bullet with sub-bullets) so a future reviewer sees them together
120
- - **Never duplicate a fact across sections.** `:UnitTests:` facts belong **only** in `***implementation reqs***`; `:ConformanceTests:` facts belong **only** in `***test reqs***`. The two groups never overlap — the script generators read each from its own section
121
- - **For non-Java languages**, the facts have language-specific equivalents — Python: `src/foo/`, `tests/foo/`, `tests.foo`; Node: `src/foo/`, `test/foo/`, `test/foo/**/*.test.ts`. The `implement-*-testing-script` skills know the mapping per language, but the spec still has to declare the host-relative paths and packages so the skill knows what to put in the script bodies
118
+ - **The coding agent's output folder `$1` mirrors the same layout.** `$1/<integration source path>/*` exists because the coding agent emits the generated code into the same package directories it'll be copied into — the `cp -R` is a straight overlay, not a path translation
119
+ - **Each fact lives in one place.** If two `***implementation reqs***` entries declare slightly different `:UnitTests:` paths (or two `***test reqs***` entries declare slightly different `:ConformanceTests:` packages), the coding agent can't tell which to use. Author each group as a tight cluster (one bullet with sub-bullets) so a future reviewer sees them together
120
+ - **Never duplicate a fact across sections.** `:UnitTests:` facts belong **only** in `***implementation reqs***`; `:ConformanceTests:` facts belong **only** in `***test reqs***`. The two groups never overlap — the agents read each from its own section
121
+ - **For non-Java languages**, the facts have language-specific equivalents — Python: `src/foo/`, `tests/foo/`, `tests.foo`; Node: `src/foo/`, `test/foo/`, `test/foo/**/*.test.ts`. The `implement-*-testing-script` skills know the mapping per language, but the ***plain still has to declare the host-relative paths and packages so the skill knows what to put in the script bodies
122
122
 
123
123
  ## Common contract (both scripts)
124
124
 
@@ -131,17 +131,17 @@ Both scripts are invoked by turri with positional arguments, on the person's mac
131
131
  - `69` — unrecoverable environment failure (missing toolchain, cannot enter working folder, install failed)
132
132
  - Any other non-zero code — propagated verbatim from the underlying build / test tool
133
133
 
134
- turri passes `$1` (and `$2` for the conformance runner) as **absolute paths** (older renderer versions passed relative ones). Never build a derived path by concatenating a raw argument (`.tmp/$1`, `<lang>_$1`, `$current_dir/$2`) — with an absolute argument that produces a doubled path (`/project//abs/path/...`). Use the argument as-is where a path is needed, take its `basename` when naming a scratch folder, and resolve `$2` to absolute (if it isn't already) before any `cd`
134
+ turri passes `$1` (and `$2` for the conformance runner) as **absolute paths** (older harnesses passed relative ones). Never build a derived path by concatenating a raw argument (`.tmp/$1`, `<lang>_$1`, `$current_dir/$2`) — with an absolute argument that produces a doubled path (`/project//abs/path/...`). Use the argument as-is where a path is needed, take its `basename` when naming a scratch folder, and resolve `$2` to absolute (if it isn't already) before any `cd`
135
135
  3. **Echo the toolchain home at the top** — the first thing a developer checks when CI breaks. For Java: `JAVA_HOME`. For Python: the active interpreter (`python --version` / `which python`). For Node: `node --version`. For Go: `go env GOROOT`. Pick the variable whose value most often explains "why does it work locally but not on the CI runner?"
136
136
  4. **Respect `VERBOSE=1`.** Gate chatty diagnostic prints behind `if [ "${VERBOSE:-}" = "1" ]` (and the PowerShell equivalent). Errors and key step markers print unconditionally
137
- 5. **Resolve paths relative to the script, not `$PWD`.** Use `"$(cd "$(dirname "$0")/<relative-path-to-anchor>" && pwd)"`. Hard-coded `../../` chains break the moment the renderer's `cwd` changes
137
+ 5. **Resolve paths relative to the script, not `$PWD`.** Use `"$(cd "$(dirname "$0")/<relative-path-to-anchor>" && pwd)"`. Hard-coded `../../` chains break the moment turri's `cwd` changes
138
138
  6. **Create destination directories before copying.** `mkdir -p` before any `cp -R` / `rsync` / `robocopy` — most copy commands do not create intermediate directories and fail silently in some shells
139
139
  7. **Scope destructive operations narrowly.** Any `rm -rf` (or `Remove-Item -Recurse -Force`) targets only the module's own package path inside the working folder — never the host's `src/`, `target/`, `node_modules/`, `build/`, or `dist/` at the project root. The conformance script cleans the host's build-output directory (e.g. `./target`) only as part of its own build / install step, and removes its system-temp scratch folder on exit
140
140
  8. **Print where you are before you `cd`.** `echo "Moving to: $DIR"` saves an hour of debugging when paths are wrong. PowerShell: `Write-Host "Moving to: $DIR"`
141
141
 
142
142
  ## 1. `run_unittests_<lang>` — copy into the host, then run unit tests there
143
143
 
144
- Receives one positional argument: the renderer's build output folder (`plain_modules/<module>/code/`, absolute).
144
+ Receives one positional argument: the build output folder (`plain_modules/<module>/code/`, absolute).
145
145
 
146
146
  Purpose: stage the generated code **into the host codebase at the module's package path** and run the module's unit tests + language-appropriate quality gates against the host project from inside the host root.
147
147
 
@@ -162,17 +162,17 @@ Required steps:
162
162
  Hard rules:
163
163
 
164
164
  - **Self-contained.** The script stages `$1` itself on every run; it never relies on another script having run first
165
- - **Never run the full test suite** when scoping is possible. A per-module script that runs the entire host's tests wastes minutes on every render iteration
165
+ - **Never run the full test suite** when scoping is possible. A per-module script that runs the entire host's tests wastes minutes on every regeneration
166
166
 
167
167
  ## 2. `run_conformance_tests_<lang>` — copy into the host, build it, then run the external suite
168
168
 
169
- Receives two positional arguments: the renderer's build output folder (`$1`, `plain_modules/<module>/code/`) and the conformance-tests folder (`$2`, `plain_modules/<module>/tests/` — the module's whole conformance suite), both absolute.
169
+ Receives two positional arguments: the build output folder (`$1`, `plain_modules/<module>/code/`) and the conformance-tests folder (`$2`, `plain_modules/<module>/tests/` — the module's whole conformance suite), both absolute.
170
170
 
171
- Purpose: stage the generated code into the host, build / install the host, and run the whole conformance suite in `$2` against that build. The conformance suite is a separate project that consumes the integration as a dependency from a local cache (`~/.m2`, `node_modules`, the language equivalent), so the script installs the host itself first — otherwise the suite links against whatever was last built, which may not be the renderer's most recent output. turri runs it once per check, and its exit code decides whether the conformance tests pass.
171
+ Purpose: stage the generated code into the host, build / install the host, and run the whole conformance suite in `$2` against that build. The conformance suite is a separate project that consumes the integration as a dependency from a local cache (`~/.m2`, `node_modules`, the language equivalent), so the script installs the host itself first — otherwise the suite links against whatever was last built, which may not be the most recent regenerated code. turri runs it once per check, and its exit code decides whether the conformance tests pass.
172
172
 
173
173
  Required steps:
174
174
 
175
- 1. Validate `$1` and `$2`. Resolve `$2` to an absolute path if it isn't one already (newer renderers pass it absolute; older ones passed it relative to the invocation directory)
175
+ 1. Validate `$1` and `$2`. Resolve `$2` to an absolute path if it isn't one already (turri passes it absolute; older harnesses passed it relative to the invocation directory)
176
176
  2. Resolve the host codebase root from the configured env var, `rm -rf` the module's main + test package directories under the host's source tree, `mkdir -p` the destination directories, and copy `$1/src/...` into the host's source tree at the module's package path — **the same staging as `run_unittests`**
177
177
  3. `cd` into the host codebase root, verify with an explicit exit-code check
178
178
  4. Clean the host's build-output directory before compiling — stale class / object files from a previous build cause confusing link-time mismatches when the contract has changed. Maven: `rm -rf ./target`. Cargo: `cargo clean -p <pkg>`. Go: `go clean -cache` (usually unnecessary, but mention if applicable). For npm projects with incremental builds disabled, wipe the relevant `dist/` / `build/` folder
@@ -195,7 +195,7 @@ Required steps:
195
195
  - Bash: `output=$(mvn test --no-transfer-progress 2>&1)` (or the language equivalent)
196
196
  - PowerShell: `$output = & <cmd> 2>&1 | Out-String`
197
197
  10. **Parse the captured output strictly** (see *Pass criteria* below) — don't trust the test tool's exit code alone
198
- 11. On the failure path: print the captured output unconditionally so the renderer (and the user) can see what failed
198
+ 11. On the failure path: print the captured output unconditionally so turri (and the user) can see what failed
199
199
  12. On the success path: print the output only if `VERBOSE=1`
200
200
 
201
201
  ### Secrets and `.env` handling
@@ -238,15 +238,15 @@ These are the **only** valid pass criteria. Anything outside this list is a fail
238
238
 
239
239
  Failure cases — each must be detected explicitly:
240
240
 
241
- - `Tests run: 0` (or the language equivalent) → **failure**. The renderer must never be told "green" when nothing ran. Exit `1` per the shared testing-script rules (the "no tests discovered" exit code)
241
+ - `Tests run: 0` (or the language equivalent) → **failure**. turri must never be told "green" when nothing ran. Exit `1` per the shared testing-script rules (the "no tests discovered" exit code)
242
242
  - Any non-zero `Failures:`, `Errors:`, or `Skipped:` count → **failure**. Dump the captured output and propagate the test tool's exit code
243
243
  - The test tool exited non-zero but the summary line shows `Tests run: 0` → still a `1` (no-tests-discovered), not the tool's own exit code
244
244
 
245
- **Why parse stdout instead of trusting the test tool's exit code.** Every major test runner returns `0` when zero test classes match a filter. Maven Surefire, pytest with no collected tests, `go test ./pkg/that/has/no/_test.go/files`, Jest with an empty pattern — all green-by-default. The renderer's contract is "tests must run AND must pass" — the exit code alone cannot express that.
245
+ **Why parse stdout instead of trusting the test tool's exit code.** Every major test runner returns `0` when zero test classes match a filter. Maven Surefire, pytest with no collected tests, `go test ./pkg/that/has/no/_test.go/files`, Jest with an empty pattern — all green-by-default. turri's contract is "tests must run AND must pass" — the exit code alone cannot express that.
246
246
 
247
247
  ## Cross-cutting rules
248
248
 
249
- - **No secrets in scripts.** Read credentials from env vars the renderer (or the user's shell) already sets. If a required env var is missing, fail fast with a clear `Error: $FOO is required for ...` and exit `69`. Never hardcode an API key, never read from a checked-in file
249
+ - **No secrets in scripts.** Read credentials from env vars turri (or the user's shell) already sets. If a required env var is missing, fail fast with a clear `Error: $FOO is required for ...` and exit `69`. Never hardcode an API key, never read from a checked-in file
250
250
  - **Mirror the package / module path exactly.** A typo in the package segment (e.g. one wrong directory in `com/example/foo/...` or `host_pkg/foo/bar/...`) makes `rm -rf` silently do nothing and the subsequent copy put files in the wrong place. Both produce a **green** build with stale code. Derive the package path from the `host-codebase` concept; never retype it inline
251
251
  - **Don't add cleverness to the script that belongs in the build.** If you're tempted to `grep` the test output for more than the pass/fail summary, change the test or the test-runner config instead. The script is a thin contract — keep it that way
252
252
  - **Don't use shortcut profiles that skip quality gates.** Maven's `-Pfast`, Gradle's `-x check`, npm's `--ignore-scripts`, pytest's `--no-cov`, `-DskipTests` anywhere except the conformance script's two build / install steps (the host install and the conformance project's compile, where the tests run right after) — all defeat the purpose of these scripts. The build's full quality gate (tests + lint + coverage thresholds) must run for unit and conformance
@@ -267,7 +267,7 @@ Use them as a template when adding a new embedded integration in Java / Maven
267
267
  1. Copy the two scripts from a working embedded-integration module into the project's `test_scripts/`
268
268
  2. Search-and-replace the package segment everywhere it appears — including the test-filter argument (the most commonly missed spot)
269
269
  3. `chmod +x` both (and verify ACLs on Windows for the `.ps1` siblings)
270
- 4. Do not link them from the specs: turri finds them in the project root - `config.turri.yaml` (`unittests-script:`, `conformance-tests-script:`), else the one of each kind in the root, else in `test_scripts/` - and shows them to the agents itself. If `test_scripts/` ends up with two scripts of one kind, name the one to use in `config.turri.yaml`.
271
- 5. Smoke-test by running each script manually with the renderer's output folder as `$1` (and the conformance-tests folder as `$2` for the conformance runner). Confirm exit codes match what the renderer expects
270
+ 4. Do not link them from the ***plain: turri finds them in the project root - `config.turri.yaml` (`unittests-script:`, `conformance-tests-script:`), else the one of each kind in the root, else in `test_scripts/` - and shows them to the agents itself. If `test_scripts/` ends up with two scripts of one kind, name the one to use in `config.turri.yaml`.
271
+ 5. Smoke-test by running each script manually with the build output folder as `$1` (and the conformance-tests folder as `$2` for the conformance runner). Confirm exit codes match what turri expects
272
272
 
273
273
  For non-Java languages, the skills [`implement-unit-testing-script`](../skills/implement-unit-testing-script/SKILL.md), and [`implement-conformance-testing-script`](../skills/implement-conformance-testing-script/SKILL.md) adapt the contract above to Python, Node.js, Go, Rust, Flutter, and others. Always route script creation through these skills so the cross-cutting rules above are applied uniformly.