@turri-dev/cli 0.1.7 → 0.1.8-next.91b957c

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 (96) hide show
  1. package/README.md +6 -8
  2. package/dist/btw.d.ts +2 -0
  3. package/dist/btw.js +2 -2
  4. package/dist/cli.js +6 -2
  5. package/dist/config-edit.d.ts +1 -1
  6. package/dist/config-edit.js +4 -0
  7. package/dist/config.d.ts +27 -0
  8. package/dist/config.js +28 -1
  9. package/dist/extension.d.ts +11 -0
  10. package/dist/extension.js +118 -14
  11. package/dist/genome.js +2 -0
  12. package/dist/host.d.ts +3 -1
  13. package/dist/host.js +4 -1
  14. package/dist/identity.d.ts +6 -1
  15. package/dist/identity.js +33 -7
  16. package/dist/init-config.d.ts +3 -0
  17. package/dist/init-config.js +15 -0
  18. package/dist/ledger-cli.d.ts +1 -0
  19. package/dist/ledger-cli.js +50 -0
  20. package/dist/ledger-tools.d.ts +10 -0
  21. package/dist/ledger-tools.js +64 -0
  22. package/dist/loop-cli.js +4 -0
  23. package/dist/loop-tools.js +3 -1
  24. package/dist/pi.d.ts +2 -0
  25. package/dist/pi.js +24 -4
  26. package/dist/regenerate/activity.d.ts +9 -0
  27. package/dist/regenerate/activity.js +11 -0
  28. package/dist/regenerate/agent-env.d.ts +7 -0
  29. package/dist/regenerate/agent-env.js +126 -5
  30. package/dist/regenerate/agent-shell.js +5 -0
  31. package/dist/regenerate/cases.js +3 -0
  32. package/dist/regenerate/chunk-plan.d.ts +5 -6
  33. package/dist/regenerate/chunk-plan.js +43 -10
  34. package/dist/regenerate/conformance-agents.js +2 -2
  35. package/dist/regenerate/conformance.js +6 -3
  36. package/dist/regenerate/debug-log.d.ts +3 -1
  37. package/dist/regenerate/debug-log.js +10 -2
  38. package/dist/regenerate/diagnose.js +12 -2
  39. package/dist/regenerate/environment-error.d.ts +6 -0
  40. package/dist/regenerate/environment-error.js +19 -1
  41. package/dist/regenerate/job-log.d.ts +3 -1
  42. package/dist/regenerate/job-log.js +8 -5
  43. package/dist/regenerate/jobs-tree.d.ts +7 -3
  44. package/dist/regenerate/jobs-tree.js +21 -6
  45. package/dist/regenerate/jobs.d.ts +18 -0
  46. package/dist/regenerate/jobs.js +62 -5
  47. package/dist/regenerate/ledger-view.d.ts +92 -0
  48. package/dist/regenerate/ledger-view.js +345 -0
  49. package/dist/regenerate/ledger.d.ts +275 -0
  50. package/dist/regenerate/ledger.js +349 -0
  51. package/dist/regenerate/lineage.d.ts +9 -1
  52. package/dist/regenerate/lineage.js +64 -12
  53. package/dist/regenerate/loop.d.ts +6 -0
  54. package/dist/regenerate/loop.js +36 -6
  55. package/dist/regenerate/pulse-files.d.ts +14 -0
  56. package/dist/regenerate/pulse-files.js +63 -0
  57. package/dist/regenerate/records.d.ts +5 -3
  58. package/dist/regenerate/records.js +6 -4
  59. package/dist/regenerate/regenerate.js +7 -5
  60. package/dist/regenerate/regression.js +4 -2
  61. package/dist/regenerate/services.js +3 -0
  62. package/dist/regenerate/side-panel.d.ts +2 -0
  63. package/dist/regenerate/side-panel.js +4 -3
  64. package/dist/regenerate/spec-map.js +8 -5
  65. package/dist/regenerate/test-scripts.js +18 -5
  66. package/dist/regenerate/testing.js +3 -0
  67. package/dist/regenerate/unit-review.js +3 -0
  68. package/dist/run-report.d.ts +1 -1
  69. package/dist/run-report.js +15 -5
  70. package/dist/self-invocation.d.ts +1 -1
  71. package/dist/self-invocation.js +3 -2
  72. package/dist/skill-progress.d.ts +1 -1
  73. package/dist/skill.d.ts +5 -0
  74. package/dist/skill.js +1 -0
  75. package/dist/skills.d.ts +14 -0
  76. package/dist/skills.js +19 -1
  77. package/dist/surface.d.ts +5 -0
  78. package/dist/surface.js +18 -0
  79. package/docs/authoring-plain.md +2 -2
  80. package/docs/config.md +24 -3
  81. package/docs/development.md +3 -1
  82. package/docs/headless.md +9 -4
  83. package/docs/hosting.md +46 -0
  84. package/docs/installation.md +1 -0
  85. package/docs/regenerating.md +11 -11
  86. package/docs/sandbox.md +5 -5
  87. package/docs/skills-and-gates.md +3 -1
  88. package/docs/using.md +39 -8
  89. package/genome/rules/func-specs.md +1 -0
  90. package/genome/rules/turri-regeneration.md +3 -0
  91. package/genome/skills/add-functional-spec/SKILL.md +12 -3
  92. package/genome/skills/add-functional-specs/SKILL.md +12 -2
  93. package/genome/skills/brood/SKILL.md +2 -0
  94. package/genome/skills/bud/SKILL.md +2 -0
  95. package/genome/skills/spawn/SKILL.md +47 -35
  96. package/package.json +1 -1
package/docs/using.md CHANGED
@@ -7,14 +7,14 @@ cd ~/my-project
7
7
  turri
