@turri-dev/cli 0.1.4-next.5a94e68 → 0.1.4-next.8254fbc

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 (82) hide show
  1. package/.pi/themes/turri-dark.json +67 -66
  2. package/.pi/themes/turri-light.json +71 -73
  3. package/README.md +40 -128
  4. package/assets/jellyfish/dark-00.png +0 -0
  5. package/assets/jellyfish/dark-01.png +0 -0
  6. package/assets/jellyfish/dark-02.png +0 -0
  7. package/assets/jellyfish/dark-03.png +0 -0
  8. package/assets/jellyfish/dark-04.png +0 -0
  9. package/assets/jellyfish/dark-05.png +0 -0
  10. package/assets/jellyfish/dark-06.png +0 -0
  11. package/assets/jellyfish/dark-07.png +0 -0
  12. package/assets/jellyfish/dark-08.png +0 -0
  13. package/assets/jellyfish/dark-09.png +0 -0
  14. package/assets/jellyfish/dark-10.png +0 -0
  15. package/assets/jellyfish/dark-11.png +0 -0
  16. package/assets/jellyfish/dark-12.png +0 -0
  17. package/assets/jellyfish/dark-13.png +0 -0
  18. package/assets/jellyfish/dark-14.png +0 -0
  19. package/assets/jellyfish/light-00.png +0 -0
  20. package/assets/jellyfish/light-01.png +0 -0
  21. package/assets/jellyfish/light-02.png +0 -0
  22. package/assets/jellyfish/light-03.png +0 -0
  23. package/assets/jellyfish/light-04.png +0 -0
  24. package/assets/jellyfish/light-05.png +0 -0
  25. package/assets/jellyfish/light-06.png +0 -0
  26. package/assets/jellyfish/light-07.png +0 -0
  27. package/assets/jellyfish/light-08.png +0 -0
  28. package/assets/jellyfish/light-09.png +0 -0
  29. package/assets/jellyfish/light-10.png +0 -0
  30. package/assets/jellyfish/light-11.png +0 -0
  31. package/assets/jellyfish/light-12.png +0 -0
  32. package/assets/jellyfish/light-13.png +0 -0
  33. package/assets/jellyfish/light-14.png +0 -0
  34. package/dist/brand.js +7 -7
  35. package/dist/cultivate-cli.js +16 -23
  36. package/dist/extension.js +15 -21
  37. package/dist/loop-cli.js +8 -8
  38. package/dist/module-report.js +5 -4
  39. package/dist/regenerate/plain-palette.js +51 -36
  40. package/dist/regenerate/side-panel.js +1 -1
  41. package/dist/regenerate/spec-map-view.js +9 -5
  42. package/dist/release-cli.js +3 -8
  43. package/dist/validate-cli.js +3 -8
  44. package/docs/README.md +5 -12
  45. package/docs/authoring-plain.md +37 -119
  46. package/docs/config.md +50 -176
  47. package/docs/deploy.md +21 -80
  48. package/docs/development.md +13 -41
  49. package/docs/headless.md +30 -136
  50. package/docs/images/how-turri-works.svg +29 -31
  51. package/docs/images/turri-banner.png +0 -0
  52. package/docs/installation.md +13 -40
  53. package/docs/parser.md +15 -43
  54. package/docs/regenerating.md +231 -964
  55. package/docs/sandbox.md +38 -152
  56. package/docs/skills-and-gates.md +50 -173
  57. package/docs/theming.md +45 -46
  58. package/docs/using.md +66 -356
  59. package/genome/rules/bullet-continuation.md +5 -13
  60. package/genome/rules/concise-specs-examples.md +2 -4
  61. package/genome/rules/concise-specs-integration-examples.md +2 -6
  62. package/genome/rules/concise-specs.md +1 -2
  63. package/genome/rules/func-specs.md +1 -0
  64. package/genome/rules/integration-embedded-testing.md +1 -4
  65. package/genome/rules/integrations.md +1 -2
  66. package/genome/rules/project-model.md +14 -35
  67. package/genome/rules/stdlib.md +14 -49
  68. package/genome/rules/turri-regeneration.md +48 -0
  69. package/genome/skills/add-implementation-requirement/SKILL.md +1 -2
  70. package/genome/skills/analyze-if-func-spec-too-complex/SKILL.md +3 -8
  71. package/genome/skills/brood/SKILL.md +37 -127
  72. package/genome/skills/brood/references/intent.md +4 -12
  73. package/genome/skills/brood/references/product.md +24 -76
  74. package/genome/skills/brood/references/stack.md +7 -29
  75. package/genome/skills/brood/references/testing.md +11 -42
  76. package/genome/skills/bud/SKILL.md +32 -109
  77. package/genome/skills/bud/references/intent.md +4 -11
  78. package/genome/skills/implement-conformance-testing-script/SKILL.md +3 -6
  79. package/genome/skills/implement-unit-testing-script/SKILL.md +1 -2
  80. package/genome/skills/mature/SKILL.md +21 -69
  81. package/genome/skills/spawn/SKILL.md +28 -113
  82. package/package.json +1 -1
package/docs/using.md CHANGED
@@ -7,19 +7,7 @@ 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
11
- (`turri -c`, `turri --harness-model <m>`). It opens with turri's own
12
- banner - the jellyfish it is named after, swimming until the conversation fills the screen: a picture in a
13
- terminal that shows images (Kitty, Ghostty, WezTerm, Warp, iTerm2), and drawn in text in any other, tmux
14
- included - swimming a stroke a loop, its tentacles following its bell, frames `scripts/jellyfish-frames.mjs`
15
- writes -
16
- turri's version (and, run from a clone, the commit it is on, and whether the clone has changes), where commands
17
- will run, the rules and skills loaded - rather than pi's startup header and resource list; `turri --verbose` shows
18
- those too. pi's "Update Available" notice is left out - turri's pi is a pinned dependency `pi update` never
19
- touches - and the terminal's tab reads `🪼 turri - <folder>`, not pi's `π`. Talk to it: ask it to start a
20
- project, add a feature, render a module, fix a spec. It decides which skill or tool applies - but
21
- not *how* a skill runs: `cultivate` hands the work to the gated runner, which owns the steps, the
22
- 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, swimming until the conversation fills the screen: a picture in a terminal that shows images (Kitty, Ghostty, WezTerm, Warp, iTerm2), and drawn in text in any other, tmux included - swimming a stroke a loop, its tentacles following its bell, frames `scripts/jellyfish-frames.mjs` writes - turri's version (and, run from a clone, the commit it is on, and whether the clone has changes), where commands will run, the rules and skills loaded - 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)).
23
11
 
24
12
  The skills that build from scratch:
25
13
 
@@ -29,22 +17,11 @@ The skills that build from scratch:
29
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 |
30
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 |
31
19
 
32
- Peeking is safe while a question is open - a skill's or the chat's: `ctrl+h` opens the side panel over the question,
33
- which waits under it as it was - the panel says `your question is waiting`, and `ctrl+h` or `esc` takes you back to
34
- answer it. (The question has the keys, so turri catches `ctrl+h` itself while one is open.) The dialog holds the question
35
- alone - no hint and no invitation; the `ctrl+h` under the job panel breathes until it is first pressed.
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
21
 
