@turri-dev/cli 0.1.27 → 0.2.0

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,8 +1,8 @@
1
1
  ---
2
- description: Worked BAD to GOOD examples of concise .plain specs, one pair per conciseness failure mode
2
+ description: Worked BAD to GOOD examples of concise ***plain, one pair per conciseness failure mode
3
3
  ---
4
4
 
5
- # Worked examples of concise `.plain` specs
5
+ # Worked examples of concise ***plain
6
6
 
7
7
  `concise-specs.md` is the rule; this file is the example bank behind it. Every entry names one failure mode, shows the padded version, and shows the rewrite that carries the same information.
8
8
 
@@ -10,7 +10,7 @@ Read the pairs, not the prose: in each one, the GOOD block says everything the B
10
10
 
11
11
  The BAD blocks intentionally demonstrate the mistakes they name, including invalid syntax. Copy only from GOOD blocks.
12
12
 
13
- Integration specs fail in their own ways — over-precision, inlined contract data, and edge cases the provider's documentation invites. Those examples are in `concise-specs-integration-examples.md`.
13
+ Integration ***plain fails in its own ways — over-precision, inlined contract data, and edge cases the provider's documentation invites. Those examples are in `concise-specs-integration-examples.md`.
14
14
 
15
15
  ## Padding around one fact
16
16
 
@@ -19,11 +19,14 @@ BAD:
19
19
  ```plain
20
20
  ***functional specs***
21
21
 
22
- - In order to provide users with a robust and seamless experience, :TaskService: exposes a comprehensive endpoint for the creation of new :Task: items.
22
+ # create-task
23
+ In order to provide users with a robust and seamless experience, :TaskService: exposes a comprehensive endpoint for the creation of new :Task: items.
23
24
 
24
- - The endpoint accepts a request and, provided that the incoming payload is valid and well-formed, proceeds to persist the :Task: appropriately.
25
+ # persist-task
26
+ The endpoint accepts a request and, provided that the incoming payload is valid and well-formed, proceeds to persist the :Task: appropriately.
25
27
 
26
- - If the payload is not valid, an appropriate error is returned to the caller so that the user is informed of the problem.
28
+ # reject-invalid-payload
29
+ If the payload is not valid, an appropriate error is returned to the caller so that the user is informed of the problem.
27
30
  ```
28
31
 
29
32
  GOOD:
@@ -31,13 +34,14 @@ GOOD:
31
34
  ```plain
32
35
  ***functional specs***
33
36
 
34
- - A :User: can create a :Task: via `POST /tasks`.
35
- - The request body is a :Task: without `id`.
36
- - The response is `201` with the created :Task:.
37
- - A request without a name returns `400`.
37
+ # create-task
38
+ A :User: can create a :Task: via `POST /tasks`.
39
+ - The request body is a :Task: without `id`.
40
+ - The response is `201` with the created :Task:.
41
+ - A request without a name returns `400`.
38
42
  ```
39
43
 
40
- Three bullets became one, and the rewrite names the method, the path, the request shape, and both status codes — none of which the padded version pinned down.
44
+ Three functional specs became one, and the rewrite names the method, the path, the request shape, and both status codes — none of which the padded version pinned down.
41
45
 
42
46
  ## Rationale, motivation, and benefits
43
47
 
@@ -46,7 +50,8 @@ BAD:
46
50
  ```plain
47
51
  ***functional specs***
48
52
 
49
- - Because support staff frequently need to find customers quickly, and because scanning the full list is slow and error-prone, :CustomerDirectory: offers a search capability that greatly improves their daily workflow.
53
+ # search-customers
54
+ Because support staff frequently need to find customers quickly, and because scanning the full list is slow and error-prone, :CustomerDirectory: offers a search capability that greatly improves their daily workflow.
50
55
  ```
51
56
 
52
57
  GOOD:
@@ -54,7 +59,8 @@ GOOD:
54
59
  ```plain
55
60
  ***functional specs***
56
61
 
57
- - :CustomerDirectory: returns :Customer: items whose name or email contains a search term, case-insensitively.
62
+ # search-customers
63
+ :CustomerDirectory: returns :Customer: items whose name or email contains a search term, case-insensitively.
58
64
  ```
59
65
 
60
66
  Why the feature exists changes nothing about what is built. What "search" matches does.