8
8
  ```
9
9
 
10
- That is pi, with turri's tools, skills and themes loaded - `turri` alone, or with pi's options (`turri -c`, `turri --harness-model <m>`). It opens with turri's own banner - the jellyfish it is named after, regenerating until the conversation fills the screen: a pixel polyp on the sea floor grows into the jellyfish - a bell from pink down to indigo, an orange gut, neon tentacles - which swims a while, sinks back to the floor, and the polyp grows again, round and round: a picture in a terminal that shows images (Kitty, Ghostty, WezTerm, Warp, iTerm2), and drawn at a third of the size in half blocks in any other, tmux included (`src/jellyfish.ts` draws it, ported from the design system's pixel kit, `scripts/jellyfish-frames.mjs` writes the pictures) - turri's version (and, run from a clone, the commit it is on, and whether the clone has changes) and where its settings are changed - and only when something is wrong, skills that failed to load or agents' commands less fenced than they should be - rather than pi's startup header and resource list; `turri --verbose` shows those too. pi's "Update Available" notice is left out - turri's pi is a pinned dependency `pi update` never touches - and the terminal's tab reads `🪼 turri - <folder>`, not pi's `π`. Talk to it: ask it to start a project, add a feature, render a module, fix a spec. It decides which skill or tool applies - but not *how* a skill runs: `cultivate` hands the work to the gated runner, which owns the steps, the gates and the judges (see [skills and gates](skills-and-gates.md)).
10
+ That is pi, with turri's tools, skills and themes loaded - `turri` alone, or with pi's options (`turri -c`, `turri --harness-model <m>`). It opens with turri's own banner - the jellyfish it is named after, regenerating until the conversation fills the screen: a pixel polyp on the sea floor grows into the jellyfish - a bell from pink down to indigo, an orange gut, neon tentacles - which swims a while, sinks back to the floor, and the polyp grows again, round and round: a picture in a terminal that shows images (Kitty, Ghostty, WezTerm, Warp, iTerm2), and drawn at a third of the size in half blocks in any other, tmux included (`src/jellyfish.ts` draws it, ported from the design system's pixel kit, `scripts/jellyfish-frames.mjs` writes the pictures) - turri's version (and, run from a clone, the commit it is on, and whether the clone has changes) and where its settings are changed - and only when something is wrong, skills that failed to load or agents' commands less fenced than they should be - rather than pi's startup header and resource list; `turri --verbose` shows those too. pi's "Update Available" notice is left out - turri's pi is a pinned dependency `pi update` never touches - and the terminal's tab reads `🪼 turri - <folder>`, not pi's `π`. Talk to it: ask it to add a feature to a spec, render a module, fix a spec. It decides which skill or tool applies - but not *how* a skill runs: `cultivate` hands the work to the gated runner, which owns the steps, the gates and the judges (see [skills and gates](skills-and-gates.md)).
11
11
 
12
- The skills that build from scratch:
12
+ Three skills you start yourself, by their commands - turri never starts them on its own, and says which to type when one fits: `/brood`, `/spawn` and `/bud`, each with what you want after it - `/spawn a URL shortener in Go`. The skills that build from scratch:
13
13
 
14
14
  | skill | how it works |
15
15
  | --- | --- |
16
16
  | `brood` | first, how many questions the stack and product phases may ask - light (3), medium (5), thorough (10) or best judgement, broader with fewer, turri deciding what they leave open; then intent, stack, then testing - conformance tests on or off (into `config.turri.yaml`), their `***test reqs***` and the conformance testing script, which build nothing - then the product feature by feature, where every answer becomes one spec change - a git diff of the `.plain` files, written with `write_spec_diff` and rendered as a render spec diff pulse the moment it is written, with its conformance tests when they are on |
17
- | `spawn` | its quick twin: asks only what you want to build and which stack - one of the standard library's, your own, or `You choose` - and confirms a five-line brief, then writes the stack and the unit tests itself - conformance tests off, unless you ask for them - and writes the product feature by feature on its own, each feature a spec diff queued as it is written - after which you keep talking, and every change you ask for is a spec diff, and what is left to build is worked out again from the spec |
17
+ | `spawn` | its quick twin, for something running in minutes: asks what you want to build only when your message does not say, and chooses the stack itself unless you named one - conformance tests off, unless you ask for them - then writes the smallest thing that runs, which starts the first build at once, and the main slice of what you described and one more on their happy path, each a spec diff queued as it is written - nothing you did not describe: named only the kind of software, you get it running, and say what it does. You try each as it lands, and say `go on` for the next slice it proposed, or what to change instead - every change is a spec diff, and what is left to build is worked out again from the spec |
18
18
  | `mature` | for a spec you already have, rough or hand-written: on its own until it is fully rendered - renders what is not built, watches the agents building it, and when one struggles on something the spec leaves open, settles it in the spec as a spec diff, stops that build and renders it again; decides open choices itself and marks them in its report |
19
19
 
20
20
  Peeking is safe while a question is open - a skill's or the chat's: `ctrl+h` opens the side panel over the question, which waits under it as it was - the panel says `your question is waiting`, and `ctrl+h` or `esc` takes you back to answer it. (The question has the keys, so turri catches `ctrl+h` itself while one is open.) The dialog holds the question alone - no hint and no invitation; the `ctrl+h` under the job panel breathes until it is first pressed.
@@ -36,7 +36,8 @@ While a skill runs, a line above the input shows its phases, every one by name -
36
36
  | `engine` | show or choose the model the code is regenerated on - see [below](#choosing-a-model) |
37
37
  | `pulses` | the pulses - running, planned and finished - or one of them |
38
38
  | `halt` | halt a pulse, a module's planned pulses, or what `activate` started |
39
- | `diagnose` | why a pulse did not land, from its transcript: how it ended, the stages that went wrong, the last failing test run, the last review, the tool calls that failed |
39
+ | `diagnose` | why a pulse did not land, from its transcript: how it ended, the stages that went wrong, the last failing test run, the last review, the tool calls that failed - and what the [ledger](#the-ledger) recorded of it |
40
+ | `ledger` | what turri did, from the [ledger](#the-ledger), this session's and every earlier one's: a pulse as facts, by its id - its rounds, test runs, verdicts, healers, refusals and commits; events of some kinds counted and listed, for a module or since a time - `healer.failed`, or `healer` for the group; or the last runs, a line a pulse |
40
41
  | `lineage` | a module's lineage: what each regeneration and conformance run changed in it, and what it was regenerated from |
41
42
  | `cultivate` | run a gated skill, its steps and review gates enforced |
42
43
  | `release`, `activate` | try what is regenerated: release it to `dist/<module>` and activate it on this machine, installing what it needs - see [deploy](deploy.md) |
@@ -80,7 +81,7 @@ A render takes minutes, so in the TUI every render tool starts the work as a pul
80
81
 
81
82
  One module is shown at a time, with a tab for each module of the chain on the line under the top line, in the chain's order - the module it is built on to the left: `d365_version_api [d365_http_client] d365_utils 12 ›`. A tab regenerating spins, one stuck says `!`; what does not fit is counted at either end. `←` `→` go from one tab to the next. The module shown is the one in focus - the one regenerating now, else the one asked for, else the first - until you pick another tab; it goes back to following once another module is in focus, or the one in focus starts regenerating. Under the module's own text is what it imports, under **imported**, a folded block a file, `▸ from stdlib/backend/python-fastapi · 7 reqs · all built`, closed until opened. The modules it requires are tabs of their own: a chain of many modules is never drawn nested, one in the next. A map longer than the screen has a minimap down its right edge, a cell a slice in the colour of its most pressing mark, the slice shown solid. The map is read from the files - the code record, the `.plain` files, the tests record - so it is right the moment turri opens a project, before anything runs; the work loop's plan adds the pulses on top. It maps the files asked to build this conversation, else `module:` in `config.turri.yaml`, else the `.plain` files of the folder that no other one there imports or requires - the folder's files looked at again only once one of them, or its config, changes. `↑` `↓` move row by row, `enter` or `space` open and close an item or an import block - a functional spec opens to its sub-bullets and its `***acceptance tests***`, nested under it as the spec has them - `←` `→` go to the next module's tab, `o` and `c` open or close everything shown, `pgup` `pgdn` and the wheel scroll, `g`/`G` go to the top and the bottom.
82
83
 
83
- `p` goes to the **pulses** - and back - onto the pulse that regenerates the item under the cursor, and back onto the first item the pulse under the cursor regenerates. The pulses are every pulse as three sections - running, queued, finished - each opened and closed on its own (running and queued start open). A pulse is one line: its module, kind and number (`hubspot · regenerate pulse 1`, `hubspot · conformance pulse 2`) - so it is named wherever a pulse is named in a line (the job panel, the `pulses` tool, `/halt`, the command line), never by what it regenerates, which is in it, opened - its time (none while it is queued: it has not started) and its cost - a finished one's mark green when it passed, red when it failed or did not pass, amber when it was stopped. Opened, a running one shows what it is doing; a queued one, what it waits for; a finished one, its agents and what each spent, and whether it did not pass. Under it is a row for each file its spec diff changes - the file of the module being rendered first and open, the rest by name and closed - each opening onto that file's lines. A file with nothing added or taken out is not listed. `↑` `↓` move, `enter` or `space` open and close what is under the cursor, `→` `←` open and close (`←` on a closed pulse goes to its section, on a closed file to its pulse), `o` and `c` open or close every pulse of the section - or, on a file, every file of its pulse - `pgup` `pgdn` and the wheel scroll, `g`/`G` go to the top and the bottom. The cursor stays on its row when the pulse under it moves on; a pulse opened closes when it moves to another section. What is open is kept while the panel is closed. What the agents said and did is not shown - it is in each pulse's log (see [Agent logs](#agent-logs)).
84
+ `p` goes to the **pulses** - and back - onto the pulse that regenerates the item under the cursor, and back onto the first item the pulse under the cursor regenerates. The pulses are every pulse as three sections - running, queued, finished - each opened and closed on its own (running and queued start open) - and a fourth, **earlier sessions**, closed, when the [ledger](#the-ledger) has pulses of sessions before this one: its last three runs', each pulse read only - opened, what the ledger says of it (how it ended, its rounds and test runs, the healers, what turri refused and committed, its last stages and its log) - and a line for how many more runs it has. A pulse is one line: its module, kind and number (`hubspot · regenerate pulse 1`, `hubspot · conformance pulse 2`) - so it is named wherever a pulse is named in a line (the job panel, the `pulses` tool, `/halt`, the command line), never by what it regenerates, which is in it, opened - its time (none while it is queued: it has not started) and its cost - a finished one's mark green when it passed, red when it failed or did not pass, amber when it was stopped. Opened, a running one shows what it is doing; a queued one, what it waits for; a finished one, its agents and what each spent, and whether it did not pass. Under it is a row for each file its spec diff changes - the file of the module being rendered first and open, the rest by name and closed - each opening onto that file's lines. A file with nothing added or taken out is not listed. `↑` `↓` move, `enter` or `space` open and close what is under the cursor, `→` `←` open and close (`←` on a closed pulse goes to its section, on a closed file to its pulse), `o` and `c` open or close every pulse of the section - or, on a file, every file of its pulse - `pgup` `pgdn` and the wheel scroll, `g`/`G` go to the top and the bottom. The cursor stays on its row when the pulse under it moves on; a pulse opened closes when it moves to another section. What is open is kept while the panel is closed. What the agents said and did is not shown - it is in each pulse's log (see [Agent logs](#agent-logs)).
84
85
 
85
86
  `ctrl+h` again, or `esc`, closes it and goes back to the chat. Beside the chat, one side has the keys and the other is drawn faint: `ctrl+h` switches sides - from the chat to the panel, from the panel to the chat, the panel staying and following the pulses - `esc` gives the chat the keys too, and a click gives them to the side clicked. `ctrl+c` closes the panel; so do `s`, over the whole screen, then `esc`. (pi's regular screen, `--tui-mode regular`, reads no mouse: there it is the keys alone.) While the panel has the keys, every key is the panel's, whatever else happens: a question the chat model asks in the background (`ask_user`) waits in the chat, unanswered - an `enter` in the panel never answers it - and the panel's top line says "the chat is waiting for your answer". Back in the chat, the question is there, with the keys.
86
87
  - `turri` runs pi in fullscreen mode, so the conversation stays where you scroll it while the pulses redraw (PgUp/PgDn, the wheel); `--tui-mode regular` goes back to the terminal's own scrollback.
@@ -151,7 +152,9 @@ A provider failure - no credits, bad key, rate limit - is raised with the provid
151
152
 
152
153
  Each `plain_modules/<module>` is a git repository whose git directory is `.plaingit` rather than `.git`, so it stays plain files to your own repository. A commit is made after every step that changes the module - a render, a functionality regenerated, a conformance run, a regression repair, a spec change. `/lineage [module]` and `lineage` show it.
153
154
 
154
- The last commit is also the last known good state. Every render, functionality regenerated, spec change and conformance run starts by putting the codebase it works in back to it, so if turri was stopped or restarted mid-pulse, whatever that pulse left half-written is undone first - and one that does not pass is undone the same way when it ends, commits and all. Only work that passed is committed. Installed dependencies and caches are not in the history and stay. With git directly:
155
+ The last commit is also the last known good state. Every render, functionality regenerated, spec change and conformance run starts by putting the codebase it works in back to it, so if turri was stopped or restarted mid-pulse, whatever that pulse left half-written is undone first - and one that does not pass is undone the same way when it ends, commits and all. Only work that passed is committed. Installed dependencies and caches are not in the history and stay.
156
+
157
+ The history is turri's own: the hooks your git config names (`core.hooksPath` - gitleaks, husky) do not run on its commits. When work that passed cannot be committed all the same - a `.plaingit/index.lock` a git stopped mid-commit left, a full disk - the pulse does not land: the next start would undo it while turri took it as built. It is rolled back, and the stop says what git said and how to fix it. Any other step's commit failing leaves only a gap in the history. With git directly:
155
158
 
156
159
  ```bash
