@turri-dev/cli 0.0.0-stage → 0.1.1

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 (315) hide show
  1. package/.pi/themes/turri-dark.json +80 -0
  2. package/.pi/themes/turri-light.json +82 -0
  3. package/LICENSE +21 -0
  4. package/README.md +272 -2
  5. package/assets/jellyfish/dark-00.png +0 -0
  6. package/assets/jellyfish/dark-01.png +0 -0
  7. package/assets/jellyfish/dark-02.png +0 -0
  8. package/assets/jellyfish/dark-03.png +0 -0
  9. package/assets/jellyfish/dark-04.png +0 -0
  10. package/assets/jellyfish/dark-05.png +0 -0
  11. package/assets/jellyfish/dark-06.png +0 -0
  12. package/assets/jellyfish/dark-07.png +0 -0
  13. package/assets/jellyfish/dark-08.png +0 -0
  14. package/assets/jellyfish/dark-09.png +0 -0
  15. package/assets/jellyfish/dark-10.png +0 -0
  16. package/assets/jellyfish/dark-11.png +0 -0
  17. package/assets/jellyfish/dark-12.png +0 -0
  18. package/assets/jellyfish/dark-13.png +0 -0
  19. package/assets/jellyfish/dark-14.png +0 -0
  20. package/assets/jellyfish/fallback.txt +252 -0
  21. package/assets/jellyfish/light-00.png +0 -0
  22. package/assets/jellyfish/light-01.png +0 -0
  23. package/assets/jellyfish/light-02.png +0 -0
  24. package/assets/jellyfish/light-03.png +0 -0
  25. package/assets/jellyfish/light-04.png +0 -0
  26. package/assets/jellyfish/light-05.png +0 -0
  27. package/assets/jellyfish/light-06.png +0 -0
  28. package/assets/jellyfish/light-07.png +0 -0
  29. package/assets/jellyfish/light-08.png +0 -0
  30. package/assets/jellyfish/light-09.png +0 -0
  31. package/assets/jellyfish/light-10.png +0 -0
  32. package/assets/jellyfish/light-11.png +0 -0
  33. package/assets/jellyfish/light-12.png +0 -0
  34. package/assets/jellyfish/light-13.png +0 -0
  35. package/assets/jellyfish/light-14.png +0 -0
  36. package/bin/turri.mjs +29 -0
  37. package/dist/ask.js +149 -0
  38. package/dist/brand.js +50 -0
  39. package/dist/btw.js +174 -0
  40. package/dist/chat-models.js +37 -0
  41. package/dist/chat-skills.js +18 -0
  42. package/dist/cli.js +178 -0
  43. package/dist/config-command.js +197 -0
  44. package/dist/config-edit.js +367 -0
  45. package/dist/config.js +489 -0
  46. package/dist/conform-cli.js +29 -0
  47. package/dist/cultivate-cli.js +110 -0
  48. package/dist/drift-cli.js +25 -0
  49. package/dist/environment.js +70 -0
  50. package/dist/extension.js +2372 -0
  51. package/dist/genome.js +301 -0
  52. package/dist/graph.js +246 -0
  53. package/dist/identity.js +35 -0
  54. package/dist/init-config.js +511 -0
  55. package/dist/judge.js +62 -0
  56. package/dist/lineage-cli.js +13 -0
  57. package/dist/loop-cli.js +132 -0
  58. package/dist/loop-tools.js +225 -0
  59. package/dist/mature-tools.js +193 -0
  60. package/dist/model-check.js +117 -0
  61. package/dist/module-report.js +9 -0
  62. package/dist/pi-launch.js +31 -0
  63. package/dist/pi.js +813 -0
  64. package/dist/plain/check.js +76 -0
  65. package/dist/plain/concepts.js +213 -0
  66. package/dist/plain/errors.js +43 -0
  67. package/dist/plain/files.js +57 -0
  68. package/dist/plain/highlight.js +195 -0
  69. package/dist/plain/index.js +15 -0
  70. package/dist/plain/liquid.js +129 -0
  71. package/dist/plain/markdown.js +208 -0
  72. package/dist/plain/parser.js +752 -0
  73. package/dist/plain/plain.tmLanguage.json +124 -0
  74. package/dist/plain/spec.js +291 -0
  75. package/dist/plain/stdlib.js +44 -0
  76. package/dist/question-dialog.js +125 -0
  77. package/dist/questioning.js +109 -0
  78. package/dist/quiet.js +125 -0
  79. package/dist/regenerate/activity.js +187 -0
  80. package/dist/regenerate/agent-env.js +190 -0
  81. package/dist/regenerate/agent-shell.js +114 -0
  82. package/dist/regenerate/arbiter.js +133 -0
  83. package/dist/regenerate/audit.js +203 -0
  84. package/dist/regenerate/cases.js +83 -0
  85. package/dist/regenerate/change-view.js +102 -0
  86. package/dist/regenerate/choose-conformance.js +117 -0
  87. package/dist/regenerate/chunk-plan.js +625 -0
  88. package/dist/regenerate/codebase.js +75 -0
  89. package/dist/regenerate/command-check.js +312 -0
  90. package/dist/regenerate/compaction.js +20 -0
  91. package/dist/regenerate/confine.js +310 -0
  92. package/dist/regenerate/conform.js +133 -0
  93. package/dist/regenerate/conformance-agents.js +955 -0
  94. package/dist/regenerate/conformance.js +936 -0
  95. package/dist/regenerate/conversation-writes.js +100 -0
  96. package/dist/regenerate/credentials.js +88 -0
  97. package/dist/regenerate/debug-log.js +228 -0
  98. package/dist/regenerate/debugger.js +90 -0
  99. package/dist/regenerate/delivery.js +19 -0
  100. package/dist/regenerate/diagnose-job.js +40 -0
  101. package/dist/regenerate/diagnose.js +81 -0
  102. package/dist/regenerate/diff-view.js +240 -0
  103. package/dist/regenerate/drift.js +194 -0
  104. package/dist/regenerate/engine.js +118 -0
  105. package/dist/regenerate/environment-error.js +220 -0
  106. package/dist/regenerate/job-log.js +102 -0
  107. package/dist/regenerate/job-panel.js +336 -0
  108. package/dist/regenerate/jobs-tree.js +300 -0
  109. package/dist/regenerate/jobs.js +427 -0
  110. package/dist/regenerate/lanes.js +32 -0
  111. package/dist/regenerate/lineage.js +384 -0
  112. package/dist/regenerate/loop.js +1435 -0
  113. package/dist/regenerate/masking.js +95 -0
  114. package/dist/regenerate/notes.js +397 -0
  115. package/dist/regenerate/os-sandbox.js +243 -0
  116. package/dist/regenerate/paths.js +165 -0
  117. package/dist/regenerate/plain-palette.js +83 -0
  118. package/dist/regenerate/prompt.js +704 -0
  119. package/dist/regenerate/records.js +294 -0
  120. package/dist/regenerate/regenerate.js +598 -0
  121. package/dist/regenerate/regression.js +181 -0
  122. package/dist/regenerate/release.js +262 -0
  123. package/dist/regenerate/requires.js +241 -0
  124. package/dist/regenerate/resources.js +164 -0
  125. package/dist/regenerate/self-check.js +111 -0
  126. package/dist/regenerate/services.js +155 -0
  127. package/dist/regenerate/shell.js +319 -0
  128. package/dist/regenerate/side-panel.js +278 -0
  129. package/dist/regenerate/spec-map-view.js +574 -0
  130. package/dist/regenerate/spec-map.js +561 -0
  131. package/dist/regenerate/spec-steps.js +527 -0
  132. package/dist/regenerate/state.js +10 -0
  133. package/dist/regenerate/steer.js +91 -0
  134. package/dist/regenerate/steering.js +119 -0
  135. package/dist/regenerate/stop-report.js +161 -0
  136. package/dist/regenerate/submit-work.js +71 -0
  137. package/dist/regenerate/test-kinds.js +124 -0
  138. package/dist/regenerate/test-scripts.js +695 -0
  139. package/dist/regenerate/testing.js +406 -0
  140. package/dist/regenerate/transcript-view.js +1 -0
  141. package/dist/regenerate/unit-gate.js +20 -0
  142. package/dist/regenerate/unit-review.js +347 -0
  143. package/dist/regenerate/web.js +256 -0
  144. package/dist/regenerate/workspace.js +99 -0
  145. package/dist/regenerate-cli.js +68 -0
  146. package/dist/release-agent.js +114 -0
  147. package/dist/release-cli.js +131 -0
  148. package/dist/release-tools.js +148 -0
  149. package/dist/review/live.js +165 -0
  150. package/dist/rules.js +47 -0
  151. package/dist/self-invocation.js +110 -0
  152. package/dist/setup.js +245 -0
  153. package/dist/skill-progress.js +78 -0
  154. package/dist/skill.js +149 -0
  155. package/dist/skills.js +74 -0
  156. package/dist/spec-diff-cli.js +37 -0
  157. package/dist/spec-tools.js +155 -0
  158. package/dist/stack.js +158 -0
  159. package/dist/stacks.js +97 -0
  160. package/dist/stdlib.js +100 -0
  161. package/dist/terminal-images.js +46 -0
  162. package/dist/tools.js +242 -0
  163. package/dist/validate-cli.js +52 -0
  164. package/docs/README.md +58 -0
  165. package/docs/authoring-plain.md +245 -0
  166. package/docs/config.md +353 -0
  167. package/docs/deploy.md +109 -0
  168. package/docs/development.md +75 -0
  169. package/docs/headless.md +148 -0
  170. package/docs/images/how-turri-works.svg +50 -0
  171. package/docs/images/turri-banner.png +0 -0
  172. package/docs/installation.md +118 -0
  173. package/docs/parser.md +108 -0
  174. package/docs/regenerating.md +1116 -0
  175. package/docs/sandbox.md +233 -0
  176. package/docs/skills-and-gates.md +254 -0
  177. package/docs/theming.md +76 -0
  178. package/docs/using.md +454 -0
  179. package/genome/rules/bullet-continuation.md +69 -0
  180. package/genome/rules/concise-specs-examples.md +431 -0
  181. package/genome/rules/concise-specs-integration-examples.md +270 -0
  182. package/genome/rules/concise-specs.md +80 -0
  183. package/genome/rules/definitions.md +107 -0
  184. package/genome/rules/examples/integration-embedded-testing/run_conformance_tests_java.sh +163 -0
  185. package/genome/rules/examples/integration-embedded-testing/run_unittests_java.sh +51 -0
  186. package/genome/rules/exported-concepts.md +39 -0
  187. package/genome/rules/func-specs.md +129 -0
  188. package/genome/rules/impl-reqs.md +68 -0
  189. package/genome/rules/import-modules.md +48 -0
  190. package/genome/rules/integration-embedded-testing.md +276 -0
  191. package/genome/rules/integration-embedded.md +171 -0
  192. package/genome/rules/integration-standalone.md +135 -0
  193. package/genome/rules/integrations.md +137 -0
  194. package/genome/rules/linked-resources.md +69 -0
  195. package/genome/rules/module-structure.md +105 -0
  196. package/genome/rules/project-model.md +88 -0
  197. package/genome/rules/required-concepts.md +44 -0
  198. package/genome/rules/requires-modules.md +80 -0
  199. package/genome/rules/stdlib.md +73 -0
  200. package/genome/rules/test-reqs.md +57 -0
  201. package/genome/skills/add-acceptance-test/SKILL.md +100 -0
  202. package/genome/skills/add-concept/SKILL.md +71 -0
  203. package/genome/skills/add-functional-spec/SKILL.md +84 -0
  204. package/genome/skills/add-functional-specs/SKILL.md +118 -0
  205. package/genome/skills/add-implementation-requirement/SKILL.md +86 -0
  206. package/genome/skills/add-resource/SKILL.md +105 -0
  207. package/genome/skills/add-template/SKILL.md +64 -0
  208. package/genome/skills/add-test-requirement/SKILL.md +73 -0
  209. package/genome/skills/analyze-2-func-specs/SKILL.md +101 -0
  210. package/genome/skills/analyze-func-specs/SKILL.md +123 -0
  211. package/genome/skills/analyze-if-func-spec-too-complex/SKILL.md +211 -0
  212. package/genome/skills/break-down-func-spec/SKILL.md +205 -0
  213. package/genome/skills/brood/SKILL.md +229 -0
  214. package/genome/skills/brood/references/intent.md +35 -0
  215. package/genome/skills/brood/references/product.md +101 -0
  216. package/genome/skills/brood/references/stack.md +61 -0
  217. package/genome/skills/brood/references/testing.md +56 -0
  218. package/genome/skills/bud/SKILL.md +148 -0
  219. package/genome/skills/bud/references/checklist.md +44 -0
  220. package/genome/skills/bud/references/intent.md +30 -0
  221. package/genome/skills/check-plain-env/SKILL.md +285 -0
  222. package/genome/skills/consolidate-concepts/SKILL.md +192 -0
  223. package/genome/skills/create-import-module/SKILL.md +104 -0
  224. package/genome/skills/create-requires-module/SKILL.md +109 -0
  225. package/genome/skills/debug-specs/SKILL.md +188 -0
  226. package/genome/skills/implement-conformance-testing-script/SKILL.md +238 -0
  227. package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_cypress.ps1 +337 -0
  228. package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_golang.ps1 +111 -0
  229. package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +136 -0
  230. package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.ps1 +103 -0
  231. package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +150 -0
  232. package/genome/skills/implement-unit-testing-script/SKILL.md +160 -0
  233. package/genome/skills/implement-unit-testing-script/assets/run_unittests_flutter.ps1 +87 -0
  234. package/genome/skills/implement-unit-testing-script/assets/run_unittests_golang.ps1 +73 -0
  235. package/genome/skills/implement-unit-testing-script/assets/run_unittests_java.sh +72 -0
  236. package/genome/skills/implement-unit-testing-script/assets/run_unittests_python.ps1 +81 -0
  237. package/genome/skills/implement-unit-testing-script/assets/run_unittests_python.sh +98 -0
  238. package/genome/skills/implement-unit-testing-script/assets/run_unittests_react.ps1 +87 -0
  239. package/genome/skills/init-plain-project/SKILL.md +117 -0
  240. package/genome/skills/init-plain-project/references/checklist.md +30 -0
  241. package/genome/skills/mature/SKILL.md +126 -0
  242. package/genome/skills/refactor-module/SKILL.md +196 -0
  243. package/genome/skills/resolve-section-ownership/SKILL.md +64 -0
  244. package/genome/skills/resolve-spec-conflict/SKILL.md +96 -0
  245. package/genome/skills/spawn/SKILL.md +163 -0
  246. package/package.json +68 -4
  247. package/stdlib/backend/common.plain +25 -0
  248. package/stdlib/backend/conformance/common.plain +12 -0
  249. package/stdlib/backend/conformance/go-gin.plain +9 -0
  250. package/stdlib/backend/conformance/go-nethttp.plain +9 -0
  251. package/stdlib/backend/conformance/java-springboot.plain +9 -0
  252. package/stdlib/backend/conformance/python-django.plain +9 -0
  253. package/stdlib/backend/conformance/python-fastapi.plain +9 -0
  254. package/stdlib/backend/conformance/python-flask.plain +9 -0
  255. package/stdlib/backend/conformance/rust-axum.plain +9 -0
  256. package/stdlib/backend/conformance/typescript-express.plain +9 -0
  257. package/stdlib/backend/conformance/typescript-fastify.plain +9 -0
  258. package/stdlib/backend/conformance/typescript-nestjs.plain +9 -0
  259. package/stdlib/backend/go-gin.plain +18 -0
  260. package/stdlib/backend/go-nethttp.plain +18 -0
  261. package/stdlib/backend/java-springboot.plain +19 -0
  262. package/stdlib/backend/python-django.plain +19 -0
  263. package/stdlib/backend/python-fastapi.plain +23 -0
  264. package/stdlib/backend/python-flask.plain +23 -0
  265. package/stdlib/backend/rust-axum.plain +17 -0
  266. package/stdlib/backend/typescript-express.plain +19 -0
  267. package/stdlib/backend/typescript-fastify.plain +19 -0
  268. package/stdlib/backend/typescript-nestjs.plain +19 -0
  269. package/stdlib/cli/common.plain +17 -0
  270. package/stdlib/cli/conformance/common.plain +11 -0
  271. package/stdlib/cli/conformance/go-cobra.plain +9 -0
  272. package/stdlib/cli/conformance/go-flag.plain +9 -0
  273. package/stdlib/cli/conformance/java-picocli.plain +9 -0
  274. package/stdlib/cli/conformance/python-argparse.plain +9 -0
  275. package/stdlib/cli/conformance/python-click.plain +9 -0
  276. package/stdlib/cli/conformance/python-typer.plain +9 -0
  277. package/stdlib/cli/conformance/rust-clap.plain +9 -0
  278. package/stdlib/cli/conformance/typescript-commander.plain +9 -0
  279. package/stdlib/cli/go-cobra.plain +14 -0
  280. package/stdlib/cli/go-flag.plain +14 -0
  281. package/stdlib/cli/java-picocli.plain +15 -0
  282. package/stdlib/cli/python-argparse.plain +18 -0
  283. package/stdlib/cli/python-click.plain +16 -0
  284. package/stdlib/cli/python-typer.plain +16 -0
  285. package/stdlib/cli/rust-clap.plain +14 -0
  286. package/stdlib/cli/typescript-commander.plain +17 -0
  287. package/stdlib/frontend/angular.plain +17 -0
  288. package/stdlib/frontend/common.plain +17 -0
  289. package/stdlib/frontend/conformance/angular.plain +5 -0
  290. package/stdlib/frontend/conformance/common.plain +11 -0
  291. package/stdlib/frontend/conformance/react-vite.plain +5 -0
  292. package/stdlib/frontend/conformance/sveltekit-spa.plain +5 -0
  293. package/stdlib/frontend/conformance/vue-vite.plain +5 -0
  294. package/stdlib/frontend/react-vite.plain +16 -0
  295. package/stdlib/frontend/sveltekit-spa.plain +16 -0
  296. package/stdlib/frontend/vue-vite.plain +16 -0
  297. package/stdlib/lang/go.plain +13 -0
  298. package/stdlib/lang/java.plain +12 -0
  299. package/stdlib/lang/python.plain +18 -0
  300. package/stdlib/lang/rust.plain +12 -0
  301. package/stdlib/lang/typescript.plain +13 -0
  302. package/stdlib/library/common.plain +15 -0
  303. package/stdlib/library/conformance/common.plain +9 -0
  304. package/stdlib/library/conformance/go.plain +9 -0
  305. package/stdlib/library/conformance/java-gradle.plain +9 -0
  306. package/stdlib/library/conformance/java-maven.plain +9 -0
  307. package/stdlib/library/conformance/python.plain +9 -0
  308. package/stdlib/library/conformance/rust.plain +9 -0
  309. package/stdlib/library/conformance/typescript.plain +9 -0
  310. package/stdlib/library/go.plain +12 -0
  311. package/stdlib/library/java-gradle.plain +13 -0
  312. package/stdlib/library/java-maven.plain +13 -0
  313. package/stdlib/library/python.plain +13 -0
  314. package/stdlib/library/rust.plain +12 -0
  315. package/stdlib/library/typescript.plain +15 -0