@@ -86,11 +92,12 @@ BAD:
86
92
  ```plain
87
93
  ***functional specs***
88
94
 
89
- - :OrderApi: returns a list of :Order: items over HTTP.
90
- - The list contains :Order: items.
91
- - If there are no :Order: items, the list is empty.
92
- - Each :Order: has an `id`, which is unique.
93
- - The caller receives the response after the request is sent.
95
+ # list-orders
96
+ :OrderApi: returns a list of :Order: items over HTTP.
97
+ - The list contains :Order: items.
98
+ - If there are no :Order: items, the list is empty.
99
+ - Each :Order: has an `id`, which is unique.
100
+ - The caller receives the response after the request is sent.
94
101
  ```
95
102
 
96
103
  GOOD:
@@ -98,8 +105,9 @@ GOOD:
98
105
  ```plain
99
106
  ***functional specs***
100
107
 
101
- - :OrderApi: returns the :Order: items of the authenticated :User: via `GET /orders`, newest first.
102
- - The response is `200` with a JSON array, empty when the :User: has no :Order: items.
108
+ # list-orders
109
+ :OrderApi: returns the :Order: items of the authenticated :User: via `GET /orders`, newest first.
110
+ - The response is `200` with a JSON array, empty when the :User: has no :Order: items.
103
111
  ```
104
112
 
105
113
  Every cut line was already implied: a list of :Order: items contains :Order: items, an identifier identifies, and a response follows a request. What survives is what a reader could *not* have guessed — the ownership filter, the sort order, and the response shape.
@@ -113,11 +121,14 @@ BAD:
113
121
  ```plain
114
122
  ***functional specs***
115
123
 
116
- - :OrderService: validates all incoming data before processing it.
124
+ # validate-input
125
+ :OrderService: validates all incoming data before processing it.
117
126
 
118
- - :OrderService: handles errors and returns meaningful error messages.
127
+ # handle-errors
128
+ :OrderService: handles errors and returns meaningful error messages.
119
129
 
120
- - :OrderService: saves the :Order: to storage so that it is not lost.
130
+ # save-order
131
+ :OrderService: saves the :Order: to storage so that it is not lost.
121
132
  ```
122
133
 
123
134
  GOOD:
@@ -125,7 +136,8 @@ GOOD:
125
136
  ```plain
126
137
  ***functional specs***
127
138
 
128
- - :OrderService: rejects an :Order: whose `total` does not equal the sum of its :OrderLine: amounts, with `422`.
139
+ # reject-wrong-total
140
+ :OrderService: rejects an :Order: whose `total` does not equal the sum of its :OrderLine: amounts, with `422`.
129
141
  ```
130
142
 
131
143
  Validating input, reporting errors, and persisting on a save operation belong in the `***implementation reqs***` and a baseline is assumed. If there is a specific use case for a particular operation, it should be documented there, not in the `***functional specs***`. The one fact worth stating is *which* rule is enforced and what the caller sees when it fails.
@@ -208,7 +220,7 @@ GOOD:
208
220
  - :ConformanceTests: mock every external HTTP call.
209
221
  ```
210
222
 
211
- Every hedge hands the renderer a decision the spec was supposed to make. A spec states one behavior.
223
+ Every hedge hands the coding agent a decision the ***plain was supposed to make. A functional spec states one behavior.
212
224
 
213
225
  ## Ornate vocabulary
214
226
 
@@ -217,7 +229,8 @@ BAD:
217
229
  ```plain
218
230
  ***functional specs***
219
231
 
220
- - :ReportGenerator: is responsible for facilitating the utilization of a plurality of :DataSource: instances in order to initiate the generation of a :Report: prior to the performance of the validation of the resulting output.
232
+ # build-report
233
+ :ReportGenerator: is responsible for facilitating the utilization of a plurality of :DataSource: instances in order to initiate the generation of a :Report: prior to the performance of the validation of the resulting output.
221
234
  ```
222
235
 
223
236
  GOOD:
@@ -225,22 +238,24 @@ GOOD:
225
238
  ```plain
226
239
  ***functional specs***
227
240
 
228
- - :ReportGenerator: builds a :Report: from one or more :DataSource: items, then validates it.
241
+ # build-report
242
+ :ReportGenerator: builds a :Report: from one or more :DataSource: items, then validates it.
229
243
  ```
230
244
 
231
245
  Same sequence, plain words. See the substitution table in `concise-specs.md`.
232
246
 
233
- ## Sub-bullets that elaborate instead of disambiguating
247
+ ## Detail that elaborates instead of disambiguating
234
248
 
235
249
  BAD:
236
250
 
237
251
  ```plain
238
252
  ***functional specs***
239
253
 