157
160
  git --git-dir=plain_modules/<module>/.plaingit --work-tree=plain_modules/<module> log
@@ -159,14 +162,41 @@ git --git-dir=plain_modules/<module>/.plaingit --work-tree=plain_modules/<module
159
162
 
160
163
  ## Agent logs
161
164
 
162
- When an agent does something you cannot explain, its logs are where to look: the chat shows what its pulse is doing, not what its agents said. Every agent a render starts - the coding agent, the conformance agent, the repair agent, the spec-steps planner - also streams its whole conversation to a file of its own, always.
165
+ When an agent does something you cannot explain, its logs are where to look: the chat shows what its pulse is doing, not what its agents said. Every agent a render starts - the coding agent, the conformance agent, the repair agent, the spec-steps planner - also streams its whole conversation to a file of its own.
163
166
 
164
167
  The logs are in `.turri/debug/` in the project, beside `plain_modules`, one per agent, named by when it started and what it is: `2026-09-26T13-45-02-123Z-app-3-coding-agent.log`. Each starts with the pulse it runs for, its model and thinking level, its folder, its saved pi session, its tools and its system prompt, and then has, in order and stamped with the time: every prompt it is sent, whole; its thinking and replies as they stream; every tool call with its arguments, numbered
165
168
  - `→ #3 bash` - and its whole result under the same number, `← #3 bash done`, since calls made together run at once and finish in any order; a tool call a response was cut off in, marked as never run; each response's stop reason, tokens and cost; the provider's retries and errors; and how each turn ended. Every line is on disk as it happens, so `tail -f` follows an agent live and a run that crashed leaves its log up to that moment. The pulse's own log names each agent's log as it starts.