@@ -0,0 +1,80 @@
1
+ ---
2
+ description: Conciseness and plain-language rules that keep .plain specs reviewable by a human
3
+ ---
4
+
5
+ # Rules for keeping `.plain` specs concise
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.
8
+
9
+ ## Why this matters
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
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
+
16
+ ## Do not write the obvious
17
+
18
+ Delete any line a competent reader would already assume. Ask of every line: *if this were missing, would anything be built differently?* If not, cut it.
19
+
20
+ Do not write:
21
+
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
+ - 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
25
+ - Standard behavior of a technology already named in `***implementation reqs***` (an HTTP framework parses HTTP; a database driver opens connections)
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")
29
+
30
+ Worked pairs for every item above — padding, rationale, defaults, technology behavior,
31
+ meta-commentary, and duplication of an `import` — are in `concise-specs-examples.md`.
32
+
33
+ ## Use plain words
34
+
35
+ - Prefer the shortest word that is still exact; a technical term needs to be exact, an elaborate one is not
36
+ - Write short sentences: one clause plus, at most, one qualifier
37
+ - Use the same word for the same thing every time — synonym variety reads as two different things
38
+ - 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
39
+ - Do not hedge: `should ideally`, `may optionally`, `typically`, `generally`, `if possible`. A spec states one behavior; a hedge tells the renderer to guess
40
+
41
+ | Do not write | Write |
42
+ |---|---|
43
+ | utilize, leverage | use |
44
+ | facilitate, enable the ability to | let, or name the action |
45
+ | in order to | to |
46
+ | prior to / subsequent to | before / after |
47
+ | in the event that | if |
48
+ | is responsible for handling | handles |
49
+ | performs the validation of | validates |
50
+ | a plurality of | several, or a number |
51
+ | terminate, initiate | stop, start |
52
+ | functionality for X | X |
53
+
54
+ ## Keep the shape small
55
+
56
+ - One statement per bullet, one bullet per fact (see `bullet-continuation.md`)
57
+ - Nest a sub-bullet only to remove a real ambiguity; a sub-bullet that merely elaborates is filler
58
+ - 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`)
59
+ - Tables, prose paragraphs, and code blocks do not belong in a section; external artifacts are linked from `resources/` (see `linked-resources.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 the renderer sees each part (see `module-structure.md`, and *Split one crowded bullet across its owning sections* in `concise-specs-examples.md`)
61
+
62
+ ## Terse is not a defect
63
+
64
+ 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.
65
+
66
+ - Add a word only to make a line correct, unambiguous, or checkable — never to make it read better
67
+ - Do not merge short bullets into one sentence for rhythm, and do not open a section or a bullet with a lead-in
68
+ - The bar is the other rules — correct, intent intact, reviewable, testable. A spec that clears them is finished however clipped it sounds
69
+ - Filler is not neutral: the renderer reads every line as a requirement, so a line written for flow can invent one
70
+
71
+ ## Review pass before writing to disk
72
+
73
+ Read the drafted lines once more and apply, in order:
74
+
75
+ 1. **The deletion test** — cut every line whose removal would change nothing about what gets built
76
+ 2. **The word test** — replace every ornate word with a plain one, and delete every uncheckable adjective, adverb, and hedge
77
+ 3. **The duplication test** — cut anything already stated in this file, an `import`, or a `requires` chain
78
+ 4. **The read-aloud test** — a line you cannot read aloud in one breath is either two facts or one padded one
79
+
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 a spec cut past its content looks like.
@@ -0,0 +1,107 @@
1
+ ---
2
+ description: Rules for writing ***definitions*** sections in .plain files
3
+ ---
4
+
5
+ # Rules for writing `***definitions***`
6
+
7
+ When writing or editing a `***definitions***` section in a `.plain` file, always follow these rules:
8
+
9
+ ## Concept syntax
10
+ - Wrap concept names in colons: `:ConceptName:`
11
+ - Use CamelCase starting with an uppercase letter
12
+ - Valid characters: letters, digits, `+`, `-`, `.`, `_`
13
+
14
+ ## Uniqueness
15
+ - Concept names must be globally unique across the spec and all its imports
16
+ - Check for collisions with concepts coming from `import` and `requires` modules before adding
17
+
18
+ ## Predefined concepts (do not redefine)
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
21
+
22
+ | Predefined concept | Meaning |
23
+ |--------------------|---------|
24
+ | `:plainDefinitions:` | Content of the `***definitions***` section |
25
+ | `:plainImplementationReqs:` | Content of the `***implementation reqs***` section |
26
+ | `:plainFunctionality:` | Content of the `***functional specs***` section |
27
+ | `:plainTestReqs:` | Content of the `***test reqs***` section |
28
+ | `:Implementation:` | The system implementing `:plainFunctionality:` |
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 |
33
+
34
+ ## Conciseness
35
+ - A definition is one plain sentence plus, where needed, its attributes — see `concise-specs.md`
36
+ - Never restate the concept name as its own definition, and never explain why the concept exists
37
+
38
+ ## Define before use
39
+ - A concept must be defined before it is referenced in any section (definitions, implementation reqs, functional specs, test reqs)
40
+ - Sources of definitions: the module's own `***definitions***`, an `import`ed module's definitions, or a `require`d module's `exported_concepts`
41
+
42
+ ## No circular references
43
+ - Concept references must not form cycles — if A references B, then B must not reference A (directly or indirectly)
44
+ - Insert each concept after any concepts it references
45
+
46
+ Bad — circular:
47
+
48
+ ```plain
49
+ ***definitions***
50
+
51
+ - :Customer: is a user who has placed at least one :Order:.
52
+
53
+ - :Order: is placed by :Customer: and contains :OrderItem: entries.
54
+ ```
55
+
56
+ `:Order:` references `:Customer:`, and `:Customer:` references `:Order:`. Fix by removing the back-reference:
57
+
58
+ ```plain
59
+ ***definitions***
60
+
61
+ - :Customer: is a user of the system.
62
+
63
+ - :Order: is placed by :Customer: and contains :OrderItem: entries.
64
+ ```
65
+
66
+ ## Exported concepts are not transitive
67
+ - If module A exports a concept and module B `requires` A, a module C with `requires: [B]` does **not** gain access to A's exports
68
+ - To use an ancestor's exports, list that ancestor in `requires` as well; concepts shared more broadly belong in a common import module
69
+
70
+ ## Description quality
71
+ - Descriptions must be clear, concise, and language-agnostic
72
+ - Nest attributes and constraints as sub-bullets
73
+ - Do not use programming language constructs (generics, annotations, framework types) in definitions
74
+
75
+ ## Concept granularity and technical components
76
+ - Definitions are not restricted to high-level domain objects. When an implementation warrants abstract, technical, or infrastructural components to clarify responsibilities, it is desired and encouraged to define them.
77
+ - Group related technical concepts using the `of` keyword or by stating their relationship explicitly.
78
+
79
+ Example of defining technical components alongside their behavior:
80
+
81
+ ```plain
82
+ ***definitions***
83
+
84
+ - :CsvToJsonConverter: bidirectionally converts csv and json strings.
85
+
86
+ - :CsvToJson: of :CsvToJsonConverter: converts a list of csv strings (e.g., "value1,value2,value3") to a list of json strings (e.g., "{\"key1\":\"value1\"}").
87
+
88
+ - :JsonToCsv: of :CsvToJsonConverter: converts a list of json strings (e.g., "{\"key1\":\"value1\"}") to a list of csv strings (e.g., "value1,value2").
89
+
90
+ - :StorageService: is an abstraction for a remote blob storage backend.
91
+
92
+ - :CsvFileWriter: writes CSV rows to local files, automatically rotates to new files when size limits are reached, and flushes completed files to :StorageService:.
93
+
94
+ - :CsvFileReader: reads CSV rows in a batched manner.
95
+
96
+ - :CsvJoiner: joins csvs and uses :CsvFileWriter: to create the merged CSV.
97
+ ```
98
+
99
+ ## Format
100
+
101
+ ```plain
102
+ ***definitions***
103
+
104
+ - :ConceptName: is a description of what it represents.
105
+ - Attribute one (required)
106
+ - Attribute two (optional)
107
+ ```
@@ -0,0 +1,163 @@
1
+ #!/bin/bash
2
+
3
+ # Export Java 21
4
+ #export JAVA_HOME="/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home"
5
+ #export PATH="$JAVA_HOME/bin:$PATH"
6
+ echo "JAVA_HOME: $JAVA_HOME"
7
+
8
+ # Check if build folder name is provided
9
+ if [ -z "$1" ]; then
10
+ printf "Error: No build folder name provided.\n"
11
+ printf "Usage: $0 <build_folder_name> <conformance_tests_folder>\n"
12
+ exit 1
13
+ fi
14
+
15
+ # Check if conformance tests folder name is provided
16
+ if [ -z "$2" ]; then
17
+ printf "Error: No conformance tests folder name provided.\n"
18
+ printf "Usage: $0 <build_folder_name> <conformance_tests_folder>\n"
19
+ exit 1
20
+ fi
21
+
22
+ current_dir=$(pwd)
23
+
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).
26
+ case "$2" in
27
+ /*) CONFORMANCE_TESTS_SOURCE="$2" ;;
28
+ *) CONFORMANCE_TESTS_SOURCE="$current_dir/$2" ;;
29
+ esac
30
+
31
+ # Host-relative paths of the module, as declared in ***implementation reqs***.
32
+ # Replace the placeholders with the module's integration source path and its
33
+ # :UnitTests: source path (the same paths run_unittests_java.sh copies to).
34
+ INTEGRATION_CODE_PATH="<placeholder for integration code>"
35
+ INTEGRATION_TESTS_PATH="<placeholder for integration code tests>"
36
+
37
+ # Host codebase root: read from HOST_CODEBASE_ROOT (the one configured fact),
38
+ # defaulting to three levels up from this script.
39
+ MAIN_PROJECT_FOLDER="${HOST_CODEBASE_ROOT:-$(cd "$(dirname "$0")/../../.." && pwd)}"
40
+
41
+ # Stage the generated code into the host codebase (same copy as run_unittests_java.sh)
42
+ if [ "${VERBOSE:-}" -eq 1 ] 2>/dev/null; then
43
+ printf "Copying generated code to main project folder: $MAIN_PROJECT_FOLDER\n"
44
+ fi
45
+
46
+ # Check if the main project folder exists
47
+ if [ ! -d "$MAIN_PROJECT_FOLDER" ]; then
48
+ echo "Error: Main project folder '$MAIN_PROJECT_FOLDER' does not exist."
49
+ exit 2
50
+ fi
51
+
52
+ # clean existing code of this module only from the main project folder
53
+ rm -rf "$MAIN_PROJECT_FOLDER/$INTEGRATION_CODE_PATH"/*
54
+ rm -rf "$MAIN_PROJECT_FOLDER/$INTEGRATION_TESTS_PATH"/*
55
+
56
+ # copy generated code to the main project folder
57
+ mkdir -p "$MAIN_PROJECT_FOLDER/$INTEGRATION_CODE_PATH"
58
+ mkdir -p "$MAIN_PROJECT_FOLDER/$INTEGRATION_TESTS_PATH"
59
+ cp -R "$1/$INTEGRATION_CODE_PATH"/* "$MAIN_PROJECT_FOLDER/$INTEGRATION_CODE_PATH"
60
+ cp -R "$1/$INTEGRATION_TESTS_PATH"/* "$MAIN_PROJECT_FOLDER/$INTEGRATION_TESTS_PATH"
61
+
62
+ # Move to the host codebase and build / install it, so the conformance project
63
+ # resolves this build from the local Maven repository (~/.m2), not a stale one.
64
+ echo "Moving to: $MAIN_PROJECT_FOLDER"
65
+ cd "$MAIN_PROJECT_FOLDER" 2>/dev/null
66
+
67
+ if [ $? -ne 0 ]; then
68
+ printf "Error: Java build folder '$MAIN_PROJECT_FOLDER' does not exist.\n"
69
+ exit 2
70
+ fi
71
+
72
+ # Remove target directory to avoid conflicts with a previous build
73
+ rm -rf ./target || echo "Warning: some files may be locked"
74
+
75
+ # -DskipTests is legitimate here: this step only installs the host build;
76
+ # the conformance tests run below.
77
+ echo "Running maven install in the host codebase..."
78
+ mvn clean install -Dspring-boot.repackage.skip=true -DskipTests
79
+
80
+ install_exit_code=$?
81
+ if [ $install_exit_code -ne 0 ]; then
82
+ echo "Error: Maven install failed in the host codebase with exit code $install_exit_code..."
83
+ exit 69
84
+ fi
85
+
86
+ # Scratch folder lives in the system temp directory so no build debris is left
87
+ # inside the project. It is removed again when the script exits.
88
+ CONFORMANCE_TESTS_FOLDER="/tmp/java_conformance"
89
+
90
+ trap 'rm -rf "$CONFORMANCE_TESTS_FOLDER"' EXIT
91
+
92
+ printf "Preparing Java conformance tests subfolder: $CONFORMANCE_TESTS_FOLDER\n"
93
+
94
+ # Check if the conformance tests scratch folder exists
95
+ if [ -d "$CONFORMANCE_TESTS_FOLDER" ]; then
96
+ # Find and delete all files and folders
97
+ find "$CONFORMANCE_TESTS_FOLDER" -mindepth 1 -exec rm -rf {} +
98
+
99
+ if [ "${VERBOSE:-}" -eq 1 ] 2>/dev/null; then
100
+ printf "Cleanup completed.\n"
101
+ fi
102
+ else
103
+ # print the current directory
104
+ printf "Current directory: $(pwd)\n"
105
+
106
+ printf "Subfolder does not exist. Creating it...\n"
107
+ mkdir -p $CONFORMANCE_TESTS_FOLDER
108
+ fi
109
+
110
+ printf "Copying all files and folders from $CONFORMANCE_TESTS_SOURCE to $CONFORMANCE_TESTS_FOLDER...\n"
111
+ cp -R "$CONFORMANCE_TESTS_SOURCE"/* $CONFORMANCE_TESTS_FOLDER
112
+
113
+ # Move to the subfolder
114
+ printf "Moving to $CONFORMANCE_TESTS_FOLDER...\n"
115
+ cd "$CONFORMANCE_TESTS_FOLDER" 2>/dev/null
116
+
117
+ if [ $? -ne 0 ]; then
118
+ printf "Error: Java conformance tests folder '$CONFORMANCE_TESTS_FOLDER' does not exist.\n"
119
+ exit 2
120
+ fi
121
+
122
+ echo "Running maven install in the conformance tests folder..."
123
+ mvn clean install -DskipTests
124
+
125
+
126
+ if [ $? -ne 0 ]; then
127
+ exit 2
128
+ fi
129
+
130
+ echo "Running maven test in the conformance tests folder..."
131
+
132
+ output=$(mvn test --no-transfer-progress 2>&1)
133
+ exit_code=$?
134
+
135
+ echo "Finished running maven test in the conformance tests folder..."
136
+
137
+ # Check if no tests were run
138
+ if echo "$output" | grep -q 'Tests run: [1-9][0-9]*, Failures: 0, Errors: 0, Skipped: 0'; then
139
+ echo "All tests passed"
140
+ echo "$output"
141
+ exit $exit_code
142
+ else
143
+ # Check if no tests were run
144
+ if echo "$output" | grep -q 'Tests run: 0, Failures: 0, Errors: 0, Skipped: 0'; then
145
+ echo "Tests run: 0"
146
+ echo "Error: No tests were executed (Tests run: 0)"
147
+ echo "You are seeing this cause the following appeared in the output: Tests run: 0, Failures: 0, Errors: 0, Skipped: 0"
148
+ else
149
+ echo "Some tests failed, had errors, or were skipped. This is not allowed. All tests must pass."
150
+ fi
151
+ fi
152
+
153
+ # If there was an error, print the output and exit with the error code
154
+ if [ $exit_code -ne 0 ]; then
155
+ echo "Error: Maven test failed in the conformance tests folder with exit code $exit_code..."
156
+ echo "$output"
157
+ exit $exit_code
158
+ fi
159
+
160
+ echo "Finished running conformance tests..."
161
+ echo "$output"
162
+ # Echo the original exit code of the unittest command
163
+ exit $exit_code
@@ -0,0 +1,51 @@
1
+ #!/bin/bash
2
+
3
+ # Export Java 21
4
+ #export JAVA_HOME="/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home"
5
+ #export PATH="$JAVA_HOME/bin:$PATH"
6
+ echo "JAVA_HOME: $JAVA_HOME"
7
+
8
+ # Check if subfolder name is provided
9
+ if [ -z "$1" ]; then
10
+ echo "Error: No subfolder name provided."
11
+ echo "Usage: $0 <subfolder_name>"
12
+ exit 1
13
+ fi
14
+ # FIX: Changed this line from "../../" to "../../.." to go up three levels to the main project folder
15
+ MAIN_PROJECT_FOLDER="$(cd "$(dirname "$0")/../../.." && pwd)"
16
+
17
+ if [ "${VERBOSE:-}" -eq 1 ] 2>/dev/null; then
18
+ printf "Copying generated code to main project folder: $MAIN_PROJECT_FOLDER\n"
19
+ fi
20
+
21
+ # Check if the main project folder exists
22
+ if [ ! -d "$MAIN_PROJECT_FOLDER" ]; then
23
+ echo "Error: Main project folder '$MAIN_PROJECT_FOLDER' does not exist."
24
+ exit 2
25
+ fi
26
+
27
+ # clean existing code from the main project folder
28
+ rm -rf $MAIN_PROJECT_FOLDER/<placeholder for integration code>/*
29
+ rm -rf $MAIN_PROJECT_FOLDER/<placeholder for integration code tests>/*
30
+
31
+ # copy generated code to the main project folder
32
+ # FIX: added the mkdir lines otherwise it complains that the cp destintation directory does not exist
33
+ mkdir -p $MAIN_PROJECT_FOLDER/<placeholder for integration code>
34
+ mkdir -p $MAIN_PROJECT_FOLDER/<placeholder for integration code tests>
35
+ cp -R $1/<placeholder for integration code>/* $MAIN_PROJECT_FOLDER/<placeholder for integration code>
36
+ cp -R $1/<placeholder for integration code tests>/* $MAIN_PROJECT_FOLDER/<placeholder for integration code tests>
37
+
38
+ # Move to the subfolder
39
+ # FIX: added this line to print the current directory to help the LLM
40
+ echo "Moving to: $MAIN_PROJECT_FOLDER"
41
+ cd "$MAIN_PROJECT_FOLDER" 2>/dev/null
42
+
43
+ if [ $? -ne 0 ]; then
44
+ printf "Error: Java build folder '$MAIN_PROJECT_FOLDER' does not exist.\n"
45
+ exit 2
46
+ fi
47
+
48
+
49
+ # Execute all Java unittests in the subfolder
50
+ echo "Running Java unittests in $1..."
51
+ mvn test -Dtest='<placeholder for integration code tests package>.**.*Test' checkstyle:check
@@ -0,0 +1,39 @@
1
+ ---
2
+ description: Rules for using exported_concepts in .plain files
3
+ ---
4
+
5
+ # Rules for `exported_concepts`
6
+
7
+ When adding or editing `exported_concepts` in a `.plain` file's frontmatter, always follow these rules:
8
+
9
+ ## What exported_concepts does
10
+ - `exported_concepts` declares which concepts from this module are visible to modules that `require` it
11
+ - Concepts not listed in `exported_concepts` are internal to the module and invisible to downstream modules
12
+ - Only modules that use `requires` receive exported concepts — `import` gives access to all definitions, not just exports
13
+ - An exported concept is visible with its full definition text
14
+
15
+ ## When to use it
16
+ - Use `exported_concepts` on any module that other modules will `require`
17
+ - List only the concepts that downstream modules actually need to reference
18
+ - Keep the exported surface small — expose only what is necessary
19
+
20
+ ## Concepts must be defined
21
+ - Every concept listed in `exported_concepts` must be defined in the module's own `***definitions***` section
22
+ - Do not export concepts that are not defined in the module
23
+
24
+ ## Exports are not transitive
25
+ - If module A exports `:Foo:` and module B `requires` A, a module C with `requires: [B]` does **not** gain access to `:Foo:`
26
+ - If module C also needs `:Foo:`, it should list A in its `requires` as well (`requires: [A, B]`) or get `:Foo:` through a common import module
27
+
28
+ ## Format
29
+
30
+ ```plain
31
+ ---
32
+ import:
33
+ - airplain
34
+ exported_concepts: [":User:", ":JwtToken:"]
35
+ description: Exports User and JwtToken for downstream modules
36
+ ---
37
+ ```
38
+
39
+ List concepts as a YAML array with each concept in `:ConceptName:` notation.
@@ -0,0 +1,129 @@
1
+ ---
2
+ description: Rules for writing ***functional specs*** and ***acceptance tests*** in .plain files
3
+ ---
4
+
5
+ # Rules for writing `***functional specs***`
6
+
7
+ When writing or editing a `***functional specs***` section in a `.plain` file, always follow these rules:
8
+
9
+ ## Voice
10
+ - 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
+ - **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
+ - **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
14
+ - Do **not** use "should" / "should be able to" in a functional spec — that is requirement-modal voice; state the fact directly
15
+
16
+ BAD — imperative commands, or the vague "The system":
17
+
18
+ ```plain
19
+ ***functional specs***
20
+
21
+ - Implement the entry point for :App:.
22
+
23
+ - The system shows :TaskList:.
24
+
25
+ - Add :Task:.
26
+ ```
27
+
28
+ GOOD — statements of fact with concrete subjects:
29
+
30
+ ```plain
31
+ ***functional specs***
32
+
33
+ - :App: has an entry point.
34
+
35
+ - The :TaskList: is displayed.
36
+
37
+ - A :User: can add a :Task:. Only valid :Task: items are added.
38
+ ```
39
+
40
+ ## 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`
42
+ - Cut anything obvious, any rationale, and every uncheckable adjective; keep every interface detail, boundary case, and disambiguation
43
+ - Shorten the wording, never the facts: the rules below always win over brevity
44
+
45
+ ## Complexity limit
46
+ - 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
+ - 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
+ - Use `analyze-if-func-spec-too-complex` to verify before inserting
51
+ - 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
52
+
53
+ ## First-spec bootstrap cost
54
+ - The first functional spec in a new root module carries implicit implementation cost even when its text describes little behavior
55
+ - 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
56
+ - Count that bootstrap work toward the 200-changed-line limit; it is not free setup outside the spec
57
+ - Make the first spec the module's simplest useful, independently observable capability
58
+ - The first spec must still imply a testable outcome; setup alone is not a functional spec
59
+ - Prefer one minimal entry point or public operation with a deterministic result that can be invoked and verified
60
+ - Defer persistence, integrations, multiple interfaces, branching workflows, and cross-cutting behavior until later specs can build on the generated baseline
61
+ - 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
62
+
63
+ ## Chronological ordering
64
+ - Specs are rendered incrementally, top to bottom
65
+ - The renderer has **no knowledge of future specs** — only previously rendered specs are in context
66
+ - A new spec can reference behavior from earlier specs but cannot assume anything about specs that come after it
67
+ - Functional specs from `requires` modules are treated as previous requirements — transitively, across the whole ancestor chain
68
+
69
+ ## No conflicts
70
+ - The new spec must not contradict any existing functional spec
71
+ - Before adding, review all existing specs and verify compatibility
72
+ - If ambiguity exists, add explicit detail to eliminate any conflicting interpretation
73
+
74
+ ## Language agnosticism
75
+ - Write in terms of behavior, concepts, and domain logic
76
+ - Avoid language-specific terminology: generics syntax, framework annotations, language-specific collection types, decorator syntax, base-class keywords, framings like "POJO" or "dataclass"
77
+ - General technical terms that are not language-specific are fine: null values, JSON types, HTTP status codes, REST endpoints, etc.
78
+ - **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.)
79
+ - **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.
80
+
81
+ ## Disambiguation
82
+ - Each functional spec must be unambiguous — the renderer should have only one reasonable interpretation
83
+ - If a single line is not enough to fully disambiguate the behavior, use **nested sub-bullets** to add detail
84
+ - Nested lines clarify the parent spec — they do not introduce separate functionality
85
+ - Even with nested detail, the spec must still imply ≤ 200 lines of code
86
+
87
+ ## Testability
88
+ - Every functional spec must describe behavior that can be verified through an observable interface
89
+ - State the triggering input or action and the deterministic outcome a test can observe
90
+ - Include relevant outputs, state changes, errors, or externally visible side effects
91
+ - Do not rely on generated implementation details as the only way to verify the behavior
92
+ - If a black-box conformance test cannot be derived from the spec, make the behavior more explicit
93
+ - Testability does not require an acceptance test; acceptance tests are reserved for full workflows
94
+
95
+ ## Deterministic interface
96
+ - Specs must be detailed enough that a developer can use the built software without reading the generated code
97
+ - All external interfaces must be explicit: REST endpoint paths and HTTP methods, CLI command names and arguments, file formats, message schemas, etc.
98
+ - Never leave interface details up to the renderer's discretion
99
+
100
+ ## Encapsulation
101
+ - Functionality must be self-contained in the spec text
102
+ - `requires` modules only pass on functional specs and `exported_concepts` — never implementation reqs, so do not rely on implementation reqs to convey behavior
103
+ - Behavior that downstream modules need must be expressed in functional specs, not elsewhere
104
+
105
+ ## Acceptance tests
106
+ - Nest `***acceptance tests***` under a functional spec when verification criteria are needed
107
+ - 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
108
+ - 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
109
+ - Each acceptance test must be a direct logical consequence of the parent spec — it illustrates, not extends
110
+ - Acceptance tests must describe concrete, verifiable outcomes — not vague qualities
111
+ - Acceptance tests must not contradict, narrow, or extend beyond the parent spec
112
+
113
+ ## Format
114
+
115
+ ```plain
116
+ ***functional specs***
117
+
118
+ - :App: has an entry point.
119
+
120
+ - A :User: can add a :Task:. Only valid :Task: items are added.
121
+
122
+ - A :User: can send a :Message: to a :Conversation:.
123
+ - A :Message: must have non-empty content.
124
+ - The :Message: is appended to the end of the :Conversation:.
125
+ - All :Participant: members of the :Conversation: can see the new :Message:.
126
+
127
+ ***acceptance tests***
128
+ - Sending a :Message: to a :Conversation: with three participants should make the message visible to all three.
129
+ ```
@@ -0,0 +1,68 @@
1
+ ---
2
+ description: Rules for writing ***implementation reqs*** sections in .plain files
3
+ ---
4
+
5
+ # Rules for writing `***implementation reqs***`
6
+
7
+ When writing or editing an `***implementation reqs***` section in a `.plain` file, always follow these rules:
8
+
9
+ ## HOW, not WHAT
10
+ - Implementation reqs describe **how** the software should be built, not **what** it should do
11
+ - Observable behavior (endpoints, business rules, user-facing features) belongs in `***functional specs***`
12
+ - Internal structure, technology choices, and coding guidance belong here
13
+
14
+ ## `:UnitTests:` lives here (hard rule)
15
+ - **Everything** about `:UnitTests:` goes in `***implementation reqs***` — paths, approach, packages, framework, conventions, fixtures, mocking policy, file layout, naming, lint / static-analysis gates
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
18
+ - Author each `:UnitTests:` requirement via `add-implementation-requirement` and phrase it in terms of `:UnitTests:` so the partition stays visible at a glance
19
+
20
+ ## What belongs here
21
+ - Technology choices: language, framework, runtime version
22
+ - Architectural constraints: patterns, layering, dependency rules
23
+ - Coding standards: naming conventions, style guidelines
24
+ - Data formats: serialization, encoding, transformation rules
25
+ - Error handling: strategies, retry logic, exception hierarchies
26
+ - Algorithm descriptions: specific approaches when behavior alone is insufficient
27
+ - Performance guidance: memory constraints, streaming requirements, batching strategies
28
+ - Language-specific constructs: generics, annotations, framework-specific types and idioms
29
+ - **Unit-test guidance: framework, structure, mocking conventions, file layout** — unit tests are part of the generated codebase, so requirements that shape them are implementation reqs
30
+
31
+ ## What does NOT belong here
32
+ - Behavior and features → `***functional specs***`
33
+ - Concept definitions → `***definitions***`
34
+ - **Conformance-test guidance** → `***test reqs***`
35
+ - **Acceptance-test scenarios** → `***acceptance tests***` nested under the relevant functional spec
36
+
37
+ ## Unit tests vs conformance tests (common mistake)
38
+ - Unit-test guidance (`:UnitTests:` framework, structure, mocking) goes **here**, not in `***test reqs***`
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
42
+
43
+ ## Encapsulation warning
44
+ - `requires` modules only pass on functional specs and `exported_concepts` — never implementation reqs
45
+ - If downstream modules need certain behavior to be visible, express it in functional specs, not here
46
+
47
+ ## Conciseness
48
+ - State each req in the fewest plain words that stay exact — see `concise-specs.md`
49
+ - Do not restate the standard behavior of a technology this section already names
50
+
51
+ ## No duplication
52
+ - Do not duplicate guidance already present in the file or its imports
53
+ - Check imported modules before adding a new req
54
+
55
+ ## Concept references
56
+ - Reference defined `:Concepts:` where they add clarity
57
+ - All referenced concepts must already be defined in `***definitions***`
58
+ - Make the component a req constrains its subject; `:Implementation:` is the whole codebase, so use it only for a fact that holds everywhere — language, dependency manager, stack-wide convention
59
+
60
+ ## Format
61
+
62
+ ```plain
63
+ ***implementation reqs***
64
+ - :Implementation: should be in Python 3.12.
65
+ - :Implementation: should use pip for dependency management.
66
+ - :ReportExporter: writes a :CsvFile: with streaming writes, never holding the full dataset in memory.
67
+ - :UnitTests: should use pytest, run with `pytest tests/`.
68
+ ```