240
- - A :User: can archive a :Project:.
241
- - Archiving is an action the user performs on a project.
242
- - The archive action is available to users who have access to the project.
243
- - Once archived, the project is in the archived state.
254
+ # archive-project
255
+ A :User: can archive a :Project:.
256
+ - Archiving is an action the user performs on a project.
257
+ - The archive action is available to users who have access to the project.
258
+ - Once archived, the project is in the archived state.
244
259
  ```
245
260
 
246
261
  GOOD:
@@ -248,23 +263,25 @@ GOOD:
248
263
  ```plain
249
264
  ***functional specs***
250
265
 
251
- - A :User: can archive a :Project: they own.
252
- - An archived :Project: is excluded from :ProjectList:.
253
- - Archiving a :Project: that is already archived returns `409`.
266
+ # archive-project
267
+ A :User: can archive a :Project: they own.
268
+ - An archived :Project: is excluded from :ProjectList:.
269
+ - Archiving a :Project: that is already archived returns `409`.
254
270
  ```
255
271
 
256
- A sub-bullet earns its line by removing an ambiguity. If it only says the parent again in more words, it is filler.
272
+ A detail bullet earns its line by removing an ambiguity. If it only says the statement line again in more words, it is filler.
257
273
 
258
- ## Restating the parent bullet
274
+ ## Restating the statement line
259
275
 
260
276
  BAD:
261
277
 
262
278
  ```plain
263
279
  ***functional specs***
264
280
 
265
- - :SessionStore: expires a :Session: 30 minutes after its last use.
266
- - Sessions do not live forever; they time out.
267
- - The timeout is 30 minutes.
281
+ # expire-session
282
+ :SessionStore: expires a :Session: 30 minutes after its last use.
283
+ - Sessions do not live forever; they time out.
284
+ - The timeout is 30 minutes.
268
285
  ```
269
286
 
270
287
  GOOD:
@@ -272,8 +289,9 @@ GOOD:
272
289
  ```plain
273
290
  ***functional specs***
274
291
 
275
- - :SessionStore: expires a :Session: 30 minutes after its last use.
276
- - A request carrying an expired :Session: returns `401`.
292
+ # expire-session
293
+ :SessionStore: expires a :Session: 30 minutes after its last use.
294
+ - A request carrying an expired :Session: returns `401`.
277
295
  ```
278
296
 
279
297
  ## Synonym drift
@@ -283,23 +301,27 @@ BAD:
283
301
  ```plain
284
302
  ***functional specs***
285
303
 
286
- - A :User: can upload a :Document:.
304
+ # upload-document
305
+ A :User: can upload a :Document:.
287
306
 
288
- - The system stores the submitted file in :DocumentStore:.
307
+ # store-document
308
+ The system stores the submitted file in :DocumentStore:.
289
309
 
290
- - The uploaded asset is retrievable by its identifier.
310
+ # retrieve-document
311
+ The uploaded asset is retrievable by its identifier.
291
312
  ```
292
313
 
293
- Three names — `:Document:`, "file", "asset" — read as three things. A reader cannot tell whether "asset" is a fourth concept, and the renderer cannot either.
314
+ Three names — `:Document:`, "file", "asset" — read as three things. A reader cannot tell whether "asset" is a fourth concept, and the coding agent cannot either.
294
315
 
295
316
  GOOD:
296
317
 
297
318
  ```plain
298
319
  ***functional specs***
299
320
 
300
- - A :User: can upload a :Document:.
301
- - :DocumentStore: stores the :Document: and assigns it a :DocumentId:.
302
- - A :User: can retrieve a :Document: by its :DocumentId:.
321
+ # upload-document
322
+ A :User: can upload a :Document:.
323
+ - :DocumentStore: stores the :Document: and assigns it a :DocumentId:.
324
+ - A :User: can retrieve a :Document: by its :DocumentId:.
303
325
  ```
304
326
 
305
327
  ## Meta-commentary and scope disclaimers
@@ -309,13 +331,17 @@ BAD:
309
331
  ```plain
310
332
  ***functional specs***
311
333
 
312
- - This spec is intentionally kept small so that it stays within the complexity limit.
334
+ # export-csv-size-note
335
+ This spec is intentionally kept small so that it stays within the complexity limit.
313
336
 
314
- - As described above, :ExportService: writes a :CsvFile:.
337
+ # export-csv-reference
338
+ As described above, :ExportService: writes a :CsvFile:.
315
339
 
316
- - No changes are made to the existing :ImportService: or to the user interface.
340
+ # export-csv-no-changes
341
+ No changes are made to the existing :ImportService: or to the user interface.
317
342
 
318
- - Future specs will extend this behavior with additional formats.
343
+ # export-csv-future
344
+ Future specs will extend this behavior with additional formats.
319
345
  ```
320
346
 
321
347
  GOOD:
@@ -323,12 +349,13 @@ GOOD:
323
349
  ```plain
324
350
  ***functional specs***
325
351
 
326
- - :ExportService: writes the :Order: items of a :BillingPeriod: to a :CsvFile:.
327
- - The header row is `id,customer,total,currency`.
328
- - An empty :BillingPeriod: produces a :CsvFile: with only the header row.
352
+ # export-csv
353
+ :ExportService: writes the :Order: items of a :BillingPeriod: to a :CsvFile:.
354
+ - The header row is `id,customer,total,currency`.
355
+ - An empty :BillingPeriod: produces a :CsvFile: with only the header row.
329
356
  ```
330
357
 
331
- A spec describes the software, not itself. What the spec does *not* change is everything it does not mention, and what later specs will add belongs to those specs.
358
+ ***plain describes the software, not itself. What a functional spec does *not* change is everything it does not mention, and what later functional specs will add belongs to them.
332
359
 
333
360
  ## Prose and tables inside a section
334
361
 
@@ -337,13 +364,14 @@ BAD:
337
364
  ```plain
338
365
  ***functional specs***
339
366
 
340
- - :PricingEngine: applies discounts.
341
- The discount matrix is as follows:
342
- | Tier | Volume | Discount |
343
- |---|---|---|
344
- | Bronze | 0-99 | 0% |
345
- | Silver | 100-499 | 5% |
346
- | Gold | 500+ | 12% |
367
+ # apply-discounts
368
+ :PricingEngine: applies discounts.
369
+ The discount matrix is as follows:
370
+ | Tier | Volume | Discount |
371
+ |---|---|---|
372
+ | Bronze | 0-99 | 0% |
373
+ | Silver | 100-499 | 5% |
374
+ | Gold | 500+ | 12% |
347
375
  ```
348
376
 
349
377
  GOOD:
@@ -351,15 +379,16 @@ GOOD:
351
379
  ```plain
352
380
  ***functional specs***
353
381
 
354
- - :PricingEngine: applies the :DiscountTier: matrix in [resources/discount-tiers.json](resources/discount-tiers.json) to an :Order: total.
355
- - An :Order: below the lowest tier threshold gets no discount.
382
+ # apply-discounts
383
+ :PricingEngine: applies the :DiscountTier: matrix in [resources/discount-tiers.json](resources/discount-tiers.json) to an :Order: total.
384
+ - An :Order: below the lowest tier threshold gets no discount.
356
385
  ```
357
386
 
358
387
  A section holds `- ` list items. Matrices, schemas, and payloads are external artifacts and are linked from `resources/` — see `linked-resources.md`.
359
388
 
360
389
  ## Split one crowded bullet across its owning sections
361
390
 
362
- One bullet that mixes behavior, technology, and test policy is hard to review and partly ignored: the renderer reads each concept only from its owning section, so the unit-test and conformance-test facts below never reach the generators that need them.
391
+ One bullet that mixes behavior, technology, and test policy is hard to review and partly ignored: turri reads each concept only from its owning section, so the unit-test and conformance-test facts below never reach the agents that need them.
363
392
 
364
393
  BAD — everything in one place:
365
394
 
@@ -372,7 +401,8 @@ BAD — everything in one place:
372
401
 
373
402
  ***functional specs***
374
403
 
375
- - :ImageResizer:, implemented as a Python class using Pillow with a thread pool of 4 workers, resizes an uploaded :Image: to a thumbnail, where a thumbnail is defined as a JPEG at most 256 pixels on its longest edge.
404
+ # resize-image
405
+ :ImageResizer:, implemented as a Python class using Pillow with a thread pool of 4 workers, resizes an uploaded :Image: to a thumbnail, where a thumbnail is defined as a JPEG at most 256 pixels on its longest edge.
376
406
  ```
377
407
 
378
408
  GOOD — each fact in the section that owns it:
@@ -394,9 +424,10 @@ GOOD — each fact in the section that owns it:
394
424
 
395
425
  ***functional specs***
396
426
 
397
- - :ImageResizer: produces a :Thumbnail: from an :Image:.
398
- - An :Image: already within the :Thumbnail: bounds is returned unchanged.
399
- - An :Image: that is not a supported format raises :UnsupportedImageError:.
427
+ # resize-image
428
+ :ImageResizer: produces a :Thumbnail: from an :Image:.
429
+ - An :Image: already within the :Thumbnail: bounds is returned unchanged.
430
+ - An :Image: that is not a supported format raises :UnsupportedImageError:.
400
431
  ```
401
432
 
402
433
  Each section now answers one question, and the definition, the mechanism, and the behavior are each one line to check instead of clauses buried in a paragraph about resizing. Use the split whenever a bullet answers more than one of *what is it*, *what does it do*, *how is it built*, and *how is it tested* — see `module-structure.md` for section ownership and canonical section order.
@@ -405,25 +436,25 @@ Use `resolve-section-ownership` to perform the split. It is not the same as spli
405
436
 
406
437
  The most common single case of this is a functional spec that states a mechanism rather than a result — a retry schedule, a cache, a token refresh. `impl-reqs.md` owns HOW; a functional spec keeps what a caller observes. `concise-specs-integration-examples.md` works through several.
407
438
 
408
- ## Narrated acceptance tests
439
+ ## Narrated scenarios
409
440
 
410
441
  BAD:
411
442
 
412
443
  ```plain
413
- ***acceptance tests***
444
+ ***conformance tests***
414
445
 
415
- - The tester should first open the application and log in with a valid account, then navigate to the projects area where they will be able to see the list of projects, and then they should create a new project by filling in the form, after which they should verify that everything worked as expected and the project shows up correctly.
446
+ # create-project
447
+ The tester should first open the application and log in with a valid account, then navigate to the projects area where they will be able to see the list of projects, and then they should create a new project by filling in the form, after which they should verify that everything worked as expected and the project shows up correctly.
416
448
  ```
417
449
 
418
450
  GOOD:
419
451
 
420
452
  ```plain
421
- ***acceptance tests***
453
+ ***conformance tests***
422
454
 
423
- - A :User: creates a :Project: and finds it in :ProjectList:.
424
- - Sign in as a :User: with no :Project: items.
425
- - Create a :Project: named `Apollo`.
426
- - :ProjectList: contains exactly one :Project:, named `Apollo`.
455
+ # create-project
456
+ A signed-in :User: with no :Project: items creates a :Project: named `Apollo` and finds it in :ProjectList:.
457
+ - :ProjectList: contains exactly one :Project:, named `Apollo`.
427
458
  ```
428
459
 
429
- One narrated paragraph becomes an ordered set of checkable steps, and "everything worked as expected" becomes an assertion.
460
+ One narrated paragraph becomes one checkable sentence, and "everything worked as expected" becomes an assertion.
@@ -1,22 +1,22 @@
1
1
  ---
2
- description: Worked BAD to GOOD examples of concise integration specs, where over-precision and obvious edge cases dominate
2
+ description: Worked BAD to GOOD examples of concise integration ***plain, where over-precision and obvious edge cases dominate
3
3
  ---
4
4
 
5
- # Worked examples of concise integration specs
5
+ # Worked examples of concise integration ***plain
6
6
 
7
- `concise-specs.md` is the rule and `concise-specs-examples.md` is the general example bank. This file covers integration specs only, because they fail differently.
7
+ `concise-specs.md` is the rule and `concise-specs-examples.md` is the general example bank. This file covers integration ***plain only, because it fails differently.
8
8
 
9
- An integration is technically demanding, the provider's contract is large, and the author has the provider's documentation open while writing. The result is a spec that is *too precise*: status codes, field lists, retry arithmetic, and every edge case the API can produce, written out as prose bullets. It reads as rigorous and is unreviewable.
9
+ An integration is technically demanding, the provider's contract is large, and the author has the provider's documentation open while writing. The result is ***plain that is *too precise*: status codes, field lists, retry arithmetic, and every edge case the API can produce, written out as prose bullets. It reads as rigorous and is unreviewable.
10
10
 
11
11
  Conciseness here is almost never about covering less. `integrations.md` makes edge-case coverage a hard floor — auth, environments, versioning, pagination, rate limits, the error model, retries, idempotency, webhooks, data mapping, compliance, observability. Every one of those must be covered. The lever is **where** the coverage lives:
12
12
 
13
- - **Shapes and enumerations go to `resources/`** — schemas, error maps, retry policy, rate-limit headers. A spec bullet links to the file; it never restates its contents.
14
- - **The spec keeps behavior** — what the integration does with the shape, and what a caller observes.
13
+ - **Shapes and enumerations go to `resources/`** — schemas, error maps, retry policy, rate-limit headers. A ***plain bullet links to the file; it never restates its contents.
14
+ - **The ***plain keeps behavior** — what the integration does with the shape, and what a caller observes.
15
15
  - **Mechanism goes to `***implementation reqs***`** — retry logic, exception hierarchies, token caching, connection handling. Integration precision is mostly HOW, and `impl-reqs.md` owns HOW. `***functional specs***` keeps only what a caller can observe.
16
16
 
17
- That last lever is easy to miss, so several examples below move a bullet between sections rather than shortening it. A fact in the wrong section is worse than a verbose one: the renderer reads each concept only from its owning section, so a misplaced fact is silently ignored.
17
+ That last lever is easy to miss, so several examples below move a bullet between sections rather than shortening it. A fact in the wrong section is worse than a verbose one: turri reads each concept only from its owning section, so a misplaced fact is silently ignored.
18
18
 
19
- Applied consistently, a spec gets shorter as coverage goes *up*, because each new corner case adds a line to a resource file rather than a paragraph to the spec.
19
+ Applied consistently, ***plain gets shorter as coverage goes *up*, because each new corner case adds a line to a resource file rather than a paragraph to the ***plain.
20
20
 
21
21
  The BAD blocks intentionally demonstrate the mistakes they name, including invalid syntax. Copy only from GOOD blocks.
22
22
 
@@ -31,11 +31,14 @@ BAD:
31
31
 
32
32
  ***functional specs***
33
33
 
34
- - :ProviderClient: retries the request when :ProviderApi: returns 408, 425, 429, 500, 502, 503, or 504, and also on connection errors, DNS failures, socket timeouts, TLS handshake failures, and connection resets.
34
+ # retry-transient-errors
35
+ :ProviderClient: retries the request when :ProviderApi: returns 408, 425, 429, 500, 502, 503, or 504, and also on connection errors, DNS failures, socket timeouts, TLS handshake failures, and connection resets.
35
36
 
36
- - :ProviderClient: does not retry on 400, 401, 403, 404, 405, 409, 410, 415, or 422, and raises immediately.
37
+ # no-retry-permanent-errors
38
+ :ProviderClient: does not retry on 400, 401, 403, 404, 405, 409, 410, 415, or 422, and raises immediately.
37
39
 
38
- - On 429, :ProviderClient: waits and tries again, unless the retry budget is exhausted.
40
+ # retry-on-429
41
+ On 429, :ProviderClient: waits and tries again, unless the retry budget is exhausted.
39
42
  ```
40
43
 
41
44
  GOOD:
@@ -50,7 +53,7 @@ GOOD:
50
53
  - :ProviderClient: classifies every failure of :ProviderApi: through [resources/error-map.yaml](resources/error-map.yaml) and retries the transient ones under [resources/retry-policy.yaml](resources/retry-policy.yaml).
51
54
  ```
52
55
 
53
- The status-code lists move into `error-map.yaml`, which the renderer already reads to generate the exception hierarchy and the transient predicate. Coverage is unchanged and the classification now has one source of truth instead of two that can disagree — see *Transient vs. permanent exception classification* in `integrations.md`.
56
+ The status-code lists move into `error-map.yaml`, which the coding agent already reads to generate the exception hierarchy and the transient predicate. Coverage is unchanged and the classification now has one source of truth instead of two that can disagree — see *Transient vs. permanent exception classification* in `integrations.md`.
54
57
 
55
58
  Note the section too. Classifying and retrying is mechanism, so it is an implementation req; what belongs in `***functional specs***` is only the part a caller observes — which exception each error category surfaces as.
56
59
 
@@ -76,7 +79,7 @@ GOOD:
76
79
  - :Customer: is a :ProviderApi: record, defined by [resources/provider.openapi.yaml](resources/provider.openapi.yaml) under `components.schemas.Customer`.
77
80
  ```
78
81
 
79
- Field lists rot the moment the provider adds a field, and the renderer generates types from the schema, not from the sentence. Keep in the definition only what the schema cannot say — a stability or uniqueness guarantee, a unit, a lifecycle rule.
82
+ Field lists rot the moment the provider adds a field, and the coding agent generates types from the schema, not from the sentence. Keep in the definition only what the schema cannot say — a stability or uniqueness guarantee, a unit, a lifecycle rule.
80
83
 
81
84
  ## Specifying the provider instead of the integration
82
85
 
@@ -91,13 +94,17 @@ BAD:
91
94
 
92
95
  ***functional specs***
93
96
 
94
- - :ProviderApi: returns `200` with a JSON body when a request succeeds.
97
+ # provider-success-response
98
+ :ProviderApi: returns `200` with a JSON body when a request succeeds.
95
99
 
96
- - :ProviderApi: returns `404` when the requested :Customer: does not exist.
100
+ # provider-not-found
101
+ :ProviderApi: returns `404` when the requested :Customer: does not exist.
97
102
 
98
- - :ProviderApi: rate-limits clients and includes the remaining quota in the response headers.
103
+ # provider-rate-limit
104
+ :ProviderApi: rate-limits clients and includes the remaining quota in the response headers.
99
105
 
100
- - :ProviderApi: requires the `Authorization` header on every request.
106
+ # provider-auth-header
107
+ :ProviderApi: requires the `Authorization` header on every request.
101
108
  ```
102
109
 
103
110
  GOOD:
@@ -123,20 +130,21 @@ GOOD:
123
130
 
124
131
  ***functional specs***
125
132
 
126
- - :ProviderClient: fetches a :Customer: from :ProviderApi: by :CustomerId:.
133
+ # fetch-customer
134
+ :ProviderClient: fetches a :Customer: from :ProviderApi: by :CustomerId:.
127
135
  ```
128
136
 
129
137
  Every BAD bullet is true, and none of them is deleted — they are moved. The success shape, the `404`, and the `Authorization` requirement are what an OpenAPI file exists to state; the rate-limit model has its own conventional files. Provider behavior with no machine-readable home goes in `resources/<provider>-notes.md`. `integrations.md` carries the full artifact table.
130
138
 
131
- What stays in the sections is only what gets built. A bullet stating provider behavior renders into nothing — the renderer cannot build the provider, and no conformance test can assert a sentence that makes no claim about the integration. State instead what the integration does when the provider behaves that way.
139
+ What stays in the sections is only what gets built. A bullet stating provider behavior regenerates into nothing — the coding agent cannot build the provider, and no conformance test can assert a sentence that makes no claim about the integration. State instead what the integration does when the provider behaves that way.
132
140
 
133
- Note where the links hang: both artifacts attach to the :ProviderApi: concept, and everything else references the token. `linked-resources.md` requires each resource to be linked from exactly one place, so a second spec needing the contract cannot introduce a second, divergent reference to it.
141
+ Note where the links hang: both artifacts attach to the :ProviderApi: concept, and everything else references the token. `linked-resources.md` requires each resource to be linked from exactly one place, so a second functional spec needing the contract cannot introduce a second, divergent reference to it.
134
142
 
135
- ## One operation fragmented into several specs
143
+ ## One operation fragmented into several functional specs
136
144
 
137
145
  Integration work invites this: the author walks through the request lifecycle — credential check, discovery call, request shape, paging — and each step becomes its own spec.
138
146
 
139
- BAD — four specs, one operation:
147
+ BAD — four functional specs, one operation:
140
148
 
141
149
  ```plain
142
150
  ***definitions***
@@ -147,22 +155,26 @@ BAD — four specs, one operation:
147
155
 
148
156
  ***functional specs***
149
157
 
150
- - A call to `fetch` fails before any request to :ProviderApi: is sent when `PROVIDER_API_KEY` is unset or empty.
151
- - The failure names `PROVIDER_API_KEY`.
158
+ # fetch-requires-api-key
159
+ A call to `fetch` fails before any request to :ProviderApi: is sent when `PROVIDER_API_KEY` is unset or empty.
160
+ - The failure names `PROVIDER_API_KEY`.
152
161
 
153
- - A call to `fetch` reads the field catalogue from :ProviderApi: once, before requesting any :Record:.
154
- - The catalogue yields the name of every field the account defines.
155
- - A call to `fetch` whose catalogue read fails requests no :Record: items.
162
+ # fetch-reads-catalogue
163
+ A call to `fetch` reads the field catalogue from :ProviderApi: once, before requesting any :Record:.
164
+ - The catalogue yields the name of every field the account defines.
165
+ - A call to `fetch` whose catalogue read fails requests no :Record: items.
156
166
 
157
- - A request for :Record: items from :ProviderApi: names every field in the catalogue and asks for at most 100 records.
158
- - Archived :Record: items are not requested.
167
+ # fetch-requests-records
168
+ A request for :Record: items from :ProviderApi: names every field in the catalogue and asks for at most 100 records.
169
+ - Archived :Record: items are not requested.
159
170
 
160
- - A call to `fetch` requests pages until :ProviderApi: returns a response carrying no next-page cursor.
161
- - Each page after the first is requested with the cursor from the previous response.
162
- - The :Record: items of every page are carried forward together.
171
+ # fetch-pages-records
172
+ A call to `fetch` requests pages until :ProviderApi: returns a response carrying no next-page cursor.
173
+ - Each page after the first is requested with the cursor from the previous response.
174
+ - The :Record: items of every page are carried forward together.
163
175
  ```
164
176
 
165
- GOOD — one spec, with the result stated first:
177
+ GOOD — one functional spec, with the result stated first:
166
178
 
167
179
  ```plain
168
180
  ***definitions***
@@ -175,13 +187,14 @@ GOOD — one spec, with the result stated first:
175
187
 
176
188
  ***functional specs***
177
189
 
178
- - :RecordSource: `fetch()` returns every non-archived :Record: with every field :ProviderApi: defines, paging under [resources/pagination.yaml](resources/pagination.yaml).
179
- - :RecordSource: reads the field catalogue once per `fetch()`.
180
- - `fetch()` fails before any request when `PROVIDER_API_KEY` is unset or empty, naming it.
181
- - A failed catalogue read fails `fetch()` before any :Record: is requested.
190
+ # fetch-records
191
+ :RecordSource: `fetch()` returns every non-archived :Record: with every field :ProviderApi: defines, paging under [resources/pagination.yaml](resources/pagination.yaml).
192
+ - :RecordSource: reads the field catalogue once per `fetch()`.
193
+ - `fetch()` fails before any request when `PROVIDER_API_KEY` is unset or empty, naming it.
194
+ - A failed catalogue read fails `fetch()` before any :Record: is requested.
182
195
  ```
183
196
 
184
- Merging is not in tension with the complexity limit. Split a spec when it implies more than 200 changed lines of code (`break-down-func-spec`); merge when several specs implement one operation that fits inside that budget. Fragment count is not a measure of size.
197
+ Merging is not in tension with the complexity limit. Split a functional spec when it implies more than 200 changed lines of code (`break-down-func-spec`); merge when several implement one operation that fits inside that budget. Fragment count is not a measure of size.
185
198
 
186
199
  ## The auth flow narrated step by step
187
200
 
@@ -190,9 +203,11 @@ BAD:
190
203
  ```plain
191
204
  ***functional specs***
192
205
 
193
- - :ProviderAuth: first reads the client id and the client secret, then builds a form-encoded body containing `grant_type=client_credentials`, the client id, and the client secret, then posts that body to the token endpoint, then parses the JSON response, then extracts the `access_token` and the `expires_in` fields, then stores the token in memory together with the moment it expires, and then attaches it to subsequent requests as a bearer token.
206
+ # obtain-token
207
+ :ProviderAuth: first reads the client id and the client secret, then builds a form-encoded body containing `grant_type=client_credentials`, the client id, and the client secret, then posts that body to the token endpoint, then parses the JSON response, then extracts the `access_token` and the `expires_in` fields, then stores the token in memory together with the moment it expires, and then attaches it to subsequent requests as a bearer token.
194
208
 
195
- - Before each request, :ProviderAuth: compares the current time to the stored expiry and, if the token has expired or is about to expire, repeats the whole procedure described above to obtain a new token.
209
+ # refresh-token
210
+ Before each request, :ProviderAuth: compares the current time to the stored expiry and, if the token has expired or is about to expire, repeats the whole procedure described above to obtain a new token.
196
211
  ```
197
212
 
198
213
  GOOD:
@@ -223,7 +238,7 @@ GOOD:
223
238
 
224
239
  The grant type, endpoint, body encoding, and response fields are in the security scheme. What survives is the policy the scheme does not describe: the env-var names, the refresh margin, the retry-once-on-401 rule, and the concurrency behavior.
225
240
 
226
- Almost all of it is implementation reqs — acquisition, caching, and refresh are machinery a caller never sees. Not all of it, though, and the rewrite has to name a component to say the rest. :ProviderAuth: performs the grant and has no observable surface; :AuthTokenManager: is what consumes it and hands tokens to :ProviderClient:, so it is the concept a functional spec can take as its subject. Without that consumer the section is left with a subject-less bullet, which `func-specs.md` rules out — and that one spec is the only line here a live conformance test can assert.
241
+ Almost all of it is implementation reqs — acquisition, caching, and refresh are machinery a caller never sees. Not all of it, though, and the rewrite has to name a component to say the rest. :ProviderAuth: performs the grant and has no observable surface; :AuthTokenManager: is what consumes it and hands tokens to :ProviderClient:, so it is the concept a functional spec can take as its subject. Without that consumer the section is left with a subject-less bullet, which `func-specs.md` rules out — and that one functional spec is the only line here a live conformance test can assert.
227
242
 
228
243
  ## Per-endpoint test reqs
229
244