37
- While a skill runs, a line above the input shows its phases, every one by name - those done ticked, the one it is in
38
- marked, the rest to come - and where it is: the skill's name at the left edge, `phase 2 of 4` at the right, and its
39
- phases centred between them, `✓ intent ━━━━ ⠋ stack ──── ○ testing ──── ○ product`. Under it, dimmed, the phase it is in and what
40
- it does: `stack - the language, frameworks, storage and architecture`. The phases are the skill's own steps, read from its `SKILL.md`. A skill of one phase, or none, has nothing to be partway through: its line is the spinner and its name alone,
41
- `⠹ add-test-requirement`.
22
+ While a skill runs, a line above the input shows its phases, every one by name - those done ticked, the one it is in marked, the rest to come - and where it is: the skill's name at the left edge, `phase 2 of 4` at the right, and its phases centred between them, `✓ intent ━━━━ ⠋ stack ──── ○ testing ──── ○ product`. Under it, dimmed, the phase it is in and what it does: `stack - the language, frameworks, storage and architecture`. The phases are the skill's own steps, read from its `SKILL.md`. A skill of one phase, or none, has nothing to be partway through: its line is the spinner and its name alone, `⠹ add-test-requirement`.
42
23
 
43
- `genome/skills/` holds the rest: adding a feature, a concept, a requirement, a resource; splitting a spec
44
- that is too big; resolving conflicts; checking the environment - see
45
- [authoring \*\*\*plain](authoring-plain.md#the-skills). A skill run that is interrupted can be resumed
46
- where it stopped. A project can have skills of its own, in `.turri/skills/` or `.agents/skills/` - see
47
- [skills and gates](skills-and-gates.md#a-projects-own-skills).
24
+ `genome/skills/` holds the rest: adding a feature, a concept, a requirement, a resource; splitting a spec that is too big; resolving conflicts; checking the environment - see [authoring \*\*\*plain](authoring-plain.md#the-skills). A skill run that is interrupted can be resumed where it stopped. A project can have skills of its own, in `.turri/skills/` or `.agents/skills/` - see [skills and gates](skills-and-gates.md#a-projects-own-skills).
48
25
 
49
26
  ## The tools
50
27
 
@@ -68,85 +45,22 @@ where it stopped. A project can have skills of its own, in `.turri/skills/` or `
68
45
 
69
46
  What each render does, in order, is in [regenerating the code](regenerating.md).
70
47
 
71
- The conversation knows the ***plain standard library from its first turn: the stdlib rule in its
72
- system prompt lists every stack and where the templates are, so "build this as a Flask backend"
73
- becomes an import of `stdlib/backend/python-flask`, not a stack written out by hand. The banner at
74
- start says how many stacks there are, and **`/stdlib`** lists them, each with what it is (see
75
- [the standard library](authoring-plain.md#the-standard-library)).
48
+ The conversation knows the ***plain standard library from its first turn: the stdlib rule in its system prompt lists every stack and where the templates are, so "build this as a Flask backend" becomes an import of `stdlib/backend/python-flask`, not a stack written out by hand. The banner at start says how many stacks there are, and **`/stdlib`** lists them, each with what it is (see [the standard library](authoring-plain.md#the-standard-library)).
76
49
 
77
- The agent does this work with these tools, never by running turri's command line - or
78
- another pi - through its shell: that would be a separate, headless run outside regen
79
- and `/halt`. The harness refuses such a command unless your message asks for the
80
- command line ("run it headless", "use the CLI", or the command itself). pi configuring itself -
81
- `pi install`, `update`, `list`, `config`, `auth`, its settings - is not affected.
50
+ The agent does this work with these tools, never by running turri's command line - or another pi - through its shell: that would be a separate, headless run outside regen and `/halt`. The harness refuses such a command unless your message asks for the command line ("run it headless", "use the CLI", or the command itself). pi configuring itself - `pi install`, `update`, `list`, `config`, `auth`, its settings - is not affected.
82
51
 
83
52
  ## Pulses
84
53
 
85
- A pulse is one unit of work regenerating the code. It was called a job, and still is where a name is kept -
86
- `job_id`, `parallel-jobs`, `allow-to-stop-jobs`, `.turri/jobs/` - and in a project's own files written before:
87
- the chat is told the two are the same, so an `AGENTS.md` or a skill that says "job" needs no change.
88
-
89
- A render takes minutes, so in the TUI every render tool starts the work as a pulse and
90
- returns straight away. The conversation carries on; pulses on the same module - or on modules of one
91
- `requires` chain - queue behind each other, in the order they were asked for, from the first pulse on:
92
- one queued while the spec is only a scaffold, with no functional specs yet, or while it does not
93
- parse, still holds its module, so nothing on the module runs beside it. Pulses on modules
94
- that share nothing run side by side, each with its own progress panel - two
95
- modules or ten. How many run at once is capped by what the machine has room for: past
96
- `parallel-jobs` (see [the project config](config.md#how-many-jobs-at-once)), a pulse whose turn has
97
- come waits for a free slot, and says so.
98
-
99
- - **The panel** above the input, while something runs, shows on top what finished - a line a module, its
100
- pulses oldest first, each with its mark (green, red or amber, as in the side panel), number and kind - what
101
- it regenerated is in the side panel - `cognio … 2 earlier · ✓ 3 regenerate · ✓ 4 conformance`, the newest that fit the width -
102
- then a rule, and under it each running pulse - `cognio · regenerate pulse 5`, `cognio · conformance pulse 6` - its time and cost, and what its agents are doing. A module whose work is being planned into pulses shows at once,
103
- before any pulse runs - `shorty · planning the pulses · 12s` - the planner is an agent, and takes a while; a
104
- `/regenerate` says it began the moment it is sent. Pulses are numbered within their module, as regen numbers
105
- them. `ctrl+o` expands the agents' trace alone; what finished stays a line a module. The line of keys under
106
- it - `ctrl+o to expand the trace · ctrl+h to peek at regen` - has each key breathing, fully there to a little
107
- faint and back, until it is first pressed: once `ctrl+o` has opened the trace, or the side panel has been opened,
108
- that key is still for the rest of the session and the other breathes on.
109
- What waits is not in it, and it shows no spec diff - the side panel has both. With nothing running it
110
- is gone.
111
- - **A pulse's change** is what its agent works from, not a text diff of the module's file: the items
112
- `<spec change>` gives the agent - only what the pulse's functional specs use, an import's items as
113
- well as the module's own, a code pulse's without the test reqs - each in the file it is written in,
114
- under its section, in the file's order (`change-view.ts`).
115
- - **A spec diff**, in the side panel, reads as an editor shows a diff: its \*\*\*plain highlighted
116
- as [plyn](https://github.com/plainlang/plyn) highlights it - section headers, concepts, names in
117
- backticks, text in quotes, links, the front matter - each added line filled green and each removed one
118
- red, the text on top, the fill the width of the panel ([colours](theming.md#spec-diffs)). It is shown
119
- file by file, each file's lines together under its name, with what it adds and takes out - the module
120
- being rendered first, the rest by name, and none the diff does not change. Each line has its number in
121
- that file: a spec diff is of the spec as read, with what it imports laid in, so a line is placed in the
122
- file it is written in - its links read as the parser renders them - and a removed line, in no file now,
123
- goes with the change it is part of and has no number. A line is never put in a file on a guess: one
124
- that cannot be placed is listed last, under "not found in the spec's files". Where lines of a file are not in
125
- the diff, `↕ 28 lines` says how many, as GitHub does - `↑` above the first - and names the section
126
- the lines under it are in when it is another than the one above, `↕ 28 lines · ***functional specs***`,
127
- as GitHub names a hunk's function: each section is named once.
128
- - **The side panel** (`ctrl+h`, as it was left - but on the pulse that last failed, stopped or did not pass, when one has
129
- since it was last opened: the live panel that showed it is gone with the last pulse, and its announcement in the chat
130
- says `ctrl+h shows this pulse`; **`/pulses`** on the pulses; not `ctrl+j`, which a terminal without the Kitty
131
- keyboard protocol sends as a line feed, the same as `shift+enter`, and which a dialog takes for
132
- `enter`; both stay pi's new-line keys. `ctrl+h` is the byte old terminals sent for backspace; a
133
- terminal set to send `^H` for its Backspace key would open the panel on it) takes the whole screen - the panel or the chat, one at a time -
134
- or, `s`, sits beside the chat: the chat on the left, the panel in the right half of the screen, and `s` again
135
- over the whole screen. It opens as it was last left, for the conversation; a terminal under 100 columns has
136
- no room for both and shows the panel over the whole screen.
137
- It opens on **regen**: the spec itself, in full, with how much of it the code has been regenerated from drawn
138
- onto it.
139
-
140
- Every item of the spec - a definition, a req, a functional spec with its sub-bullets and acceptance tests,
141
- what turri plans and diffs by - is a row in the file's order, its \*\*\*plain highlighted as plyn highlights it
142
- (as a spec diff is) and wrapped to the width, never cut short. The map has two columns, each headed on the
143
- line over it with a line of space under it: **status**, a mark a row - its rung on a ladder every item climbs - and the module's file, its
144
- spec. The top of the panel is where it is seen first: the top line, the module tabs, and the keys - each view's,
145
- `d talk it through in the chat` first when the module needs you - wrapped, never cut short, a line of space between
146
- the top line and the keys; then straight under them a rule, a line of space, and the columns' headings. The pulses view has its
147
- keys at the top too, and a line of space under its rule. The legend is a box of its own in the upper right corner, over what is under it, a line a
148
- mark, up the ladder. It names every rung, whatever the page shows - to take out only where something is - and a
149
- panel under 60 columns wide has none.
54
+ A pulse is one unit of work regenerating the code. It was called a job, and still is where a name is kept - `job_id`, `parallel-jobs`, `allow-to-stop-jobs`, `.turri/jobs/` - and in a project's own files written before: the chat is told the two are the same, so an `AGENTS.md` or a skill that says "job" needs no change.
55
+
56
+ A render takes minutes, so in the TUI every render tool starts the work as a pulse and returns straight away. The conversation carries on; pulses on the same module - or on modules of one `requires` chain - queue behind each other, in the order they were asked for, from the first pulse on: one queued while the spec is only a scaffold, with no functional specs yet, or while it does not parse, still holds its module, so nothing on the module runs beside it. Pulses on modules that share nothing run side by side, each with its own progress panel - two modules or ten. How many run at once is capped by what the machine has room for: past `parallel-jobs` (see [the project config](config.md#how-many-jobs-at-once)), a pulse whose turn has come waits for a free slot, and says so.
57
+
58
+ - **The panel** above the input, while something runs, shows on top what finished - a line a module, its pulses oldest first, each with its mark (green, red or amber, as in the side panel), number and kind - what it regenerated is in the side panel - `cognio … 2 earlier · ✓ 3 regenerate · ✓ 4 conformance`, the newest that fit the width - then a rule, and under it each running pulse - `cognio · regenerate pulse 5`, `cognio · conformance pulse 6` - its time and cost, and what its agents are doing. A module whose work is being planned into pulses shows at once, before any pulse runs - `shorty · planning the pulses · 12s` - the planner is an agent, and takes a while; a `/regenerate` says it began the moment it is sent. Pulses are numbered within their module, as regen numbers them. `ctrl+o` expands the agents' trace alone; what finished stays a line a module. The line of keys under it - `ctrl+o to expand the trace · ctrl+h to peek at regen` - has each key breathing, fully there to a little faint and back, until it is first pressed: once `ctrl+o` has opened the trace, or the side panel has been opened, that key is still for the rest of the session and the other breathes on. What waits is not in it, and it shows no spec diff - the side panel has both. With nothing running it is gone.
59
+ - **A pulse's change** is what its agent works from, not a text diff of the module's file: the items `<spec change>` gives the agent - only what the pulse's functional specs use, an import's items as well as the module's own, a code pulse's without the test reqs - each in the file it is written in, under its section, in the file's order (`change-view.ts`).
60
+ - **A spec diff**, in the side panel, reads as an editor shows a diff: its \*\*\*plain highlighted as [plyn](https://github.com/plainlang/plyn) highlights it - section headers, concepts, names in backticks, text in quotes, links, the front matter - each added line filled green and each removed one red, the text on top, the fill the width of the panel ([colours](theming.md#spec-diffs)). It is shown file by file, each file's lines together under its name, with what it adds and takes out - the module being rendered first, the rest by name, and none the diff does not change. Each line has its number in that file: a spec diff is of the spec as read, with what it imports laid in, so a line is placed in the file it is written in - its links read as the parser renders them - and a removed line, in no file now, goes with the change it is part of and has no number. A line is never put in a file on a guess: one that cannot be placed is listed last, under "not found in the spec's files". Where lines of a file are not in the diff, `↕ 28 lines` says how many, as GitHub does - `↑` above the first - and names the section the lines under it are in when it is another than the one above, `↕ 28 lines · ***functional specs***`, as GitHub names a hunk's function: each section is named once.
61
+ - **The side panel** (`ctrl+h`, as it was left - but on the pulse that last failed, stopped or did not pass, when one has since it was last opened: the live panel that showed it is gone with the last pulse, and its announcement in the chat says `ctrl+h shows this pulse`; **`/pulses`** on the pulses; not `ctrl+j`, which a terminal without the Kitty keyboard protocol sends as a line feed, the same as `shift+enter`, and which a dialog takes for `enter`; both stay pi's new-line keys. `ctrl+h` is the byte old terminals sent for backspace; a terminal set to send `^H` for its Backspace key would open the panel on it) takes the whole screen - the panel or the chat, one at a time - or, `s`, sits beside the chat: the chat on the left, the panel in the right half of the screen, and `s` again over the whole screen. It opens as it was last left, for the conversation; a terminal under 100 columns has no room for both and shows the panel over the whole screen. It opens on **regen**: the spec itself, in full, with how much of it the code has been regenerated from drawn onto it.
62
+
63
+ Every item of the spec - a definition, a req, a functional spec with its sub-bullets and acceptance tests, what turri plans and diffs by - is a row in the file's order, its \*\*\*plain highlighted as plyn highlights it (as a spec diff is) and wrapped to the width, never cut short. The map has two columns, each headed on the line over it with a line of space under it: **status**, a mark a row - its rung on a ladder every item climbs - and the module's file, its spec. The top of the panel is where it is seen first: the top line, the module tabs, and the keys - each view's, `d talk it through in the chat` first when the module needs you - wrapped, never cut short, a line of space between the top line and the keys; then straight under them a rule, a line of space, and the columns' headings. The pulses view has its keys at the top too, and a line of space under its rule. The legend is a box of its own in the upper right corner, over what is under it, a line a mark, up the ladder. It names every rung, whatever the page shows - to take out only where something is - and a panel under 60 columns wide has none.
150
64
 
151
65
  | Mark | Legend | Means |
152
66
  | --- | --- | --- |
@@ -158,183 +72,43 @@ come waits for a free slot, and says so.
158
72
  | `!` | needs you | in the pulse that did not land and halted the module, or the planner found no plan |
159
73
  | `−` | to take out | taken out of the spec, still in the code - a struck-through red ghost, with the code record's text, until the pulse that takes it out lands |
160
74
 
161
- `◇` and `◆` are both green, and mean the same whatever `conformance-tests:` says: a functional spec regenerated
162
- and not conformed is `◇` with its conformance tests on, off or not chosen, so changing the setting changes no mark.
163
- Tests written for an earlier text leave it at `◇`. Definitions and reqs are never conformed: `◇` is as far as they go.
164
- Test reqs are shown only where conformance tests are on - `conformance-tests:` is not `false`, or `conform` turned
165
- them on this session. A test req is the conformance tests', never built into the code: `◆` once they follow it
166
- as it reads now, the green `⠋` while a conformance pulse writes them for it, `○` until then - and no mark where no
167
- conformance test is written at all. No pulse numbers are drawn in the gutter - they move whenever the plan is
168
- made again; `p` on an item goes to the pulse that brings it.
169
-
170
- **Needs you.** The top line ends `! needs you`, in red, and under the first `!` of the module is what for, and
171
- how: `needs you - pulse 3 didn't land - its unit tests never passed · d to talk it through in the chat`. `d` closes
172
- the panel and asks the chat, in your words, what went wrong and what to do about it, with turri's reason for
173
- the halt; the chat works it out with you - a diagnosis, a change to the spec, the machine set up - and
174
- regenerates. Pulses are numbered as they start in a module, from 1 each session.
175
-
176
- A changed item shows what changed in it: its first line word by word - what is gone struck through in red,
177
- what is new in green, what is kept highlighted as it reads now - and, under it, only the sub-bullets that changed. A spec never built that is taken
178
- out is simply gone. The top line has a strip of the module's functional specs - built, regenerating, planned,
179
- waiting - and how many are built, then what is happening: `pulse 3 of 8 regenerating`, or why nothing is -
180
- `not asked to build - regenerate plans it` (turri was just opened, or nothing has asked for the module: the
181
- plan lives in memory and is made again on the next regeneration), `planning`, `waits for backend`, or
182
- `! needs you`. `enter` opens an item: all of
183
- its text against the code's, and its acceptance tests. Where it stands is beside its mark, and is not said again
184
- under it.
185
-
186
- One module is shown at a time, with a tab for each module of the chain on the line under the top line, in
187
- the chain's order - the module it is built on to the left: `d365_version_api [d365_http_client] d365_utils
188
- 12 ›`. A tab regenerating spins, one stuck says `!`; what does not fit is counted at either end. `←` `→` go from
189
- one tab to the next. The module shown is the one in focus - the one regenerating now, else the one asked for,
190
- else the first - until you pick another tab; it goes back to following once another module is in focus, or
191
- the one in focus starts regenerating. Under the module's own text is what it imports, under **imported**, a
192
- folded block a file, `▸ from stdlib/backend/python-fastapi · 7 reqs · all built`, closed until opened. The
193
- modules it requires are tabs of their own: a chain of many modules is never drawn nested, one in the next.
194
- A map longer than the screen has a minimap down its right edge, a cell a slice in the colour of
195
- its most pressing mark, the slice shown solid. The map is read from the files - the code record, the
196
- `.plain` files, the tests record - so it is right the moment turri opens a project, before anything runs;
197
- the work loop's plan adds the pulses on top. It maps the files asked to build this conversation, else
198
- `module:` in `config.turri.yaml`, else the `.plain` files of the folder that no other one there imports or
199
- requires - the folder's files looked at again only once one of them, or its config, changes. `↑` `↓` move
200
- row by row, `enter` or `space` open and close an item or an import block - a functional spec opens to its
201
- sub-bullets and its `***acceptance tests***`, nested under it as the spec has them - `←` `→` go to the next module's
202
- tab, `o` and `c` open or close everything shown, `pgup` `pgdn` and the
203
- wheel scroll, `g`/`G` go to the top and the bottom.
204
-
205
- `p` goes to the **pulses** - and back - onto the pulse that regenerates the item under the cursor, and
206
- 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
207
- 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
208
- finished one's mark green when it passed, red when it failed or did not pass, amber when it was stopped.
209
- Opened, a running one shows what it is doing; a queued one, what it waits for; a finished one, its agents
210
- and what each spent, and whether it did not pass. Under it is a row
211
- for each file its spec diff changes - the file of the module being rendered first and open, the rest by
212
- name and closed - each opening onto that file's lines. A file with nothing added or taken out is not
213
- listed. `↑` `↓` move, `enter` or `space` open and close what is under the cursor, `→` `←` open and close
214
- (`←` on a closed pulse goes to its section, on a closed file to its pulse), `o` and `c` open or close every
215
- pulse of the section - or, on a file, every file of its pulse - `pgup` `pgdn` and the wheel scroll, `g`/`G`
216
- go to the top and the bottom. The cursor stays on its row when the pulse under it moves on; a pulse opened
217
- closes when it moves to another section. What is open is kept while the panel is closed. What the agents
218
- said and did is not shown - it is in each pulse's log (see [Agent logs](#agent-logs)).
219
-
220
- `ctrl+h` again, or `esc`, closes it and goes back to the chat. Beside the chat, a click decides which side has
221
- the keys - the chat or the panel, the one clicked, or the one `⌥⌘←` / `⌥⌘→` points at (on a
222
- terminal that passes ⌘ on, over the Kitty keyboard protocol - Ghostty, kitty, WezTerm, iTerm2; not Apple's Terminal);
223
- the other is drawn faint - and `esc` gives the chat the keys too, the panel staying and
224
- following the pulses; `ctrl+h` gives the panel the keys again, and from the panel closes it. (pi's regular screen,
225
- `--tui-mode regular`, reads no mouse: there it is the keys alone.)
226
- While the panel has the keys, every key is the panel's,
227
- whatever else happens: a question the chat model asks in the background (`ask_user`) waits in the chat,
228
- unanswered - an `enter` in the panel never answers it - and the panel's top line says "the chat is waiting
229
- for your answer". Back in the chat, the question is there, with the keys.
230
- - `turri` runs pi in fullscreen mode, so the conversation stays where you scroll it while
231
- the pulses redraw (PgUp/PgDn, the wheel); `--tui-mode regular` goes back to the terminal's own
232
- scrollback.
233
- - **`/turri-config`** changes a setting of the project's `config.turri.yaml` - the models, review, conformance tests, any
234
- key - and says when it takes effect: now, at your next message, or at the next pulse; never only after a restart.
235
- See [changing it from the chat](config.md#changing-it-from-the-chat).
236
- - **`/stack`** chooses the stack everything is built with from then on, in a project whose parts are on different
237
- stacks: a list of the project's stacks, or `/stack backend`, `/stack none`. The stack's `config.turri.<stack>.yaml`
238
- is laid over `config.turri.yaml` - its testing scripts, toolchains, models - for the session; a pulse already
239
- running keeps the stack it started with. The chat model switches it too when you ask. See
240
- [stacks](config.md#stacks).
241
- - **`/regenerate [module | file.plain] [functionality ...] [from scratch [whole chain]] [how to cut the work]`** regenerates a module from its spec as it is now, as
242
- the `regenerate` tool does: what is left to regenerate is planned into pulses - one functional spec at a time, a few
243
- together or the whole module in one, as the planner judges - and the first starts. Words after the module are
244
- guidance for that plan (`/regenerate app models first`). A module's name typed with spaces for its underscores is
245
- that module - `/regenerate d365_function executor` is `d365_function_executor`. With no module named: the one `module:` in
246
- `config.turri.yaml` names, else the folder's top modules, to pick from. Asked for from scratch - `from scratch`,
247
- `start over`, `delete the module` - it asks first, then deletes the module's code and conformance tests in every
248
- codebase where they live, committed so `/lineage` keeps them, and regenerates the whole module from its spec,
249
- built though nothing in it changed: `/regenerate shorty from scratch`. The modules below it keep their code, and
250
- the module starts again from a copy of the code below it. Asked for its chain too - `/regenerate shorty from scratch,
251
- the whole chain` - the code of every module of its requires chain is deleted, the base's included, and the whole
252
- chain is regenerated from the bottom: what to do after modules were split, merged or moved, when the code below was
253
- laid out for modules that are no more. The chat's `regenerate` does the same with `from_scratch: "module"` or
254
- `"chain"`, when you ask for it; `turri regenerate --from-scratch` or `--from-scratch-chain` on the command line, not
255
- with `--dry-run`.
256
- Functionalities named after the module - `/regenerate shorty 3 5` - are regenerated though their spec did not
257
- change, on the model chosen for functionalities: as `turri regenerate shorty.plain 3 5` does, and the chat's
258
- `regenerate` with `functionalities`.
259
- - **`/halt <id>`** halts a pulse - a queued one never starts - **`/halt <module>`** (or a planned row's id) halts a
260
- module's planned pulses until you ask for it again, a spec change not starting it, and **`/halt activated <name>`**
261
- halts a server `activate` started; it lists all three when no id is given.
262
- - **What these commands show you, the chat knows.** What `/regenerate` and `/halt activated` tell you - a spec that
263
- does not parse, the pulses planned, a server halted - stays in the chat under the command, and since a slash command
264
- runs outside the conversation, it is put in the conversation as well: say "fix it" next and turri knows what you are
265
- looking at. A halted pulse reaches it as every pulse's end does.
266
- - **Nothing is queued.** What is left to build is worked out from what each codebase is built from
267
- and the spec as it is now - again whenever a pulse ends or the spec changes - and the first pulse of
268
- it runs; see [a whole module](regenerating.md#a-whole-module). Changes that overlap never pile up: the next pulse
269
- builds the spec as it is. The pulses planned after the one running are listed behind it, as queued,
270
- and so is each module waiting for the one it is built on - "waits for base" - until it can be planned.
271
- A change inside what the running pulse regenerates - a spec it regenerates reworded or given a sub-bullet, a definition or req it is given, a file they link - steers it: its agent is told, and it lands the spec as it is now there, twice a pulse at most. Otherwise a pulse building something the spec no longer wants is stopped and rolled back - unless `allow-to-stop-jobs: false` in `config.turri.yaml`, which has it land first and the change regenerated on top. To drop something, take it out of the spec - one spec diff. Stopping a pulse leaves its change
272
- in the spec: the codebase waits until the spec changes or it is asked for again.
273
- - **A change to a module below** is made in the codebase at the tip of the chain, where its code
274
- lives; the codebase below is left as it was, and is brought up to its own spec only when a new
275
- module is to start from it. Specs moved into a module the code was not built on stop the codebase:
276
- no change to its code brings that module in, so it has to be started over - its code and
277
- conformance tests taken out, kept in its history, and built again from the bottom of the chain.
278
- That is never done unasked: the chat asks you, saying why, and regenerates it from scratch once you agree;
279
- on the command line `turri regenerate` asks at the terminal, and `--start-over` agrees in advance.
280
- - **Conformance tests are a track of their own.** A code pulse lands once its unit tests pass and are
281
- reviewed. Then, before the next one builds on it, a conformance pulse writes and runs the tests of what it
282
- built - from the test reqs and acceptance tests - with the whole suite the module inherits, and, where one
283
- fails, fixes the test or the code, whichever is wrong; what they are written for is recorded in
284
- `tests/.turri.json`. With `conformance-tests: false` none is written until you ask -
285
- `conform`, for a module or some of its functional specs. A conformance pulse that does not pass
286
- is undone whole and halts the conformance tests alone: the code goes on being built.
287
- - **A pulse that fails** - its work errors, or it does not pass - is run once more. Failing again, it
288
- stops, and so does every pulse queued behind it on the same module, without running - the other
289
- modules' pulses go on. The harness then works out why: an
290
- agent that can read the project's specs, code, tests, testing scripts and logs, and turri's
291
- own source, skills and rules, says what happened, why, whether the fix belongs in the spec, the
292
- environment, the code or turri itself, and exactly what to do.
293
- - **When a pulse finishes** the transcript shows its line - `✓`, `✗` or `■`, its module, kind and number,
294
- how long it took and what it cost, never what it regenerated -
295
- `✓ shorty · conformance pulse 4 finished after 3m 47s · 488.6k tok · $0.02` - and the chat, which
296
- gets its whole report, reacts then and there, whatever else is running or queued, without waiting
297
- for you to speak: at once when it is idle, else as soon as the reply it is in ends. It does what the
298
- project's guidance says to do when a pulse finishes - release what was built, say - or tells you
299
- what finished and what it means. Ask to try it ("let me try it") and the chat releases what is
300
- built to `dist/<module>` and starts it on your machine, even while other pulses run. See [deploy](deploy.md). The chat reacts to it then and there,
301
- whatever else is running or queued, without waiting for you to speak - at once when it is idle, else
302
- as soon as the reply it is in ends: it does what the project's guidance says to do when a pulse
303
- finishes (release what was built, say), or tells you in a line or two what finished.
304
- - **When a pulse stops** - a gate still failing after 20 attempts - it says where it stopped, why in
305
- plain words, and what to change in the spec - which section, and how.
306
- Running the same build again picks up from there.
307
-
308
- In `print`, `json` and `rpc` modes the process ends when the answer is written, so the tools wait
309
- for the work there instead. Pulses live in memory for the session; the work itself is on disk.
75
+ `◇` and `◆` are both green, and mean the same whatever `conformance-tests:` says: a functional spec regenerated and not conformed is `◇` with its conformance tests on, off or not chosen, so changing the setting changes no mark. Tests written for an earlier text leave it at `◇`. Definitions and reqs are never conformed: `◇` is as far as they go. Test reqs are shown only where conformance tests are on - `conformance-tests:` is not `false`, or `conform` turned them on this session. A test req is the conformance tests', never built into the code: `◆` once they follow it as it reads now, the green `⠋` while a conformance pulse writes them for it, `○` until then - and no mark where no conformance test is written at all. No pulse numbers are drawn in the gutter - they move whenever the plan is made again; `p` on an item goes to the pulse that brings it.
76
+
77
+ **Needs you.** The top line ends `! needs you`, in red, and under the first `!` of the module is what for, and how: `needs you - pulse 3 didn't land - its unit tests never passed · d to talk it through in the chat`. `d` closes the panel and asks the chat, in your words, what went wrong and what to do about it, with turri's reason for the halt; the chat works it out with you - a diagnosis, a change to the spec, the machine set up - and regenerates. Pulses are numbered as they start in a module, from 1 each session.
78
+
79
+ A changed item shows what changed in it: its first line word by word - what is gone struck through in red, what is new in green, what is kept highlighted as it reads now - and, under it, only the sub-bullets that changed. A spec never built that is taken out is simply gone. The top line has a strip of the module's functional specs - built, regenerating, planned, waiting - and how many are built, then what is happening: `pulse 3 of 8 regenerating`, or why nothing is - `not asked to build - regenerate plans it` (turri was just opened, or nothing has asked for the module: the plan lives in memory and is made again on the next regeneration), `planning`, `waits for backend`, or `! needs you`. `enter` opens an item: all of its text against the code's, and its acceptance tests. Where it stands is beside its mark, and is not said again under it.
80
+
81
+ 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
+ `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
+
85
+ `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
+ - `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.
87
+ - **`/turri-config`** changes a setting of the project's `config.turri.yaml` - the models, review, conformance tests, any key - and says when it takes effect: now, at your next message, or at the next pulse; never only after a restart. See [changing it from the chat](config.md#changing-it-from-the-chat).
88
+ - **`/stack`** chooses the stack everything is built with from then on, in a project whose parts are on different stacks: a list of the project's stacks, or `/stack backend`, `/stack none`. The stack's `config.turri.<stack>.yaml` is laid over `config.turri.yaml` - its testing scripts, toolchains, models - for the session; a pulse already running keeps the stack it started with. The chat model switches it too when you ask. See [stacks](config.md#stacks).
89
+ - **`/regenerate [module | file.plain] [functionality ...] [from scratch [whole chain]] [how to cut the work]`** regenerates a module from its spec as it is now, as the `regenerate` tool does: what is left to regenerate is planned into pulses - one functional spec at a time, a few together or the whole module in one, as the planner judges - and the first starts. Words after the module are guidance for that plan (`/regenerate app models first`). A module's name typed with spaces for its underscores is that module - `/regenerate d365_function executor` is `d365_function_executor`. With no module named: the one `module:` in `config.turri.yaml` names, else the folder's top modules, to pick from. Asked for from scratch - `from scratch`, `start over`, `delete the module` - it asks first, then deletes the module's code and conformance tests in every codebase where they live, committed so `/lineage` keeps them, and regenerates the whole module from its spec, built though nothing in it changed: `/regenerate shorty from scratch`. The modules below it keep their code, and the module starts again from a copy of the code below it. Asked for its chain too - `/regenerate shorty from scratch, the whole chain` - the code of every module of its requires chain is deleted, the base's included, and the whole chain is regenerated from the bottom: what to do after modules were split, merged or moved, when the code below was laid out for modules that are no more. The chat's `regenerate` does the same with `from_scratch: "module"` or `"chain"`, when you ask for it; `turri regenerate --from-scratch` or `--from-scratch-chain` on the command line, not with `--dry-run`. Functionalities named after the module - `/regenerate shorty 3 5` - are regenerated though their spec did not change, on the model chosen for functionalities: as `turri regenerate shorty.plain 3 5` does, and the chat's `regenerate` with `functionalities`.
90
+ - **`/halt <id>`** halts a pulse - a queued one never starts - **`/halt <module>`** (or a planned row's id) halts a module's planned pulses until you ask for it again, a spec change not starting it, and **`/halt activated <name>`** halts a server `activate` started; it lists all three when no id is given.
91
+ - **What these commands show you, the chat knows.** What `/regenerate` and `/halt activated` tell you - a spec that does not parse, the pulses planned, a server halted - stays in the chat under the command, and since a slash command runs outside the conversation, it is put in the conversation as well: say "fix it" next and turri knows what you are looking at. A halted pulse reaches it as every pulse's end does.
92
+ - **Nothing is queued.** What is left to build is worked out from what each codebase is built from and the spec as it is now - again whenever a pulse ends or the spec changes - and the first pulse of it runs; see [a whole module](regenerating.md#a-whole-module). Changes that overlap never pile up: the next pulse builds the spec as it is. The pulses planned after the one running are listed behind it, as queued, and so is each module waiting for the one it is built on - "waits for base" - until it can be planned. A change inside what the running pulse regenerates - a spec it regenerates reworded or given a sub-bullet, a definition or req it is given, a file they link - steers it: its agent is told, and it lands the spec as it is now there, twice a pulse at most. Otherwise a pulse building something the spec no longer wants is stopped and rolled back - unless `allow-to-stop-jobs: false` in `config.turri.yaml`, which has it land first and the change regenerated on top. To drop something, take it out of the spec - one spec diff. Stopping a pulse leaves its change in the spec: the codebase waits until the spec changes or it is asked for again.
93
+ - **A change to a module below** is made in the codebase at the tip of the chain, where its code lives; the codebase below is left as it was, and is brought up to its own spec only when a new module is to start from it. Specs moved into a module the code was not built on stop the codebase: no change to its code brings that module in, so it has to be started over - its code and conformance tests taken out, kept in its history, and built again from the bottom of the chain. That is never done unasked: the chat asks you, saying why, and regenerates it from scratch once you agree; on the command line `turri regenerate` asks at the terminal, and `--start-over` agrees in advance.
94
+ - **Conformance tests are a track of their own.** A code pulse lands once its unit tests pass and are reviewed. Then, before the next one builds on it, a conformance pulse writes and runs the tests of what it built - from the test reqs and acceptance tests - with the whole suite the module inherits, and, where one fails, fixes the test or the code, whichever is wrong; what they are written for is recorded in `tests/.turri.json`. With `conformance-tests: false` none is written until you ask - `conform`, for a module or some of its functional specs. A conformance pulse that does not pass is undone whole and halts the conformance tests alone: the code goes on being built.
95
+ - **A pulse that fails** - its work errors, or it does not pass - is run once more. Failing again, it stops, and so does every pulse queued behind it on the same module, without running - the other modules' pulses go on. The harness then works out why: an agent that can read the project's specs, code, tests, testing scripts and logs, and turri's own source, skills and rules, says what happened, why, whether the fix belongs in the spec, the environment, the code or turri itself, and exactly what to do.
96
+ - **When a pulse finishes** the transcript shows its line - `✓`, `✗` or `■`, its module, kind and number, how long it took and what it cost, never what it regenerated - `✓ shorty · conformance pulse 4 finished after 3m 47s · 488.6k tok · $0.02` - and the chat, which gets its whole report, reacts then and there, whatever else is running or queued, without waiting for you to speak: at once when it is idle, else as soon as the reply it is in ends. It does what the project's guidance says to do when a pulse finishes - release what was built, say - or tells you what finished and what it means. Ask to try it ("let me try it") and the chat releases what is built to `dist/<module>` and starts it on your machine, even while other pulses run. See [deploy](deploy.md). The chat reacts to it then and there, whatever else is running or queued, without waiting for you to speak - at once when it is idle, else as soon as the reply it is in ends: it does what the project's guidance says to do when a pulse finishes (release what was built, say), or tells you in a line or two what finished.
97
+ - **When a pulse stops** - a gate still failing after 20 attempts - it says where it stopped, why in plain words, and what to change in the spec - which section, and how. Running the same build again picks up from there.
98
+
99
+ In `print`, `json` and `rpc` modes the process ends when the answer is written, so the tools wait for the work there instead. Pulses live in memory for the session; the work itself is on disk.
310
100
 
311
101
  ## The project's config.turri.yaml
312
102
 
313
- The chat reads the project's `config.turri.yaml` afresh every turn and follows it: its agent is told what
314
- it sets, and the render tools default to it - `module` when you ask to build without naming one,
315
- `conformance-tests: false` to render without conformance tests (none written, none of the existing
316
- ones run) unless you ask for them, `coding-model` for what renders run on, and the testing scripts.
317
- `harness-model` is what `turri` starts on. What you ask for in the conversation wins.
318
- Every key, what happens without it, and how the models inherit: [the project config](config.md).
103
+ The chat reads the project's `config.turri.yaml` afresh every turn and follows it: its agent is told what it sets, and the render tools default to it - `module` when you ask to build without naming one, `conformance-tests: false` to render without conformance tests (none written, none of the existing ones run) unless you ask for them, `coding-model` for what renders run on, and the testing scripts. `harness-model` is what `turri` starts on. What you ask for in the conversation wins. Every key, what happens without it, and how the models inherit: [the project config](config.md).
319
104
 
320
- A project whose parts are on different stacks gives each stack its own `config.turri.<stack>.yaml`
321
- beside `config.turri.yaml` - `config.turri.backend.yaml`, `config.turri.frontend.yaml` - with its
322
- testing scripts, models and conformance over the project's. A stack is chosen, never worked out:
323
- `/stack backend` before building the backend, `/stack frontend` before the frontend, and every render
324
- from then on follows the chosen one's; the chat is told each stack's and which is chosen, and the status
325
- bar shows it. See [stacks](config.md#stacks).
105
+ A project whose parts are on different stacks gives each stack its own `config.turri.<stack>.yaml` beside `config.turri.yaml` - `config.turri.backend.yaml`, `config.turri.frontend.yaml` - with its testing scripts, models and conformance over the project's. A stack is chosen, never worked out: `/stack backend` before building the backend, `/stack frontend` before the frontend, and every render from then on follows the chosen one's; the chat is told each stack's and which is chosen, and the status bar shows it. See [stacks](config.md#stacks).
326
106
 
327
- A project with only a `config.yaml` - turri's file before it had its own name, or another tool's - is
328
- read from it until turri first writes a setting, which copies it to `config.turri.yaml`; see
329
- [the old config.yaml](config.md#the-old-configyaml).
107
+ A project with only a `config.yaml` - turri's file before it had its own name, or another tool's - is read from it until turri first writes a setting, which copies it to `config.turri.yaml`; see [the old config.yaml](config.md#the-old-configyaml).
330
108
 
331
109
  ## Choosing a model
332
110
 
333
- There are three: the **harness model**, the one you chat with; the **coding model**, the one
334
- every render runs on - functionalities, conformance tests, repairs, spec changes; and the **judge
335
- model**, which gives the verdicts in a conformance run - the judge, which says whether the code, the
336
- tests or the spec is wrong, and the test review. The project's `config.turri.yaml` can give each a model and
337
- a thinking level (off, minimal, low, medium, high, xhigh, max):
111
+ There are three: the **harness model**, the one you chat with; the **coding model**, the one every render runs on - functionalities, conformance tests, repairs, spec changes; and the **judge model**, which gives the verdicts in a conformance run - the judge, which says whether the code, the tests or the spec is wrong, and the test review. The project's `config.turri.yaml` can give each a model and a thinking level (off, minimal, low, medium, high, xhigh, max):
338
112
 
339
113
  ```yaml
340
114
  harness-model:
@@ -347,20 +121,11 @@ judge-model:
347
121
  model: anthropic/claude-opus-5-5
348
122
  ```
349
123
 
350
- Each may leave out either part, and a bare string (`coding-model: provider/id`, or
351
- `provider/id:high`) is a model alone. What one leaves out it takes from the one it inherits from:
352
- the judge model from the coding model, the coding model from the harness model - so with only a
353
- harness model, everything runs on it.
124
+ Each may leave out either part, and a bare string (`coding-model: provider/id`, or `provider/id:high`) is a model alone. What one leaves out it takes from the one it inherits from: the judge model from the coding model, the coding model from the harness model - so with only a harness model, everything runs on it.
354
125
 
355
- On the command line, `turri --harness-model <m> --coding-model <m>` wins over them
356
- (pi's own `--model` works for the harness model too), and in the conversation pi's `/model`
357
- changes the harness model and `engine`, below, the coding model. `model:`, from before
358
- there were two, is read as `coding-model`. With neither, renders run on the conversation's model.
126
+ On the command line, `turri --harness-model <m> --coding-model <m>` wins over them (pi's own `--model` works for the harness model too), and in the conversation pi's `/model` changes the harness model and `engine`, below, the coding model. `model:`, from before there were two, is read as `coding-model`. With neither, renders run on the conversation's model.
359
127
 
360
- Every render runs on the coding model unless you say otherwise. Say it in words -
361
- "render spec changes with gpt 5.5", "build the functionalities on Gemini 3.6 Flash", "use Claude
362
- for everything" - and the agent calls `engine`, which holds for the rest of the session
363
- (a resumed one too):
128
+ Every render runs on the coding model unless you say otherwise. Say it in words - "render spec changes with gpt 5.5", "build the functionalities on Gemini 3.6 Flash", "use Claude for everything" - and the agent calls `engine`, which holds for the rest of the session (a resumed one too):
364
129
 
365
130
  | kind of work | covers |
366
131
  | --- | --- |
@@ -368,25 +133,11 @@ for everything" - and the agent calls `engine`, which holds for the rest of the
368
133
  | functionalities | render functionality, render module, regenerate, conformance |
369
134
  | everything | both |
370
135
 
371
- It works mid-interview as well: the skill's agent has the same tool. Pulses already queued keep the
372
- model they were queued with; `"chat"` drops the session's choice, back to the default coding model -
373
- `--coding-model`, `config.turri.yaml`, or the conversation's. `/engine` shows
374
- what each kind of work runs on. A render tool can also be given a model for one call.
375
-
376
- Names are resolved strictly, because pi's own matching guesses and says nothing ("gpt-5" can land
377
- on a Bedrock model you have no key for). An exact `provider/model-id` is taken as it is. A looser
378
- name is taken when it fits exactly one model you have credentials for, or is exactly one model's
379
- id in other words ("gpt 5.5" is `openai/gpt-5.5`, not `gpt-5.5-pro`). Anything else comes back as
380
- a short list and the agent asks you which one; a model whose provider has no credentials is never
381
- picked.
382
-
383
- A provider a pi extension registers - your company's own LLM gateway, say - works for every agent
384
- the conversation starts, not only for the conversation. Those agents load no extensions (they would
385
- load a second copy of turri), so each is given the providers the conversation's extensions
386
- registered, as they are when it starts. An unattended run - `turri regenerate`, `render` and the
387
- rest, outside the chat - has no conversation to take them from: there, only the providers in pi's
388
- own configuration (`~/.pi/agent/models.json` and `auth.json`) are there, so a gateway those runs use
389
- has to be set up in `models.json`.
136
+ It works mid-interview as well: the skill's agent has the same tool. Pulses already queued keep the model they were queued with; `"chat"` drops the session's choice, back to the default coding model - `--coding-model`, `config.turri.yaml`, or the conversation's. `/engine` shows what each kind of work runs on. A render tool can also be given a model for one call.
137
+
138
+ Names are resolved strictly, because pi's own matching guesses and says nothing ("gpt-5" can land on a Bedrock model you have no key for). An exact `provider/model-id` is taken as it is. A looser name is taken when it fits exactly one model you have credentials for, or is exactly one model's id in other words ("gpt 5.5" is `openai/gpt-5.5`, not `gpt-5.5-pro`). Anything else comes back as a short list and the agent asks you which one; a model whose provider has no credentials is never picked.
139
+
140
+ A provider a pi extension registers - your company's own LLM gateway, say - works for every agent the conversation starts, not only for the conversation. Those agents load no extensions (they would load a second copy of turri), so each is given the providers the conversation's extensions registered, as they are when it starts. An unattended run - `turri regenerate`, `render` and the rest, outside the chat - has no conversation to take them from: there, only the providers in pi's own configuration (`~/.pi/agent/models.json` and `auth.json`) are there, so a gateway those runs use has to be set up in `models.json`.
390
141
 
391
142
  To change pi's own default, in `~/.pi/agent/settings.json`:
392
143
 
@@ -394,29 +145,13 @@ To change pi's own default, in `~/.pi/agent/settings.json`:
394
145
  { "defaultProvider": "google", "defaultModel": "gemini-3.1-pro-preview" }
395
146
  ```
396
147
 
397
- A provider failure - no credits, bad key, rate limit - is raised with the provider's own message,
398
- rather than surfacing as an agent that said nothing. One that passes - overloaded, rate limited, unreachable,
399
- timed out - is waited out first, after pi's own retries: six more tries, the wait doubled each time from 15
400
- seconds up to five minutes (15s, 30s, 1m, 2m, 4m, 5m, a tenth either way so parallel jobs do not all come back
401
- at once), the agent carrying on where it was. Each wait - pi's own retries too - is shown as it happens - a
402
- notification in the chat and the job panel's status, a yellow line in a headless run - and listed in the run
403
- report's `turn_incidents`. So is a provider stalling: a request to the model that nothing has come back on for two
404
- minutes (`TURRI_PROVIDER_STALL`, in seconds; 0 never), said once for each silence while the turn goes on waiting.
405
- A turn turri stops itself - its time up, the agent going round in a circle - is the work's normal course and is not
406
- said, only listed.
148
+ A provider failure - no credits, bad key, rate limit - is raised with the provider's own message, rather than surfacing as an agent that said nothing. One that passes - overloaded, rate limited, unreachable, timed out - is waited out first, after pi's own retries: six more tries, the wait doubled each time from 15 seconds up to five minutes (15s, 30s, 1m, 2m, 4m, 5m, a tenth either way so parallel jobs do not all come back at once), the agent carrying on where it was. Each wait - pi's own retries too - is shown as it happens - a notification in the chat and the job panel's status, an orange line in a headless run - and listed in the run report's `turn_incidents`. So is a provider stalling: a request to the model that nothing has come back on for two minutes (`TURRI_PROVIDER_STALL`, in seconds; 0 never), said once for each silence while the turn goes on waiting. A turn turri stops itself - its time up, the agent going round in a circle - is the work's normal course and is not said, only listed.
407
149
 
408
150
  ## Module history
409
151
 
410
- Each `plain_modules/<module>` is a git repository whose git directory is `.plaingit` rather than
411
- `.git`, so it stays plain files to your own repository. A commit is made after every step that
412
- changes the module - a render, a functionality regenerated, a conformance run, a regression repair, a spec
413
- change. `/lineage [module]` and `lineage` show it.
152
+ 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.
414
153
 
415
- The last commit is also the last known good state. Every render, functionality regenerated, spec change and
416
- conformance run starts by putting the codebase it works in back to it, so if turri was
417
- stopped or restarted mid-pulse, whatever that pulse left half-written is undone first - and one that
418
- does not pass is undone the same way when it ends, commits and all. Only work that passed is
419
- committed. Installed dependencies and caches are not in the history and stay. With git directly:
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:
420
155
 
421
156
  ```bash
422
157
  git --git-dir=plain_modules/<module>/.plaingit --work-tree=plain_modules/<module> log
@@ -424,40 +159,18 @@ git --git-dir=plain_modules/<module>/.plaingit --work-tree=plain_modules/<module
424
159
 
425
160
  ## Agent logs
426
161
 
427
- When an agent does something you cannot explain, its logs are where to look: the chat shows what
428
- its pulse is doing, not what its agents said. Every agent a render starts - the
429
- coding agent, the conformance agent, the repair agent, the spec-steps planner - also streams its
430
- whole conversation to a file of its own, always.
431
-
432
- The logs are in `.turri/debug/` in the project, beside `plain_modules`, one per agent, named
433
- by when it started and what it is: `2026-09-26T13-45-02-123Z-app-3-coding-agent.log`. Each starts
434
- with the pulse it runs for, its model and thinking level, its folder, its saved pi session, its
435
- tools and its system prompt, and then has, in order and stamped with the time: every prompt it is
436
- sent, whole; its thinking and replies as they stream; every tool call with its arguments, numbered
437
- - `→ #3 bash` - and its whole result under the same number, `← #3 bash done`, since calls made
438
- together run at once and finish in any order; a tool call a response was cut off in, marked as
439
- never run; each response's stop reason, tokens and cost; the provider's
440
- retries and errors; and how each turn ended. Every line is on disk as it happens, so
441
- `tail -f` follows an agent live and a run that crashed leaves its log up to that moment. The pulse's
442
- own log names each agent's log as it starts.
443
-
444
- Beside them, each pulse has a log of its own in `.turri/jobs/` - `<time>-<pulse id>-<kind>.log`:
445
- its whole transcript, written as it happens. The harness's stages, the functional spec or the
446
- diff it builds, and every one of its agents in turn - each prompt, its thinking and replies, every
447
- tool call and its result, whole where the screen clips them - and how the pulse ended. A finished pulse,
448
- 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
449
- prompt, tokens and retries besides.
450
-
451
- No agent can read the logs: they are outside `plain_modules` - or, for a `--build-dir` outside it,
452
- beside that folder rather than in it. Nothing prunes them either - delete
453
- the folder when you are done with it. A log that cannot be written is given up on without failing
454
- the render.
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.
163
+
164
+ 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
+ - `→ #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
+
167
+ 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
+
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.
455
170
 
456
171
  ## From the command line
457
172
 
458
- The same work, without a conversation. Run it from the directory that holds the spec, so its
459
- linked resources resolve the way the parser expects. For a long run - a whole spec overnight - see
460
- [running unattended](headless.md).
173
+ The same work, without a conversation. Run it from the directory that holds the spec, so its linked resources resolve the way the parser expects. For a long run - a whole spec overnight - see [running unattended](headless.md).
461
174
 
462
175
  ```bash
463
176
  turri validate <file.plain> # validate a spec - no model, no API key
@@ -474,7 +187,4 @@ turri cultivate brood # run a skill directly - by name, the pro
474
187
  turri release <file.plain> # release what is regenerated to dist/<module>, and activate it here
475
188
  ```
476
189
 
477
- The ones that build take `--model provider/model-id`; `regenerate` also takes `--build-dir` and
478
- `--dry-run`, which plans the work, prints the prompt of each codebase's first pulse and starts nothing.
479
- Template directories come from `PLAIN_TEMPLATE_DIRS`. `--help`
480
- on any of them lists the rest.
190
+ The ones that build take `--model provider/model-id`; `regenerate` also takes `--build-dir` and `--dry-run`, which plans the work, prints the prompt of each codebase's first pulse and starts nothing. Template directories come from `PLAIN_TEMPLATE_DIRS`. `--help` on any of them lists the rest.