166
169
 
167
170
  Beside them, each pulse has a log of its own in `.turri/jobs/` - `<time>-<pulse id>-<kind>.log`: its whole transcript, written as it happens. The harness's stages, the functional spec or the diff it builds, and every one of its agents in turn - each prompt, its thinking and replies, every tool call and its result, whole where the screen clips them - and how the pulse ended. A finished pulse, opened in the side panel, names it. It is the one to read for a pulse as a whole; an agent's own log has its system prompt, tokens and retries besides.
168
171
 
169
- No agent can read the logs: they are outside `plain_modules` - or, for a `--build-dir` outside it, beside that folder rather than in it. Nothing prunes them either - delete the folder when you are done with it. A log that cannot be written is given up on without failing the render.
172
+ They are kept only in [debug mode](config.md#debug-mode) - `debug: true` in `config.turri.yaml`, or `TURRI_DEBUG=1`, or `turri --debug` for one run. Otherwise a pulse's logs are written while it runs - the diagnosis of a pulse that fails twice reads them, and quotes what it needs, never sending you to a file that is about to go - and removed as it ends, and an agent outside a pulse writes none; the [ledger](#the-ledger) still says what each pulse did, how it ended and what it cost. To read why an agent did something, turn debug mode on and run it again.
173
+
174
+ The coding and conformance agents cannot read the logs: they are outside `plain_modules` - or, for a `--build-dir` outside it, beside that folder rather than in it. The diagnosis of a failed pulse reads them. In debug mode nothing prunes them - delete the folder when you are done with it. A log that cannot be written is given up on without failing the render.
175
+
176
+ ## The ledger
177
+
178
+ The logs keep everything a pulse's agents said, for reading one pulse closely. The ledger keeps what turri did, as facts, across pulses, sessions and runs - to answer *why did last night's run fail*, *how often does the debugger fail*, *what did this module cost*, long after the session that ran it is gone (`src/regenerate/ledger.ts`).
179
+
180
+ It is in `.turri/ledger/` in the project, a JSON line an event, one file a run - a conversation, a headless run, a host's session: `<time>-<run>-p<pid>.jsonl`. Each line has the time with its date, its order in the run, the run, and - where they apply - the pulse, the module and the agent. What it records:
181
+
182
+ | | |
183
+ | --- | --- |
184
+ | runs | `run.started` (how it was started, turri's version and commit, the machine), `run.ended` |
185
+ | pulses | `job.queued`, `job.started`, every `job.stage`, `job.retried`, `job.finished` - its status, whether it landed, how long it ran, what it cost, how it ended |
186
+ | the work loop | `loop.halted`, `loop.stopped` (a pulse the spec moved on from), `planner.failed`, `planner.fellBack` |
187
+ | the model | `model.call` (time and tokens), `model.turn`, `model.compaction`, `provider.retry`, `provider.stall`, `provider.error`, `turn.stopped` (a turn turri ended itself, and why) |
188
+ | tools and tests | `tool.call` (the tool, how long, whether it failed - never its arguments or result), `script.run` (the testing script, its exit, how long, whether the time limit stopped it, the failure's fingerprint, and `mutated` for a `can_it_fail` run on code broken on purpose) |
189
+ | the gates | `gate.round`, `review.verdict`, `arbiter.ruling`, `judge.verdict` |
190
+ | what turri refused | `guard.refused` (a repeated call, a call past its budget, a tool the turn does not have), `command.refused`, `audit.putBack` |
191
+ | the healers | `healer.started`, `healer.ended` with what it found, `healer.failed` and why - the debugger, the diagnosis of a failed pulse |
192
+ | the history | `history.committed`, `history.failed`, `history.reset`, `history.rolledBack` |
193
+ | the environment | `environment.error` |
194
+
195
+ Never in it: prompts, replies, thinking, tool arguments and results, file contents. What an event does carry - a stage, an error's first line - is masked as the logs are.
196
+
197
+ `turri ledger` prints the last runs, a line a pulse; `turri ledger <pulse>` one pulse - its rounds, its test runs and how many failed the same way, the verdicts, the healers, what turri refused, what its history recorded, its log; `--json` the events themselves, for `jq`. In the chat, `ledger` is the way in - a pulse of this session or an earlier one, the events of some kinds counted (how often the debugger failed this week: `kinds: [healer.failed], since: 7d`), the last runs - and `pulses` lists the last three earlier runs under this session's pulses, `pulses` and `diagnose` tell one of them by its id, and `diagnose` adds the ledger's facts to a pulse of this session; the side panel's pulses list has them as **earlier sessions** (see [the side panel](#in-a-conversation)).
198
+
199
+ It is for looking up, never for deciding: what to build comes from the records alone (see [what the code is built from](regenerating.md#what-the-code-is-built-from)), so deleting `.turri/ledger/` loses nothing but what can be looked up. When a run first writes to the project, the files of runs that have ended are gzipped and the oldest pruned past `ledger-keep:` megabytes - 100 unset, `0` for none at all; a run still going is never touched. `.turri` ignores itself, so the ledger is never committed, and nothing of it is sent anywhere. A ledger that cannot be written is said once and given up on, never failing the work.
170
200
 
171
201
  ## From the command line
172
202
 
@@ -183,6 +213,7 @@ turri regenerate <file.plain> --from-scratch-chain # the same for every module
183
213
  turri spec-diff <file.plain> <diff> # apply a spec diff, and regenerate it
184
214
  turri conform <file.plain> 1 # black-box tests for functionality 1
185
215
  turri lineage <module> # what each regeneration changed in a module, and when
216
+ turri ledger [pulse] # what turri did here: the last runs and their pulses, or one pulse
186
217
  turri cultivate brood # run a skill directly - by name, the project's too, or by its folder
187
218
  turri release <file.plain> # release what is regenerated to dist/<module>, and activate it here
188
219
  ```
@@ -58,6 +58,7 @@ GOOD — statements of fact with concrete subjects:
58
58
  - The first spec must still imply a testable outcome; setup alone is not a functional spec
59
59
  - Prefer one minimal entry point or public operation with a deterministic result that can be invoked and verified
60
60
  - Defer persistence, integrations, multiple interfaces, branching workflows, and cross-cutting behavior until later specs can build on the generated baseline
61
+ - A spec may start on its happy path and be hardened later - validation, edge cases and errors added to it by changing it - once the software has been tried; it must still say exactly what it does for the input it covers
61
62
  - 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
 
63
64
  ## Chronological ordering
@@ -26,7 +26,10 @@ The other rules say what a spec means. This one says what turri does with a chan
26
26
  - A definition changed patches every functional spec that uses its concept, directly or through other definitions. So does a change to a linked resource: the spec or definition linking it is changed though its text is not. A widely used definition is the costly edit - not a spec's position
27
27
  - Implementation reqs alone, or definitions no functional spec uses, are a mechanical change: the code adapts, and no test is written or changes what it asserts
28
28
  - Test reqs and acceptance tests reach the conformance tests only, never the code
29
+ - A functional spec regenerated again by name has its conformance tests written again once its new code lands: what they check that the spec leaves open - a path, a field, a message the old code chose - goes by the new code
29
30
  - Definitions moved to a common module and reqs reordered are recorded, not rendered
31
+ - A functional spec written on its happy path and hardened later - its validation, edge cases and errors added to it - is patched in place each time: growing a spec a step at a time costs no more than writing it whole up front
32
+ - A module's first pulse, when it builds one functional spec - the project set up and the smallest thing that runs - lands on its unit tests with no review
30
33
 
31
34
  ## What a coding agent sees
32
35
 
@@ -21,7 +21,7 @@ allowed-tools: [read, write, edit, bash, ls, grep, find]
21
21
  3. **Draft the functional spec** following the rules below, then run the review pass in `concise-specs.md` over the draft — trim it to the shortest wording that keeps every fact before any other check.
22
22
  4. **Analyze complexity** — use the `analyze-if-func-spec-too-complex` skill to verify the drafted spec implies ≤ 200 LOC. If too complex, use the `break-down-func-spec` skill to split it, then repeat from step 3 for each resulting spec.
23
23
  5. **Check for conflicts** with every existing functional spec — this is critical. Run `analyze-func-specs` **once** with the new spec plus all existing specs (in the file and in any `requires` chain) as a single batch. The batched analyzer returns every conflicting pair in one call — do **not** invoke a pair-by-pair analyzer. For each conflicting pair it reports, run `resolve-spec-conflict` on that pair; re-run `analyze-func-specs` over the touched set after each resolution until the verdict is `COMPATIBLE`.
24
- 6. **Append the spec** to the end of the `***functional specs***` section (specs are chronological; new ones go last).
24
+ 6. **Insert the spec where it best fits** in the `***functional specs***` section - see Placement below.
25
25
  7. **Read the file again** to confirm correct placement and syntax.
26
26
 
27
27
  ## Rules
@@ -35,7 +35,16 @@ Each functional spec must imply a **maximum of 200 changed lines of code**. If t
35
35
  Specs are rendered incrementally, top to bottom. The renderer has **no knowledge of future specs** — only previously rendered specs are in context. This means:
36
36
  - A new spec can reference behavior defined by earlier specs.
37
37
  - A new spec **cannot** assume anything about specs that come after it.
38
- - Place the new spec at the correct position if it must come before a future spec; otherwise append at the end.
38
+
39
+ ### Placement
40
+
41
+ Put the new spec where it best fits the spec as it reads, not at the end by default:
42
+ - **Below every spec it builds on** - each spec whose behaviour it references or extends, and the first spec using each concept it relies on.
43
+ - **Above every existing spec that builds on it** - one that already assumes what the new spec adds.
44
+ - **Within those bounds, beside the specs of the same feature** - usually straight after the last spec it extends, so a feature's specs read as one group.
45
+ - **At the end** only when it starts something new or fits nowhere better.
46
+
47
+ An insertion in the middle costs no more than one at the end: turri regenerates it as one addition, and the specs after it are not rebuilt (`turri-regeneration.md`). Never append just to avoid moving the numbering.
39
48
 
40
49
  ### Language Agnosticism
41
50
 
@@ -81,4 +90,4 @@ If the functional spec needs verification, use the `add-acceptance-test` skill t
81
90
  - [ ] Sentences are short, clear, and unambiguous
82
91
  - [ ] Trimmed per `concise-specs.md`: nothing obvious, no rationale, no uncheckable adjectives or hedges, plain words throughout
83
92
  - [ ] No redundancy with existing specs
84
- - [ ] Placed in correct chronological position (usually at the end)
93
+ - [ ] Placed where it best fits: below what it builds on, above what builds on it, beside its feature's specs
@@ -36,7 +36,7 @@ This skill is `add-functional-spec` applied **one spec at a time, in order**, wi
36
36
  - every spec from this batch that has already been inserted.
37
37
 
38
38
  The batched analyzer returns every conflicting pair in one call — do **not** loop over pairs invoking a per-pair analyzer. For each conflicting pair it reports, run `resolve-spec-conflict`. Apply the resolution — which may revise the new spec, an existing spec, or both — then re-run `analyze-func-specs` once over the touched set until the verdict is `COMPATIBLE`.
39
- 3. **Append the spec** to the `***functional specs***` section. Specs are chronological; the new entry goes at the end (unless an earlier existing spec must come *after* it — in that rare case, insert at the correct position).
39
+ 3. **Insert the spec where it best fits** in the `***functional specs***` section - see Placement below.
40
40
  5. **Read the file again** to confirm correct placement, ordering, and syntax for the full batch.
41
41
 
42
42
  Order matters: each new spec is inserted only after its complexity and conflict checks pass, so subsequent specs in the batch are always checked against an already-validated file.
@@ -56,6 +56,16 @@ Specs are rendered incrementally, top to bottom. The renderer has **no knowledge
56
56
  - A new spec **cannot** assume anything about specs that come after it.
57
57
  - Order the batch so that each spec only depends on specs that precede it. If two new specs would otherwise reference each other, the dependent one comes second.
58
58
 
59
+ ### Placement
60
+
61
+ Put each new spec where it best fits the spec as it reads, not at the end by default:
62
+ - **Below every spec it builds on** - each spec whose behaviour it references or extends, the batch's own included, and the first spec using each concept it relies on.
63
+ - **Above every existing spec that builds on it** - one that already assumes what the new spec adds.
64
+ - **Within those bounds, beside the specs of the same feature** - usually straight after the last spec it extends, so a feature's specs read as one group.
65
+ - **At the end** only when it starts something new or fits nowhere better.
66
+
67
+ The batch need not stay together: each spec goes where it fits. An insertion in the middle costs no more than one at the end: turri regenerates it as one addition, and the specs after it are not rebuilt (`turri-regeneration.md`). Never append just to avoid moving the numbering.
68
+
59
69
  ### Language Agnosticism
60
70
 
61
71
  Write in terms of behavior, concepts, and domain logic — not implementation constructs. Avoid language-specific types, generics syntax, framework annotations, or other constructs tied to a particular language or framework. General technical terms (null values, JSON types, HTTP status codes) are fine. Language-specific guidance belongs in `***implementation reqs***`.
@@ -115,4 +125,4 @@ If any of the newly added functional specs need verification, use the `add-accep
115
125
  - [ ] Sentences are short, clear, and unambiguous
116
126
  - [ ] Every spec trimmed per `concise-specs.md`: nothing obvious, no rationale, no uncheckable adjectives or hedges, plain words throughout
117
127
  - [ ] No redundancy with existing specs or within the batch
118
- - [ ] Specs placed in correct chronological positions
128
+ - [ ] Each spec placed where it best fits: below what it builds on, above what builds on it, beside its feature's specs
@@ -15,6 +15,8 @@ description: >-
15
15
  specs are the source of truth).
16
16
  allowed-tools: [read, write, edit, bash, ls, grep, find, write_spec_diff]
17
17
  metadata:
18
+ # Started only by the person, with its command - /brood - never by the model on its own.
19
+ command-only: true
18
20
  # What each phase does, in a line - shown under the skill's progress while it runs.
19
21
  phases:
20
22
  intent: "what problem this solves, for whom, and how you will know it works"
@@ -13,6 +13,8 @@ description: >-
13
13
  to start fast) or for editing generated code (the .plain specs are the source of truth).
14
14
  allowed-tools: [read, write, edit, bash, ls, grep, find, write_spec_diff]
15
15
  metadata:
16
+ # Started only by the person, with its command - /bud - never by the model on its own.
17
+ command-only: true
16
18
  # What each phase does, in a line - shown under the skill's progress while it runs.
17
19
  phases:
18
20
  intent: "what the feature is for, who it serves, and what it leaves out"
@@ -1,23 +1,25 @@
1
1
  ---
2
2
  name: spawn
3
3
  description: >-
4
- The quick twin of `brood`: asks only what the user wants to build and which stack to build it on -
5
- one question, "you choose" among its answers - then writes the whole `***plain` spec on its own - the
6
- stack, the unit tests and the product, feature by feature - making every choice itself where the user
7
- said nothing, and queues each feature as a render spec
8
- diff job the moment it is written. Conformance tests are off unless the user asks for them. No
9
- interview beyond intent, no gates. The user then keeps
10
- talking in the conversation, and every change they ask for is a spec diff: what is left to build
11
- is worked out again from the spec. Use when the user wants to start a new project fast, or says to just build
12
- it. For a full interview that settles the stack, the testing and every feature with the user, use
13
- `brood`. Not for adding a feature to an existing project (use `bud`).
4
+ The quick twin of `brood`, built for the shortest time to first regeneration: something running
5
+ in minutes, then grown a step at a time, the way a developer starts - the smallest thing that runs first, then the
6
+ main thing half-built, run and tried, then the next. Asks what the user wants to build only when
7
+ their message does not say, and the stack only when it cannot choose one this machine builds;
8
+ sets up the module, writes a first spec - the smallest thing that runs - that starts the first build at once, then the
9
+ first slices of the product on their happy path, and hands over: the user tries each slice as it
10
+ lands and says what next. Conformance tests are off unless the user asks for them. No gates. Use
11
+ when the user wants to start a new project fast, or says to just build it. For a full interview
12
+ that settles the stack, the testing and every feature with the user, use `brood`. Not for adding a
13
+ feature to an existing project (use `bud`).
14
14
  allowed-tools: [read, write, edit, bash, ls, grep, find, write_spec_diff]
15
15
  metadata:
16
+ # Started only by the person, with its command - /spawn - never by the model on its own.
17
+ command-only: true
16
18
  # What each phase does, in a line - shown under the skill's progress while it runs.
17
19
  phases:
18
- intent: "what you want to build, and which stack to build it on"
19
- groundwork: "the language, frameworks, storage and architecture"
20
- product: "writes the features one by one - each starts a regenerate pulse"
20
+ start: "what you want to build, and the stack - asked only when it is not clear"
21
+ skeleton: "sets up the project and writes the smallest spec that runs, so the first build can start"
22
+ regenerate: "writes the first features, simplest version first - each starts a build"
21
23
  # It writes its spec changes one after another on its own: no answer between them.
22
24
  paced: false
23
25
  ---
@@ -28,9 +30,11 @@ Load the `***plain` syntax rules before writing anything - they are in the syste
28
30
 
29
31
  ## Role
30
32
 
31
- Act as a `***plain` spec writer who decides. The only output is `.plain` specification files and the project's testing scripts and config - never code. Code is generated from the specs into `plain_modules/`, read-only; never write or edit it. Say everything in terms of specs: "I'll put this in the spec."
33
+ Act as a `***plain` spec writer who gets something running first. The only output is `.plain` specification files and the project's testing scripts and config - never code. Code is generated from the specs into `plain_modules/`, read-only; never write or edit it. Say everything in terms of specs: "I'll put this in the spec."
32
34
 
33
- The user tells you what they want, once, and which stack to build it on - or leaves that to you. Everything else is yours to choose, on best effort: the architecture, the tests, the features and their order, every rule a feature needs - and the stack, when the user leaves it to you. Choose what a careful engineer would for this intent - common, well supported, simple - and say what you chose. Never ask about any of the rest. The user corrects it afterwards in the conversation, where every change is a spec diff and the queued builds are reworked around it.
35
+ What counts is the time to first regeneration: how soon the first build starts, and the user can try what it built. Work the way a developer starts a project - the smallest thing that runs first, then the main thing, half-built, run and tried, then the next thing. Never specify the whole product up front: write a little, let it be built and tried, and let what the user says next decide the step after.
36
+
37
+ What the software does is the user's to say. Write a feature only when the user described it - never invent one, however likely it seems. Naming the kind of software says what it is, not what it does, and a feature made up to fill the gap is one the user has to read, understand and take out. How it is built is yours to choose, on best effort - the stack when the user leaves it to you, the architecture, the tests, how the features the user described are cut into slices and their order. Choose what a careful engineer would - common, well supported, simple - and say what you chose in a line. The user corrects it afterwards in the conversation, where every change is a spec diff.
34
38
 
35
39
  Read what is already there first: an existing `.plain` file, `config.turri.yaml` (or the old `config.yaml`, with no `config.turri.yaml`), `template/`, `test_scripts/`. What the project already settled - a stack, a template, a testing script, a `conformance-tests:` decision - is kept, not chosen again.
36
40
 
@@ -39,40 +43,48 @@ Read what is already there first: an existing `.plain` file, `config.turri.yaml`
39
43
  - Templates go in `template/`; import paths omit the `template/` prefix. Resources go in `resources/`.
40
44
  - Generated code lands in `plain_modules/<module>/code/`, conformance tests in `plain_modules/<module>/tests/` (both read-only).
41
45
  - One module, unless the intent needs two stacks - a web frontend and an API backend. Then two modules side by side, neither requiring the other, sharing what they both mean through one imported module in `template/`. Each is on a stack of its own, whose testing scripts are named in `config.turri.<stack>.yaml` beside `config.turri.yaml` (`unittests-script:`, `conformance-tests-script:`) - `config.turri.backend.yaml`, `config.turri.frontend.yaml`. Name each stack after the module it builds - `config.turri.backend.yaml` for `backend.plain` - and that module is built with it by itself, with nothing to choose; a stack named otherwise is passed as `stack` to `regenerate` in the chat, or `--stack <stack>` on the command line.
46
+ - A **slice** is one functional spec on its happy path: what the feature does when the input is right - no validation, no edge cases, no permissions, no persistence unless keeping data is the point. It is hardened later by changing that spec, which turri patches in place.
42
47
 
43
48
  ## Steps
44
49
 
45
- ### intent
50
+ ### start
51
+
52
+ Find out what to build and on which stack - asking as little as the user's message allows, ideally nothing.
46
53
 
47
- Find out what the user wants to build - the only thing you ask about.
54
+ - **What to build.** When the user's message says what kind of software it is - a web app, an API, a CLI - ask nothing: that is enough to start. Otherwise ask one open question with `ask_user` and `free_form: true`: what should it do? Ask no follow-ups. An answer that names only the kind of software is enough too: the first spec is built, and what it does comes later, from the user.
55
+ - **The stack.** It has to be one this machine can build: the agents use its toolchains and install none. `<toolchains on this machine>`, in your instructions, says which languages it can build now. When the user named a stack, take it. When they did not, choose one yourself from the standard library's stacks for the kind of software it is (the stdlib rule, in `<plain-rules>`), in a language the machine can build now - ask nothing. Ask only when the user named a stack in a language the machine lacks: say what to install first and that `turri doctor` checks it, and ask one `ask_user` question - wait for that, or let you choose another.
48
56
 
49
- If what the user has already said answers it, do not ask again. Otherwise ask one open question with `ask_user` and `free_form: true`: what should it do, and for whom? Ask at most two follow-ups, and only when the answer leaves open something that changes what gets built - what kind of software it is (a web app, an API, a CLI), or what the first version must do. Never ask about testing, structure or details: those are yours.
57
+ Then say in three lines what you will build first and on which stack, and carry on. Ask for no confirmation, and write nothing to disk in this step.
50
58
 
51
- Then the stack - the one technical question, because it has to be one this machine can build: the agents use its toolchains and install none, so a Go project on a laptop without Go stops at its first build. `<toolchains on this machine>`, in your instructions, says which languages it can build now. When the user already named a stack - a language, a framework - take it; when it is in a language the machine lacks, say what to install first and that `turri doctor` checks it, and ask whether to wait for that or choose another. Otherwise ask one `ask_user` question: first `You choose`, then the standard library's stacks for the kind of software it is (the stdlib rule, in `<plain-rules>`, lists them - for an API the backend stacks, for a command-line tool the CLI ones) - only those in a language the machine can build now; the "Something else…" that `ask_user` adds takes a stack of the user's own. A product of two kinds - a web app and its API - is one question a module. `You choose` leaves it to you, as the groundwork step says.
59
+ ### skeleton
52
60
 
53
- Then state the brief back in five short bullets - the problem, the primary user, what they can do with it, what makes the first version useful, and what the first version leaves out - with the stack in a line under them (the user's, or `chosen when it is built` when it is left to you) - and ask one `ask_user` question with the options `Build it` and `Change something`, the brief passed whole as its `context`: the dialog shows only the question, its options and its `context`. On a change, fold it in and ask again. Write nothing to disk in this step.
61
+ Set the module up and start the first build - on your own, no questions.
54
62
 
55
- ### groundwork
63
+ 1. **The module and its stack.** Create the `.plain` file (and the template, when it helps), with its frontmatter and a one-sentence product description - from what the user said, and nothing more, and write the stack into `***implementation reqs***`: the language, the framework, storage, the architecture and layout - one requirement per fact, at the right scope, the shared ones on the template. Follow `genome/rules/impl-reqs.md`. When the standard library has a template for the stack, import it and write only what the module needs beyond it.
64
+ 2. **Unit tests.** A `:UnitTests:` requirement - the framework, and how they are run - unless the imported stack already sets it, and the unit testing script. Keep one turri already finds (named in `config.turri.yaml`, or the one `run_unittests*.sh` in the root or `test_scripts/`); otherwise write `test_scripts/run_unittests_<language>.sh` by following the `implement-unit-testing-script` skill. Never link it from the specs. The script runs the stack's static checks with the unit tests - the formatter in check mode, the linter, the type checker - and they count as the tests do.
65
+ 3. **Conformance tests: off.** Keep a `conformance-tests:` decision the project's config already holds - `config.turri.yaml`, or the old `config.yaml`. Otherwise write `conformance-tests: false` into `config.turri.yaml`, changing nothing else in it - a project with only a `config.yaml` has it copied to `config.turri.yaml` first, and `config.yaml` is never written - and write no `***test reqs***`, import no standard library conformance template, and write no conformance testing script. Only when the user asked for conformance tests, turn them on instead: `conformance-tests: true`, the `***test reqs***` - `:ConformanceTests:` requirements following `genome/rules/test-reqs.md`, or the stack's standard library conformance template imported when the stack is from it - and `test_scripts/run_conformance_tests_<language>.sh`, by following the `implement-conformance-testing-script` skill, unless turri already finds one.
66
+ 4. Run `validate` on every module you wrote, and fix what it finds.
67
+ 5. **The first spec.** Write the module's first functional spec with `write_spec_diff`: the smallest thing that runs and shows something - the server answers one request (`GET /` with the app's name), the command-line tool prints its usage, the page shows the app's name, the library exposes one call with a fixed result. It holds no product logic, so its build only sets the project up and lands fast - and its pulse is not reviewed. Follow `add-functional-spec` for its wording, and keep it to that one observable result.
56
68
 
57
- Set up everything the first build needs, on your own, with the ordinary file tools - no questions, nothing built, and `write_spec_diff` not used.
69
+ `write_spec_diff` takes a git diff of the `.plain` file(s): `diff --git a/<file> b/<file>`, `--- a/<file>`, `+++ b/<file>`, then the hunks with a few lines of context, paths from the project root. It applies the change and queues its build. Go straight on to the next step - never wait for a build.
58
70
 
59
- 1. **The module and its stack.** Create the `.plain` file (and the template, when it helps), with its frontmatter, and write the stack into `***implementation reqs***`: the language, the framework, storage, the architecture and layout - one requirement per fact, at the right scope, the shared ones on the template. The stack is the user's, when they named or chose one; left to you, choose what fits the intent - a mainstream stack, with the fewest moving parts - in a language this machine can build now (`<toolchains on this machine>`). Follow `genome/rules/impl-reqs.md`. When the standard library has a template for it - a backend, a frontend, a command-line tool or a library (the stdlib rule, in `<plain-rules>`) - import that template and write only what the module needs beyond it.
60
- 2. **Unit tests.** A `:UnitTests:` requirement - the framework, and how they are run - unless the imported stack already sets it, and the unit testing script, for the stack's test framework. Keep one turri already finds (named in `config.turri.yaml`, or the one `run_unittests*.sh` in the root or `test_scripts/`); otherwise write `test_scripts/run_unittests_<language>.sh` by following the `implement-unit-testing-script` skill. Never link it from the specs. The script runs the stack's static checks with the unit tests - the formatter in check mode, the linter, the type checker - and they count as the tests do.
61
- 3. **Conformance tests: off**, so each feature is built fast. Keep a `conformance-tests:` decision the project's config already holds - `config.turri.yaml`, or the old `config.yaml`. Otherwise write `conformance-tests: false` into `config.turri.yaml`, changing nothing else in it - a project with only a `config.yaml` has it copied to `config.turri.yaml` first, and `config.yaml` is never written - and write no `***test reqs***`, import no standard library conformance template, and write no conformance testing script. Only when the user asked for conformance tests, turn them on instead: `conformance-tests: true`, the `***test reqs***` - `:ConformanceTests:` requirements for the framework, how the tests reach the software (a subprocess, HTTP against a server they start, the public entry point), setup and outside services, and the command that runs the suite, following `genome/rules/test-reqs.md`, or the stack's standard library conformance template imported when the stack is from it - and `test_scripts/run_conformance_tests_<language>.sh`, by following the `implement-conformance-testing-script` skill, unless turri already finds one.
71
+ ### regenerate
62
72
 
63
- Run `validate` on every module you wrote, and fix what it finds. Then say in a few lines what you chose - the stack, the architecture, the tests - and carry on. Do not ask for confirmation.
73
+ Write the first slices of what the user described, each a spec diff, while the first spec builds - on your own, without asking.
64
74
 
65
- ### product
75
+ **Only what the user described.** Every slice comes from something the user said the software does. When they said only what kind of software it is, write no slice: the step writes nothing, and the handover invites them to say what it should do first.
66
76
 
67
- Write the product, feature by feature, as spec diffs - on your own, without asking.
77
+ 1. **The main slice.** The one thing the user said the software is for, on its happy path - the half-built main function a developer writes first and runs. Its concepts go into `***definitions***` in the same change, following `add-concept`; its functional spec follows `add-functional-spec`, placed where it fits.
78
+ 2. **One more slice at most** - the next thing the user described, also on its happy path. Stop there: two slices beyond the first spec. What the user says once they have tried the first ones decides the rest, and slices written far ahead are slices to rework.
79
+ 3. **Write each with `write_spec_diff`**, one after another - never wait for a build. Never change a `.plain` file in this step by any other means. Correct a change you find wrong once written with a diff and `fixes_earlier`, never by editing the file.
68
80
 
69
- 1. **Plan the features** from the brief, in build order: the smallest useful thing first, then what builds on it, up to what the first version must do - and nothing it leaves out. Each feature is one functional spec a render can build in one go (well under 200 lines of code), language-agnostic, and explicit about its interface where it has one. A feature too big for that is two.
70
- 2. **The description first.** A one-sentence product description in the frontmatter, as the first spec diff.
71
- 3. **Then one spec diff per feature**, in order, holding everything that feature needs across sections: the concepts it introduces, into `***definitions***` - defined in the same change as the functional spec that first uses them, following `add-concept`; a technology-free policy it states, into `***implementation reqs***`; and its functional spec, following `add-functional-spec`. Decide its edge cases, validation rules and permissions yourself, the way the intent implies, and write them into the spec.
72
- 4. **Write each with `write_spec_diff`** - a git diff of the `.plain` file(s): `diff --git a/<file> b/<file>`, `--- a/<file>`, `+++ b/<file>`, then the hunks with a few lines of context, paths from the project root. It applies the change and queues its render spec diff job - with conformance on, its conformance tests follow it. Go straight on to the next feature - never wait for a build. Never change a `.plain` file in this step by any other means.
81
+ Write no validation, no edge cases and no hardening in this step: they come later, as changes to these specs, once the user has tried the slices.
73
82
 
74
- The step is done only once every feature you planned is written, one spec diff each. Never stop part-way to ask whether to go on, or which feature comes next: nobody answers in this step, and the skill ends when your turn does - so a question here leaves the product unwritten.
83
+ The step is done once the slices are written - or at once, when the user described no feature. Never stop part-way to ask whether to go on: nobody answers in this step, and the skill ends when your turn does.
75
84
 
76
- Correct a change you find wrong once written with a diff and `fixes_earlier`, never by editing the file.
85
+ End with the handover, in a few short lines, ending on no question:
77
86
 
78
- End with the handover, in a few lines: the features in build order, the jobs they were queued as, that conformance tests are off unless they were asked for (turning them on later is one line in `config.turri.yaml`, `conformance-tests: true`, with the test reqs and the script added in the conversation), and what the user can do now - try each feature as its build lands (ask to try it, and the chat deploys it), and ask for any change in the conversation. A feature added, changed or dropped is one spec diff, and what is left to build is worked out again from the spec.
87
+ - what is being built now - the first spec, then each slice - and that each can be tried as it lands: when a pulse lands, the conversation releases it and says where to try it (open this URL, run this command);
88
+ - with no feature described: that the user says what it should do first - in their own words, one thing at a time - and each becomes a spec diff. Suggest no feature of your own;
89
+ - otherwise, the next slices you would write, in order - the rest of what the user described, on its happy path, then hardening what is there (validation, edge cases, errors) - and that the user says `go on` for the next one, or asks for anything else instead;
90
+ - that conformance tests are off unless they were asked for - one line in `config.turri.yaml`, `conformance-tests: true`, with the test reqs and the script added in the conversation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turri-dev/cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.8-next.91b957c",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {