@turri-dev/cli 0.1.11-next.fec1e14 → 0.1.12-next.8125d07

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 (40) hide show
  1. package/README.md +5 -5
  2. package/dist/{spec-diff-cli.js → change-plain-cli.js} +3 -3
  3. package/dist/cli.js +1 -1
  4. package/dist/extension.js +4 -4
  5. package/dist/genome.js +5 -5
  6. package/dist/identity.js +8 -6
  7. package/dist/loop-cli.d.ts +1 -1
  8. package/dist/loop-cli.js +1 -1
  9. package/dist/regenerate/activity.js +2 -2
  10. package/dist/self-invocation.js +6 -6
  11. package/dist/skill.d.ts +3 -3
  12. package/dist/skill.js +2 -2
  13. package/dist/spec-tools.js +2 -2
  14. package/dist/stacks.js +1 -1
  15. package/dist/tools.js +1 -1
  16. package/docs/README.md +13 -13
  17. package/docs/authoring-plain.md +34 -34
  18. package/docs/config.md +25 -25
  19. package/docs/deploy.md +5 -5
  20. package/docs/development.md +11 -11
  21. package/docs/headless.md +18 -18
  22. package/docs/hosting.md +14 -14
  23. package/docs/images/how-turri-works.svg +1 -1
  24. package/docs/installation.md +13 -13
  25. package/docs/parser.md +5 -5
  26. package/docs/regenerating.md +78 -78
  27. package/docs/sandbox.md +7 -7
  28. package/docs/skills-and-gates.md +19 -19
  29. package/docs/theming.md +11 -11
  30. package/docs/using.md +50 -50
  31. package/genome/skills/brood/SKILL.md +11 -11
  32. package/genome/skills/brood/references/product.md +4 -4
  33. package/genome/skills/brood/references/testing.md +1 -1
  34. package/genome/skills/bud/SKILL.md +6 -6
  35. package/genome/skills/mature/SKILL.md +4 -4
  36. package/genome/skills/spawn/SKILL.md +4 -4
  37. package/package.json +1 -1
  38. package/genome/skills/init-plain-project/SKILL.md +0 -117
  39. package/genome/skills/init-plain-project/references/checklist.md +0 -30
  40. /package/dist/{spec-diff-cli.d.ts → change-plain-cli.d.ts} +0 -0
@@ -1,10 +1,10 @@
1
1
  # Regenerating the code
2
2
 
3
- What happens when a spec is turned into code - in which order, by which agents, and what has to be true before the harness moves on. The order is the harness's, not the agents': an agent writes code or tests, and the harness decides what runs next and whether the work is done.
3
+ What happens when \*\*\*plain is turned into code - in which order, by which agents, and what has to be true before the harness moves on. The order is the harness's, not the agents': an agent writes code or tests, and the harness decides what runs next and whether the work is done.
4
4
 
5
5
  ## Where things go
6
6
 
7
- A spec is built in its **project**: the nearest folder, from the spec's own up, that holds a `config.turri.yaml`, a stack's `config.turri.<stack>.yaml`, the old `config.yaml` or a `plain_modules/` - or, with none, the spec's own folder. That is where its `plain_modules/` is, its `config.turri.yaml` read and its testing scripts found, wherever turri was started: a project that keeps its specs in `plain/`, with `plain/config.turri.yaml` and `plain/plain_modules/`, builds `plain/hubspot.plain` in `plain/plain_modules/hubspot/`, named from the folder above. Links in a spec are relative to the spec.
7
+ \*\*\*plain is built in its **project**: the nearest folder, from \*\*\*plain's own up, that holds a `config.turri.yaml`, a stack's `config.turri.<stack>.yaml`, the old `config.yaml` or a `plain_modules/` - or, with none, \*\*\*plain's own folder. That is where its `plain_modules/` is, its `config.turri.yaml` read and its testing scripts found, wherever turri was started: a project that keeps its \*\*\*plain in `plain/`, with `plain/config.turri.yaml` and `plain/plain_modules/`, builds `plain/hubspot.plain` in `plain/plain_modules/hubspot/`, named from the folder above. Links in \*\*\*plain are relative to the file they are in.
8
8
 
9
9
  Every path below is in the project. What the person writes:
10
10
 
@@ -20,13 +20,13 @@ What a module is - each module's folder, its own git history:
20
20
  | --- | --- |
21
21
  | `plain_modules/<module>/code/` | the implementation and its unit tests |
22
22
  | `plain_modules/<module>/tests/` | the black-box conformance tests, organised however suits them |
23
- | `plain_modules/<module>/code/.turri.json` | the code record: the spec the code is built from - see [below](#what-the-code-is-built-from) |
23
+ | `plain_modules/<module>/code/.turri.json` | the code record: the \*\*\*plain description the code is built from - see [below](#what-the-code-is-built-from) |
24
24
  | `plain_modules/<module>/tests/.turri.json` | the tests record: what the conformance tests are written for - see [below](#what-the-code-is-built-from) |
25
25
  | `plain_modules/<module>/code/.turri-notes.md` | the working notes of the agents that work on the code - coding agents, reviewers, the code fixer, the repair agent - see [below](#working-notes) |
26
26
  | `plain_modules/<module>/tests/.turri-notes.md` | the conformance tests' own working notes: the conformance agent's, its runs' attempts, what its reviews let go, its pulses - never read by a coding agent |
27
27
  | `plain_modules/<module>/.plaingit` | the module's history: code, tests and both records, committed together - see [using](using.md#module-history) |
28
28
 
29
- A module that `requires` another starts from a copy of that module's code and tests, and builds on top of it; the latest module built in a chain is where later changes to any module of the chain are made. What that code implements comes with it, as built: the other module's definitions and implementation reqs, tagged with it, and its functional specs, as ones the new module inherits. A definition or req of the module's own spec that a module below already has, word for word, is not new work for it: the code implements it already.
29
+ A module that `requires` another starts from a copy of that module's code and tests, and builds on top of it; the latest module built in a chain is where later changes to any module of the chain are made. What that code implements comes with it, as built: the other module's definitions and implementation reqs, tagged with it, and its functional specs, as ones the new module inherits. A definition or req of the module's own \*\*\*plain that a module below already has, word for word, is not new work for it: the code implements it already.
30
30
 
31
31
  The harness's scratch - each ignores itself, and is never part of a module's history:
32
32
 
@@ -49,7 +49,7 @@ One project can hold modules that share nothing but a common module - a Python b
49
49
 
50
50
  ## One job
51
51
 
52
- Every piece of work on the code is a job of the work loop (see [a whole module](#a-whole-module)) - in the chat, a **pulse** - the side panel's **regen** is the spec with how much of it the code has been regenerated from (`spec-map.ts`), and its pulses every one of them - while the code and this page call it a job: a spec diff that takes the code from the spec it is built from to the spec the job ends on. To see what the first jobs would be told:
52
+ Every piece of work on the code is a job of the work loop (see [a whole module](#a-whole-module)) - in the chat, a **pulse** - the side panel's **regen** is \*\*\*plain with how much of it the code has been regenerated from (`spec-map.ts`), and its pulses every one of them - while the code and this page call it a job: a \*\*\*plain diff that takes the code from the \*\*\*plain description it is built from to the \*\*\*plain description the job ends on. To see what the first jobs would be told:
53
53
 
54
54
  ```bash
55
55
  turri regenerate <file.plain> --dry-run # plan the work, print each codebase's first prompt, start nothing
@@ -57,7 +57,7 @@ turri regenerate <file.plain> --dry-run # plan the work, print each codebas
57
57
 
58
58
  ### What the agent is given
59
59
 
60
- The prompt, and nothing else - the agent cannot read the `.plain` files. Every prompt for an agent that builds, tests or judges from the spec starts with how to read it: what each section is for (the implementation reqs bind the whole codebase; acceptance tests carry the same authority as their functionality) and what the predefined concepts mean - `:Implementation:`, `:UnitTests:`, `:ConformanceTests:` and the rest, used in every spec and defined in none. It also says how a failure is fixed without hiding it: no changing test data to get a pass, no mocking the system under test, no skipping or silencing a failing test. It holds the definitions and implementation reqs in scope, every functionality already built (the required modules' too) marked as implemented, a map of the codebase as it stands, the contents of any linked resources, and the change to build, section by section, with what to do with each functional spec it touches (see [what a job is given](#what-a-job-is-given-and-what-it-records)):
60
+ The prompt, and nothing else - the agent cannot read the `.plain` files. Every prompt for an agent that builds, tests or judges from \*\*\*plain starts with how to read it: what each section is for (the implementation reqs bind the whole codebase; acceptance tests carry the same authority as their functionality) and what the predefined concepts mean - `:Implementation:`, `:UnitTests:`, `:ConformanceTests:` and the rest, used in every module's \*\*\*plain and defined in none. It also says how a failure is fixed without hiding it: no changing test data to get a pass, no mocking the system under test, no skipping or silencing a failing test. It holds the definitions and implementation reqs in scope, every functionality already built (the required modules' too) marked as implemented, a map of the codebase as it stands, the contents of any linked resources, and the change to build, section by section, with what to do with each functional spec it touches (see [what a job is given](#what-a-job-is-given-and-what-it-records)):
61
61
 
62
62
  ```
63
63
  <definitions> … </definitions>
@@ -70,7 +70,7 @@ The prompt, and nothing else - the agent cannot read the `.plain` files. Every p
70
70
 
71
71
  The test reqs and the acceptance tests are not in it: they are the conformance agents'.
72
72
 
73
- Every section has one name, its tag's, in every prompt: how to read the spec introduces each one as `<definitions>`, `<implementation reqs>`, `<test reqs>`, `<functional specs>` (each functional spec a `<functionality module="…" id="…">`), `<acceptance tests>`, `<linked resources>` and `<spec change>`, and the prompts' own words call each section by that name. The `***definitions***` headings of a `.plain` file appear only where a spec change could not be told section by section and the agent is given the raw diff: it is then told which tag each heading is. A spec in full - the planner's, the spec-steps agent's, the conformance agents' - is laid out in the same tags.
73
+ Every section has one name, its tag's, in every prompt: how to read \*\*\*plain introduces each one as `<definitions>`, `<implementation reqs>`, `<test reqs>`, `<functional specs>` (each functional spec a `<functionality module="…" id="…">`), `<acceptance tests>`, `<linked resources>` and `<spec change>`, and the prompts' own words call each section by that name. The `***definitions***` headings of a `.plain` file appear only where a \*\*\*plain change could not be told section by section and the agent is given the raw diff: it is then told which tag each heading is. \*\*\*plain in full - the planner's, the steps agent's (`spec-steps.ts`), the conformance agents' - is laid out in the same tags.
74
74
 
75
75
  A module that `requires` another inherits its functional specs; one that `import`s another inherits its definitions, implementation reqs and test reqs.
76
76
 
@@ -84,21 +84,21 @@ A turn turri stops itself - for any of these, or for its time, below - ends as a
84
84
 
85
85
  A tool argument that is a list of objects - the explorer's `interfaces` and `plan`, a reviewer's `problems` - is what small models get wrong most. Before a call's arguments are checked, a list sent as JSON text, entries sent as JSON text, one object for the list, or a list written inside another argument's text (`...</tests_reach_it><plan>[...]</plan>`) are taken as the list; what still is not one is refused saying which argument, what was sent, each entry's fields and an example (`list-arguments.ts`).
86
86
 
87
- The agents with one thing to decide have a budget of tool calls: the judge 30, the test review and the explorer 40. Past it every tool but the one that hands the decision over refuses, telling it to decide with what it knows; past twice the budget its turn is stopped. Handing the decision over starts the count again - a reviewer kept for the next review gets its whole budget for it. And every turn of an agent a render starts has two minutes (`turn-limit:` in the [config](config.md), in seconds; 0 for none). When they are up its turn ends at its next request to the model - never in the middle of one, which the provider bills whole, uncached, for an answer thrown away: what is running then, the model answering or a tool, finishes first, within a grace of a minute (TURRI_TURN_GRACE) after which it is ended where it is. The harness takes it from there - it runs the tests, and judges. A code fix has to build and pass the code's unit tests before the conformance suite runs again: one that does not goes straight back to the coding agent, with the output, rather than to a judge. So is an agent whose calls to one tool fail ten times in a row with nothing going through in between - arguments the tool refuses never reach it, so however they are reworded, no call-by-call check sees them. A note's section is taken in any wording (`where`, "Where things are"), and one that is no section is refused with the four that are.
87
+ The agents with one thing to decide have a budget of tool calls: the judge 30, the test review and the explorer 40. Past it every tool but the one that hands the decision over refuses, telling it to decide with what it knows; past twice the budget its turn is stopped. Handing the decision over starts the count again - a reviewer kept for the next review gets its whole budget for it. And every turn of an agent a regeneration starts has two minutes (`turn-limit:` in the [config](config.md), in seconds; 0 for none). When they are up its turn ends at its next request to the model - never in the middle of one, which the provider bills whole, uncached, for an answer thrown away: what is running then, the model answering or a tool, finishes first, within a grace of a minute (TURRI_TURN_GRACE) after which it is ended where it is. The harness takes it from there - it runs the tests, and judges. A code fix has to build and pass the code's unit tests before the conformance suite runs again: one that does not goes straight back to the coding agent, with the output, rather than to a judge. So is an agent whose calls to one tool fail ten times in a row with nothing going through in between - arguments the tool refuses never reach it, so however they are reworded, no call-by-call check sees them. A note's section is taken in any wording (`where`, "Where things are"), and one that is no section is refused with the four that are.
88
88
 
89
89
  ### The tests must actually pass
90
90
 
91
91
  While it works, the agent runs tests however it likes with `bash` - one file, one case, any configuration - in the [sandbox](sandbox.md). Before it finishes, it calls `run_unit_tests`: a final check that takes no command and runs the project's unit testing script exactly as the harness will. But a job is not done on the agent's run, whatever it ran: after each turn **the harness runs the unit testing script itself**, and only that run counts (see [the testing scripts](#the-testing-scripts)). It sends the agent back, up to 20 times, when:
92
92
 
93
- - **The harness's run of the unit testing script fails** - its output goes back to the agent, with how to fix it, as every failure an agent is sent back with does (unit tests, a conformance run, a test or code the judge found wrong): understand the failure from its whole trace; find the root cause in the lines it points at, against the spec; reproduce it with that one test; fix the cause; check it with that test and then the whole suite, the run that counts; and leave the cause and the fix in the notes. **The same failure three times running** - the same fingerprint of the run, its numbers, paths and ids left out, as a conformance run counts it - and a **debugger** looks at it with fresh eyes: an agent of its own (`src/regenerate/debugger.ts`), on the `debugger` role's model, else a stronger one than the coding agent's - the judge model when `judge-model` is set, else the harness model - with a new session, that reads the failing run, the tests, the code, the build files and the unit testing script, and the web, and changes nothing. It hands over the root cause and the fix - which files, what to change - and the coding agent gets them with the failure, told to make that fix rather than another variation on what it tried. An agent circles a cause it has not thought of - an in-memory database every connection opens empty, a test runner that leaves the code off its path - and this is the way out. The rounds go on as before, up to 20; should the same failure come round three times again, the debugger looks again. **A run the time limit stopped** is looked at by the debugger at once, told how long the run had and that the limit stopped it: it finds what hangs - the root cause and the fix, as above - or that nothing does, the run getting on up to the limit and needing more time than a test run may take. Then the pulse stops, rolled back and not retried, and the person is told to raise `TURRI_COMMAND_TIMEOUT` or make the suite faster.
93
+ - **The harness's run of the unit testing script fails** - its output goes back to the agent, with how to fix it, as every failure an agent is sent back with does (unit tests, a conformance run, a test or code the judge found wrong): understand the failure from its whole trace; find the root cause in the lines it points at, against \*\*\*plain; reproduce it with that one test; fix the cause; check it with that test and then the whole suite, the run that counts; and leave the cause and the fix in the notes. **The same failure three times running** - the same fingerprint of the run, its numbers, paths and ids left out, as a conformance run counts it - and a **debugger** looks at it with fresh eyes: an agent of its own (`src/regenerate/debugger.ts`), on the `debugger` role's model, else a stronger one than the coding agent's - the judge model when `judge-model` is set, else the harness model - with a new session, that reads the failing run, the tests, the code, the build files and the unit testing script, and the web, and changes nothing. It hands over the root cause and the fix - which files, what to change - and the coding agent gets them with the failure, told to make that fix rather than another variation on what it tried. An agent circles a cause it has not thought of - an in-memory database every connection opens empty, a test runner that leaves the code off its path - and this is the way out. The rounds go on as before, up to 20; should the same failure come round three times again, the debugger looks again. **A run the time limit stopped** is looked at by the debugger at once, told how long the run had and that the limit stopped it: it finds what hangs - the root cause and the fix, as above - or that nothing does, the run getting on up to the limit and needing more time than a test run may take. Then the pulse stops, rolled back and not retried, and the person is told to raise `TURRI_COMMAND_TIMEOUT` or make the suite faster.
94
94
  - **It goes round in circles in its own runs.** An agent stuck on a failure can try the same few changes in turn - three signatures of a stand-in function, say - and run the tests after each, dozens of times in one turn. Its own `run_unit_tests` runs are watched (`createLoopWatch` in `test-scripts.ts`): the code folder back exactly as it was at an earlier failing run, its notes aside, or six failing runs in a row the same way, is a loop. The first time, the run tells it so - stop editing, read the code under test where the failure points, then make the one change the cause calls for. The second time, its turn is ended there, and the debugger looks at once, without waiting for three rounds. A passing run clears it.
95
95
  - **Tests went missing.** The test files present before the turn are inventoried and compared afterwards; a deleted file or a file that lost cases is challenged by name.
96
96
  - **The static checks fail** - when the unit testing script runs them, it exits 80 for the tests passing and its checks not, and the agent is sent back saying so, with the findings (see [the static checks](#the-static-checks)). They share the same 20 rounds - a static check is part of what "the unit tests pass" means here, not a gate after it.
97
- - **It wrote nothing.** A turn can end with the agent having only thought the problem through, and the code folder as it found it (notes aside). That leaves nothing to test or review. So before the tests run, the agent is told to stop planning and write a draft: its best guess at what the spec asks, the code and its unit tests, with any assumption put in the notes. A draft that is wrong comes back from the tests and the review; nothing written cannot. It is asked once, to write the change or say why it needs no code: one that only rewords a spec may need none. After that, the turn is taken as what it did.
97
+ - **It wrote nothing.** A turn can end with the agent having only thought the problem through, and the code folder as it found it (notes aside). That leaves nothing to test or review. So before the tests run, the agent is told to stop planning and write a draft: its best guess at what \*\*\*plain asks, the code and its unit tests, with any assumption put in the notes. A draft that is wrong comes back from the tests and the review; nothing written cannot. It is asked once, to write the change or say why it needs no code: one that only rewords \*\*\*plain may need none. After that, the turn is taken as what it did.
98
98
 
99
- **Long output.** A testing script's run is shown whole up to 16,000 characters. Past that the agent is shown its failures, each with the 20 lines after it - its trace - its counts (`Tests run:`, `Ran 3 tests`, `BUILD FAILURE`) and its last 80 lines, with DEBUG and TRACE logging left out and each gap marked: on the hycu runs, 73% less to carry, every failing run's failures still there. Any other output an agent is shown is whole up to 60,000 characters, and past that its end. The whole of it is kept in `plain_modules/.turri/logs/`, and the cut names it by an id: the agent reads it with `read_output` - a range of lines, or the lines matching a pattern, each with its number - which reads those kept outputs and nothing else. A command in its shell cut short by pi is kept the same way. No output points at a path: the file it is in is outside what the agent may reach.
99
+ **Long output.** A testing script's run is shown whole up to 16,000 characters. Past that the agent is shown its failures, each with the 20 lines after it - its trace - its counts (`Tests run:`, `Ran 3 tests`, `BUILD FAILURE`) and its last 80 lines, with DEBUG and TRACE logging left out and each gap marked: on the hycu runs, 73% less to carry, every failing run's failures still there. Any other output an agent is shown is whole up to 60,000 characters, and past that its end. The whole of it is kept in `plain_modules/.turri/logs/`, and the cut names it by an id: the agent reads it with `read_output` - a range of lines, or the lines matching a pattern, each with its number - which reads those kept outputs and nothing else. A command in its shell cut short by [pi](https://pi.dev) is kept the same way. No output points at a path: the file it is in is outside what the agent may reach.
100
100
 
101
- A test may go only when it asserts nothing meaningful - it cannot fail, exactly duplicates another, or tests something the spec does not require. Inconvenient, slow or failing are not grounds. Justified removals are reported, not silent. The baseline is taken before the agent starts, so breaking an earlier functionality's test is caught too.
101
+ A test may go only when it asserts nothing meaningful - it cannot fail, exactly duplicates another, or tests something \*\*\*plain does not require. Inconvenient, slow or failing are not grounds. Justified removals are reported, not silent. The baseline is taken before the agent starts, so breaking an earlier functionality's test is caught too.
102
102
 
103
103
  ### The static checks
104
104
 
@@ -123,16 +123,16 @@ The reviewer has `can_it_fail` too, three runs a review session: a test it doubt
123
123
 
124
124
  ### The code and its unit tests are reviewed
125
125
 
126
- Passing unit tests prove only what they check, and a coding agent is quick to write tests that check next to nothing - that a function exists, that a result is not empty, that a status is 200 - or code that no test reaches. So, with `review: true` in the [config](config.md), once the unit testing script passes a reviewer on the judge model reads what the work wrote, beside the spec, and changes nothing. It reviews both halves, with the unit testing script word for word in its prompt: a test the script never reaches is not run, and checks nothing. The review is off by default - `review: false`, or the key left out - and so is the conformance tests' review: the work goes on once its tests pass. Even on, a module's first pulse is not reviewed when it builds one functional spec - the project set up and the smallest thing that runs, as `spawn` starts one: a review of a scaffold is time spent before anything can be tried.
126
+ Passing unit tests prove only what they check, and a coding agent is quick to write tests that check next to nothing - that a function exists, that a result is not empty, that a status is 200 - or code that no test reaches. So, with `review: true` in the [config](config.md), once the unit testing script passes a reviewer on the judge model reads what the work wrote, beside \*\*\*plain, and changes nothing. It reviews both halves, with the unit testing script word for word in its prompt: a test the script never reaches is not run, and checks nothing. The review is off by default - `review: false`, or the key left out - and so is the conformance tests' review: the work goes on once its tests pass. Even on, a module's first pulse is not reviewed when it builds one functional spec - the project set up and the smallest thing that runs, as `spawn` starts one: a review of a scaffold is time spent before anything can be tried.
127
127
 
128
- - **The code.** Every behaviour, edge case, validation rule and error the spec states for this work is implemented as the spec says it, with nothing left as a stub, a placeholder or a hard-coded answer. The code keeps to the implementation reqs and does not break what was already built. A behaviour with no code for it is raised as not implemented. Such a problem is of kind `wrong`.
129
- - **The unit tests.** Every behaviour, edge case and error the spec states for this work has a test asserting the exact outcome the spec says, that fails when it breaks; that no test only checks something exists, asserts nothing, is skipped or swallows a failure; that the unit under test is never mocked - only what is outside it; and that the tests are deterministic. A test that is not there is `missing`, a weak one is `bad`.
128
+ - **The code.** Every behaviour, edge case, validation rule and error \*\*\*plain states for this work is implemented as \*\*\*plain says it, with nothing left as a stub, a placeholder or a hard-coded answer. The code keeps to the implementation reqs and does not break what was already built. A behaviour with no code for it is raised as not implemented. Such a problem is of kind `wrong`.
129
+ - **The unit tests.** Every behaviour, edge case and error \*\*\*plain states for this work has a test asserting the exact outcome \*\*\*plain says, that fails when it breaks; that no test only checks something exists, asserts nothing, is skipped or swallows a failure; that the unit under test is never mocked - only what is outside it; and that the tests are deterministic. A test that is not there is `missing`, a weak one is `bad`.
130
130
 
131
- What the change adds or changes is what needs code and tests, and a change that adds no behaviour needs neither. Code written another way than the reviewer would have written it is not a problem, as long as it does what the spec says.
131
+ What the change adds or changes is what needs code and tests, and a change that adds no behaviour needs neither. Code written another way than the reviewer would have written it is not a problem, as long as it does what \*\*\*plain says.
132
132
 
133
133
  The review is told what to inspect, so it does not have to guess. One reviewer does every review of the work - one session for the loop (see [agent sessions](#agent-sessions)) - so a review after the first starts from what it already read and raised. Its instructions hold:
134
134
 
135
- - **The spec as the coding agent had it**, laid out the same way: how to read a spec, `<definitions>`, `<implementation reqs>` and `<already implemented>`. What this work built is apart, in `<new in this work>`: the `<spec change>`, section by section.
135
+ - **\*\*\*plain as the coding agent had it**, laid out the same way: how to read \*\*\*plain, `<definitions>`, `<implementation reqs>` and `<already implemented>`. What this work built is apart, in `<new in this work>`: the `<spec change>`, section by section.
136
136
 
137
137
  And each review is shown:
138
138
 
@@ -140,15 +140,15 @@ And each review is shown:
140
140
  - **What changed since its last review**, every time after: the harness takes a snapshot of the code folder at each review - a git tree in `.plaingit`, no commit, the module's index untouched - and shows the diff from it. With it, the problems of the last review that went to the coding agent, and what the arbiter let go of it, not to be raised again.
141
141
  - **The coding agent's account.** The coding agent ends each turn that goes to review with `submit_work`: what it did and why, and for each problem the last review raised, by its number, fixed or declined, why, and the files. It is a claim, and the reviewer is told so: it checks it against the diff, which the harness takes itself - a problem said to be fixed that the code does not fix is still a problem, and one declined is weighed on its reason. An account that leaves a problem unanswered sends the coding agent back once; with no account at all, the reviewer is told so and goes by the diff.
142
142
 
143
- The reviewer is the exacting developer, opinionated about everything: it raises every problem it finds, however small. Its problems go back to the coding agent, the unit testing script has to pass again, and the next review checks those problems first rather than starting over. A problem that leaves a behaviour of the spec not implemented, implemented wrong or untested - no test, or one that cannot fail - is **blocking** and worked on first.
143
+ The reviewer is the exacting developer, opinionated about everything: it raises every problem it finds, however small. Its problems go back to the coding agent, the unit testing script has to pass again, and the next review checks those problems first rather than starting over. A problem that leaves a behaviour of \*\*\*plain not implemented, implemented wrong or untested - no test, or one that cannot fail - is **blocking** and worked on first.
144
144
 
145
- The work is reviewed twice at most. The first review that sends it back goes to the coding agent as it is. The second, **the arbiter** weighs before it reaches the coding agent: the distinguished engineer, on the judge model, read-only, given the same spec and code diff as the reviewer, the tests and every review so far. It rules on each problem. It upholds a problem when a behaviour the spec states for this work is not implemented, implemented other than the spec says, or untested, or when a test cannot fail: the reviewer is right, and the coding agent fixes it. It dismisses a problem that is out of scope or a nitpick: the test already tests the behaviour, it is another case of one already covered, it is a matter of style, or the code is written another way but does what the spec says. Only what it upholds goes back. What it dismisses is let go, with why, in the working notes' pitfalls. When it upholds nothing, the work is approved as it is. The review optimises the code and its tests; it never stops the work - whether it is done is the unit testing script's to say. What the second review sends back is worked on once, and then the work goes on without another review - once its unit tests pass, which they still must. The review is told that behaviour is what a functional spec, an acceptance test or a req states: a page or a component only a definition names has no code yet. The conformance tests are reviewed as black-box tests (see [conformance tests](#conformance-tests)).
145
+ The work is reviewed twice at most. The first review that sends it back goes to the coding agent as it is. The second, **the arbiter** weighs before it reaches the coding agent: the distinguished engineer, on the judge model, read-only, given the same \*\*\*plain and code diff as the reviewer, the tests and every review so far. It rules on each problem. It upholds a problem when a behaviour \*\*\*plain states for this work is not implemented, implemented other than \*\*\*plain says, or untested, or when a test cannot fail: the reviewer is right, and the coding agent fixes it. It dismisses a problem that is out of scope or a nitpick: the test already tests the behaviour, it is another case of one already covered, it is a matter of style, or the code is written another way but does what \*\*\*plain says. Only what it upholds goes back. What it dismisses is let go, with why, in the working notes' pitfalls. When it upholds nothing, the work is approved as it is. The review optimises the code and its tests; it never stops the work - whether it is done is the unit testing script's to say. What the second review sends back is worked on once, and then the work goes on without another review - once its unit tests pass, which they still must. The review is told that behaviour is what a functional spec, an acceptance test or a req states: a page or a component only a definition names has no code yet. The conformance tests are reviewed as black-box tests (see [conformance tests](#conformance-tests)).
146
146
 
147
147
  Every time a review sends tests back, the agent that fixes them also leaves the lesson in the working notes' pitfalls: not the fix, but the kind of test the review found weak or missing and how to write it instead - "tests assert the exact response body, never only that one came back". One that fixes the tests and leaves no lesson is asked once more. Every later agent on the codebase starts from the notes, and is told to write its tests so they would pass those reviews the first time - so the reviews of the next functionalities have less to send back, and finish sooner.
148
148
 
149
149
  ### Then
150
150
 
151
- Once the unit tests pass and are reviewed, the job lands: the code record becomes the spec the job ends on, and a commit is made to the module's history. The conformance tests are not run here: they are the conformance track's, and its job for what this one built runs next, before anything is built on it (see [conformance tests in the work loop](#conformance-tests-in-the-work-loop)). A job that does not pass is undone instead - see [below](#what-the-code-is-built-from). A job that lands ends its report with the offer to try it - "Want to try it? Just ask me" in the chat, `turri release <spec>` on the command line - and trying it is [deploy](deploy.md)'s, not the job's. Conformance jobs that land make the same offer.
151
+ Once the unit tests pass and are reviewed, the job lands: the code record becomes the \*\*\*plain description the job ends on, and a commit is made to the module's history. The conformance tests are not run here: they are the conformance track's, and its job for what this one built runs next, before anything is built on it (see [conformance tests in the work loop](#conformance-tests-in-the-work-loop)). A job that does not pass is undone instead - see [below](#what-the-code-is-built-from). A job that lands ends its report with the offer to try it - "Want to try it? Just ask me" in the chat, `turri release <spec>` on the command line - and trying it is [deploy](deploy.md)'s, not the job's. Conformance jobs that land make the same offer.
152
152
 
153
153
  ## A whole module
154
154
 
@@ -156,45 +156,45 @@ Once the unit tests pass and are reviewed, the job lands: the code record become
156
156
  turri regenerate <file.plain>
157
157
  ```
158
158
 
159
- Rendering a module - `regenerate` in a conversation, `turri regenerate` on the command line - is not a job of its own, and nothing is queued: the work loop (`src/regenerate/loop.ts`) works out what is left to build, has it planned into jobs, and runs the first. What is left is the difference between what a codebase's code is built from - its code record - and the spec of its requires chain as the `.plain` files have it now. When a job ends, or the spec changes, it is worked out again; a plan is kept only while the spec and the record it was cut from stay as they were.
159
+ Regenerating a module - `regenerate` in a conversation, `turri regenerate` on the command line - is not a job of its own, and nothing is queued: the work loop (`src/regenerate/loop.ts`) works out what is left to build, has it planned into jobs, and runs the first. What is left is the difference between what a codebase's code is built from - its code record - and its requires chain's \*\*\*plain as the `.plain` files have it now. When a job ends, or \*\*\*plain changes, it is worked out again; a plan is kept only while \*\*\*plain and the record it was cut from stay as they were.
160
160
 
161
- Code accumulates up a `requires` chain: a module is built on a copy of the code of the one it requires. So a chain's codebase is its furthest-built module - its tip - and its record holds the whole chain: the definitions and implementation reqs of the modules below, each tagged with its module, their functional specs among the ones it inherits, and its own. A change to a module below is made there. The codebases below the tip are left as they were, their records saying what they are built from; one is brought up to its own spec again only when a module not built yet is to start from it - the module below first, then the new one on a copy of its code. With no module of a chain built, it is built bottom first, a module waiting while the one it is built on has work left or a job running.
161
+ Code accumulates up a `requires` chain: a module is built on a copy of the code of the one it requires. So a chain's codebase is its furthest-built module - its tip - and its record holds the whole chain: the definitions and implementation reqs of the modules below, each tagged with its module, their functional specs among the ones it inherits, and its own. A change to a module below is made there. The codebases below the tip are left as they were, their records saying what they are built from; one is brought up to its own \*\*\*plain again only when a module not built yet is to start from it - the module below first, then the new one on a copy of its code. With no module of a chain built, it is built bottom first, a module waiting while the one it is built on has work left or a job running.
162
162
 
163
- A module already built from the spec as it is gets nothing. A job that does not land is rolled back, and halts its codebase: nothing more runs there until the spec changes or the module is asked for again. On the command line, `turri regenerate` runs until nothing more can start, one line as each job starts and ends, and exits 1 when any failed.
163
+ A module already built from \*\*\*plain as it is gets nothing. A job that does not land is rolled back, and halts its codebase: nothing more runs there until \*\*\*plain changes or the module is asked for again. On the command line, `turri regenerate` runs until nothing more can start, one line as each job starts and ends, and exits 1 when any failed.
164
164
 
165
- The person halts a module's planned work too: `halt` (and `/halt`) given a planned row - `planned-<module>-2`, `planned-<module>-waiting` - or the module's name. A module's pulses are planned again from its spec at every look, so one planned pulse cannot be taken out alone: the module is halted - its running pulse stopped and rolled back, none of its planned pulses started, the modules built on it waiting for it - and what landed stays. A halt the person asked for holds through spec changes - `write_spec_diff` brings the spec in without starting the module - until the module is asked for again (`regenerate`, `conform`). To build some of it later, or cut it differently, there is `steer`; to drop work, the spec.
165
+ The person halts a module's planned work too: `halt` (and `/halt`) given a planned row - `planned-<module>-2`, `planned-<module>-waiting` - or the module's name. A module's pulses are planned again from its \*\*\*plain at every look, so one planned pulse cannot be taken out alone: the module is halted - its running pulse stopped and rolled back, none of its planned pulses started, the modules built on it waiting for it - and what landed stays. A halt the person asked for holds through \*\*\*plain changes - `change_plain` brings \*\*\*plain in without starting the module - until the module is asked for again (`regenerate`, `conform`). To build some of it later, or cut it differently, there is `steer`; to drop work, \*\*\*plain.
166
166
 
167
- A module the loop looked after whose `.plain` file is gone is forgotten - no rows, nothing waited for - and a codebase left behind, or whose spec no longer parses, shows nothing planned: its plan, and what it waited for, were the spec's before.
167
+ A module the loop looked after whose `.plain` file is gone is forgotten - no rows, nothing waited for - and a codebase left behind, or whose \*\*\*plain no longer parses, shows nothing planned: its plan, and what it waited for, were \*\*\*plain's before.
168
168
 
169
169
  ### How the work is cut into jobs
170
170
 
171
- A job that renders the whole of a new spec is too big to build well, and a render per functional spec, the first carrying every definition and req, is no better: most of the work lands in one job. So the work is cut from the functional specs outward (`chunk-plan.ts`), in three steps:
171
+ A job that regenerates the whole of a new module's \*\*\*plain is too big to build well, and a regeneration per functional spec, the first carrying every definition and req, is no better: most of the work lands in one job. So the work is cut from the functional specs outward (`chunk-plan.ts`), in three steps:
172
172
 
173
- 1. **Which functional specs go together** - the new ones, and those [regenerated again](#what-a-job-is-given-and-what-it-records). An agent groups them, by default: fewer, fuller pulses, as each costs a coding session, a test run and a review. What builds one feature goes together - the feature, its edge cases and the specs that build on it, a component and the parts only it uses - up to `max-specs-per-pulse` (3 unset), only ones next to each other in the same module; a spec goes alone only when it is truly independent or very large on its own. Each is shown with its module and its id there, and a number of its own to answer with: a codebase regenerates the functional specs of the modules it is built on too, and each module numbers its own from 1.
173
+ 1. **Which functional specs go together** - the new ones, and those [regenerated again](#what-a-job-is-given-and-what-it-records). An agent groups them, by default: fewer, fuller pulses, as each costs a coding session, a test run and a review. What builds one feature goes together - the feature, its edge cases and the functional specs that build on it, a component and the parts only it uses - up to `max-specs-per-pulse` (3 unset), only ones next to each other in the same module; a functional spec goes alone only when it is truly independent or very large on its own. Each is shown with its module and its id there, and a number of its own to answer with: a codebase regenerates the functional specs of the modules it is built on too, and each module numbers its own from 1.
174
174
  2. **The definitions each group uses**, in code: the concepts its functional specs name, and the concepts those definitions name in turn. A definition goes with the first group that uses it; later groups have it built. One nothing uses goes with the last.
175
175
  3. **Where each new implementation req goes.** An agent places each with the group it is about - or with the first, when it is about everything (the language, the framework).
176
176
 
177
177
  Each pulse's title says what it does - at most 10 words and 70 characters, as it heads the pulse where the person watches the work. The grouping agent titles its groups; groups no agent made - the conformance tests', and a grouping that fell back - are titled by a third agent, told what each pulse does: what it builds, or, for the conformance tests, what they test. Without it, or when it fails, a pulse is titled by its functional specs' first lines, cut short.
178
178
 
179
- Changes to what is built - an item edited or taken out, a functional spec built worded differently - go first, in a job of their own. Every answer is checked: every new functional spec once, in order, next to each other, at most `max-specs-per-pulse`; every req placed once; every group titled once, within the limit. One that does not hold goes back to its agent, twice at most, and then the plan is a functional spec a job with every req in the first. A group whose functional specs and the definitions they bring pass `max-lines-per-pulse` (120 unset) is split into as few pulses as fit - its functional specs kept together in runs, in order, as long as each run stays within it, `Comments (1 of 2)`, `Comments (2 of 2)` - not a functional spec a job; its reqs do not count, as a split leaves them with its first job whatever happens. The planner runs on the chat's model in a conversation, and on the harness model under `turri regenerate`. No agent reviews its plan: the harness checks it - every change in exactly one job, the spec holding together after each, the last ending on the spec as it is.
179
+ Changes to what is built - an item edited or taken out, a functional spec built worded differently - go first, in a job of their own. Every answer is checked: every new functional spec once, in order, next to each other, at most `max-specs-per-pulse`; every req placed once; every group titled once, within the limit. One that does not hold goes back to its agent, twice at most, and then the plan is a functional spec a job with every req in the first. A group whose functional specs and the definitions they bring pass `max-lines-per-pulse` (120 unset) is split into as few pulses as fit - its functional specs kept together in runs, in order, as long as each run stays within it, `Comments (1 of 2)`, `Comments (2 of 2)` - not a functional spec a job; its reqs do not count, as a split leaves them with its first job whatever happens. The planner runs on the chat's model in a conversation, and on the harness model under `turri regenerate`. No agent reviews its plan: the harness checks it - every change in exactly one job, \*\*\*plain holding together after each, the last ending on \*\*\*plain as it is.
180
180
 
181
181
  Each planned job knows its cases - which functional specs it adds, changes (their text, or a concept they use) and takes out, or none: reqs and definitions only - and the loop says them, with each job's title, where the person looks (`drift`, `pulses`, and what `regenerate` returns).
182
182
 
183
- **Steering.** How you want the work cut and ordered - "build the batch worker's helpers with the worker", "models first" - goes to the grouping and placement agents with every plan, as a strong preference: it never overrides the limits and checks. It comes from three places, each labelled with where it came from: the conversation (`steer`, for the whole project or one module, for the session); the project's `AGENTS.md`, every section whose heading names the queue (`## Queue guidance`), read afresh with every plan; and whatever asks for the work - `regenerate` and `brood`'s `write_spec_diff` take a `guidance` of their own, which the loop keeps with that module.
183
+ **Steering.** How you want the work cut and ordered - "build the batch worker's helpers with the worker", "models first" - goes to the grouping and placement agents with every plan, as a strong preference: it never overrides the limits and checks. It comes from three places, each labelled with where it came from: the conversation (`steer`, for the whole project or one module, for the session); the project's `AGENTS.md`, every section whose heading names the queue (`## Queue guidance`), read afresh with every plan; and whatever asks for the work - `regenerate` and `brood`'s `change_plain` take a `guidance` of their own, which the loop keeps with that module.
184
184
 
185
- A plan is kept until the spec, what it starts from or its steering changes. `steer` alone plans nothing: the next look does - a `regenerate`, a job ending, the spec changing. Then the work not running yet is planned again to follow it, a running job going on as it is. Where a plan did not do as asked, it says so, and what `regenerate` returns lists it under "what the plan did not do as asked": each wish an agent did not follow, with why (both tools take a `notes` for that), a grouping or placement that did not hold, with what was wrong, and a group split for its size. The conversation tells the person that, rather than guessing.
185
+ A plan is kept until \*\*\*plain, what it starts from or its steering changes. `steer` alone plans nothing: the next look does - a `regenerate`, a job ending, \*\*\*plain changing. Then the work not running yet is planned again to follow it, a running job going on as it is. Where a plan did not do as asked, it says so, and what `regenerate` returns lists it under "what the plan did not do as asked": each wish an agent did not follow, with why (both tools take a `notes` for that), a grouping or placement that did not hold, with what was wrong, and a group split for its size. The conversation tells the person that, rather than guessing.
186
186
 
187
- ### When the spec changes
187
+ ### When \*\*\*plain changes
188
188
 
189
- A spec change is a notice, not a diff to run: **`regenerate`**, called after the spec was edited by any means - the file tools, a skill, you in an editor - has the loop work out the work again. A job running goes on while every change it makes is still part of the work, measured from the same record; one that is making something the spec no longer wants is stopped, rolled back, and the work planned again - a fixed rule, no agent. Say a module of 50 functionalities is rendering and the spec changes while functionality 25 builds: 25 goes on if the change leaves it as it is, and the work after it is planned again from what 25 lands. A job stopped so says it was turri, not you, and what changed under it - the functional spec that reads otherwise now, or the file it links that holds something else (`whyNotWanted`).
189
+ A \*\*\*plain change is a notice, not a diff to run: **`regenerate`**, called after \*\*\*plain was edited by any means - the file tools, a skill, you in an editor - has the loop work out the work again. A job running goes on while every change it makes is still part of the work, measured from the same record; one that is making something \*\*\*plain no longer wants is stopped, rolled back, and the work planned again - a fixed rule, no agent. Say a module of 50 functionalities is regenerating and \*\*\*plain changes while functionality 25 builds: 25 goes on if the change leaves it as it is, and the work after it is planned again from what 25 lands. A job stopped so says it was turri, not you, and what changed under it - the functional spec that reads otherwise now, or the file it links that holds something else (`whyNotWanted`).
190
190
 
191
- **A change inside what the running job regenerates steers it** (`steering.ts`), before any of that: a functional spec it regenerates reworded or given a sub-bullet, a definition or an implementation req it is given edited, a file one of them links edited - a change to an item it already has, never an item added or removed. Its coding agent is told, in the same shape as its first change (`describeSpecChange`): in its turn when it is in one, else as its next turn once the step it is at ends - a test run, a review - even when the tests passed or the review approved; edits made before it is told are one steer, the newest of each item. The unit tests run again after it, and a review still to come sees the change as steered, within its two reviews. The job's target moves with it: it lands built from the spec as it was steered to. A definition or req that functional specs built before the job use too is told to the agent but kept out of the record, so those specs - and this job's with them - are patched by the next job. What else changed is the next job's; a change that is partly a steer is split. Two steers a job: a third goes the way above, stopped or - with `allow-to-stop-jobs: false` - left to the next job. Conformance jobs are not steered: they are planned from what the code lands. A steer shows in the job's view in the panel (what it regenerates now), in the transcript (`⇢ steered job …`), under the job in `regenerate`'s answer, and in the job's report.
191
+ **A change inside what the running job regenerates steers it** (`steering.ts`), before any of that: a functional spec it regenerates reworded or given a sub-bullet, a definition or an implementation req it is given edited, a file one of them links edited - a change to an item it already has, never an item added or removed. Its coding agent is told, in the same shape as its first change (`describeSpecChange`): in its turn when it is in one, else as its next turn once the step it is at ends - a test run, a review - even when the tests passed or the review approved; edits made before it is told are one steer, the newest of each item. The unit tests run again after it, and a review still to come sees the change as steered, within its two reviews. The job's target moves with it: it lands built from \*\*\*plain as it was steered to. A definition or req that functional specs built before the job use too is told to the agent but kept out of the record, so those functional specs - and this job's with them - are patched by the next job. What else changed is the next job's; a change that is partly a steer is split. Two steers a job: a third goes the way above, stopped or - with `allow-to-stop-jobs: false` - left to the next job. Conformance jobs are not steered: they are planned from what the code lands. A steer shows in the job's view in the panel (what it regenerates now), in the transcript (`⇢ steered job …`), under the job in `regenerate`'s answer, and in the job's report.
192
192
 
193
- With `allow-to-stop-jobs: false` in `config.turri.yaml` it is not stopped: it runs to its end and lands what it was regenerating, and the next job regenerates what changed since as a patch on top of it. Something lands as soon as it can, and the software evolves job by job - the first build of an integration lands and throws, the next patch fills in what was missing - at the cost of regenerating what the spec has already moved on from. Your own `halt` stops a job either way. `brood`'s `write_spec_diff` makes an edit and gives the notice in one call, and so does `turri spec-diff` on the command line. What is left to regenerate, without regenerating it, is `drift`.
193
+ With `allow-to-stop-jobs: false` in `config.turri.yaml` it is not stopped: it runs to its end and lands what it was regenerating, and the next job regenerates what changed since as a patch on top of it. Something lands as soon as it can, and the software evolves job by job - the first build of an integration lands and throws, the next patch fills in what was missing - at the cost of regenerating what \*\*\*plain has already moved on from. Your own `halt` stops a job either way. `brood`'s `change_plain` makes an edit and gives the notice in one call, and so does `turri change-plain` on the command line. What is left to regenerate, without regenerating it, is `drift`.
194
194
 
195
195
  ### Regenerating a functionality
196
196
 
197
- `regenerate` with functional specs named regenerates them again, changed or not: each is taken out of the record of every codebase it is built in - committed, so the record says it is not built - and they are brought up to their spec, which regenerates it. A functionality whose spec changed needs none of it: `regenerate` regenerates it by itself.
197
+ `regenerate` with functional specs named regenerates them again, changed or not: each is taken out of the record of every codebase it is built in - committed, so the record says it is not built - and they are brought up to their \*\*\*plain, which regenerates it. A functionality whose \*\*\*plain changed needs none of it: `regenerate` regenerates it by itself.
198
198
 
199
199
  `turri regenerate <file.plain> 2` does the same on the command line.
200
200
 
@@ -220,7 +220,7 @@ The `implement-unit-testing-script` and `implement-conformance-testing-script` s
220
220
  2. the root itself: the one `run_unittests*.sh` and `run_conformance_tests*.sh` there;
221
221
  3. `test_scripts/`: the one of each there.
222
222
 
223
- The same `config.turri.yaml` holds the project's other defaults - `module`, `model`, `conformance-tests` - for [unattended runs](headless.md). A folder holding two of a kind is not guessed between: name the one to use in `config.turri.yaml` - or, in a project of stacks, in each stack's own file, and build each module with its stack. A module of such a project built with none says so when it stops: which stacks there are, and which script each names. The scripts are not linked from the specs; a link to one is ignored.
223
+ The same `config.turri.yaml` holds the project's other defaults - `module`, `model`, `conformance-tests` - for [unattended runs](headless.md). A folder holding two of a kind is not guessed between: name the one to use in `config.turri.yaml` - or, in a project of stacks, in each stack's own file, and build each module with its stack. A module of such a project built with none says so when it stops: which stacks there are, and which script each names. The scripts are not linked from \*\*\*plain; a link to one is ignored.
224
224
 
225
225
  They are required: a build with no unit testing script, or with conformance on and no conformance testing script, stops before it starts and says which skill adds it.
226
226
 
@@ -268,13 +268,13 @@ A write the sandbox refused is told apart from a read - a report naming a lock f
268
268
  - **a toolchain or a tool missing** - a JDK, Maven, Go, uv: it looks first for one installed off the PATH - Homebrew's opt folders, `/Library/Java/JavaVirtualMachines`, mise, asdf, sdkman, nvm - then asks you, with the exact command for this machine (`brew install openjdk@21`, `mise use -g java@21`), and on your yes runs it in its shell, checks the command is found now as the testing script would find it, and resumes. One installed where turri's own PATH does not reach needs turri restarted, and it says so. On a no - or where it cannot do it, sudo with a password, a licence - it tells you exactly what to do;
269
269
  - **a credential missing**: never made up - you are told where `agent-env:` reads it from.
270
270
 
271
- Either way the pulse is not tried again: no second run would find what is missing. The message is in the chat, at the end of `turri regenerate`, and in the job's log; after the fix the pulse runs again from the start. The re-run line names the spec that was regenerated, as the folder it was run from reaches it.
271
+ Either way the pulse is not tried again: no second run would find what is missing. The message is in the chat, at the end of `turri regenerate`, and in the job's log; after the fix the pulse runs again from the start. The re-run line names the \*\*\*plain description that was regenerated, as the folder it was run from reaches it.
272
272
 
273
273
  ### What a job is given, and what it records
274
274
 
275
- Every job is a spec diff: the agent that renders it is given the spec the code is built from - its functional specs in `<already implemented>` - and the change to it, in `<spec change>`, section by section - not the raw diff: each of `<definitions>`, `<implementation reqs>` and `<functional specs>` in its own tag, `<definitions change="1 added, 2 changed">`, saying what is added, what changed with its text before and now, and what is removed, measured from what is built to the spec the job ends on. A definition is itself by its concept: one reworded or moved is shown as changed, not as removed and added. Test reqs and acceptance tests are for conformance only: the code record holds neither, and no coding agent is shown them.
275
+ Every job is a \*\*\*plain diff: the agent that regenerates it is given the \*\*\*plain description the code is built from - its functional specs in `<already implemented>` - and the change to it, in `<spec change>`, section by section - not the raw diff: each of `<definitions>`, `<implementation reqs>` and `<functional specs>` in its own tag, `<definitions change="1 added, 2 changed">`, saying what is added, what changed with its text before and now, and what is removed, measured from what is built to the \*\*\*plain description the job ends on. A definition is itself by its concept: one reworded or moved is shown as changed, not as removed and added. Test reqs and acceptance tests are for conformance only: the code record holds neither, and no coding agent is shown them.
276
276
 
277
- **Every part of the spec is given with its module.** A codebase is built from the spec of its whole requires chain, and each module numbers its functional specs from 1, so every agent is shown each section grouped under the module each item belongs to - `<module name="base">`, then `<module name="app" role="current">` - as `<already implemented>` groups the functional specs (`moduleSection`, `functionalitiesByModule` in `prompt.ts`). A module's own items, and what it imports, are the current module's. `<spec change>` names a functional spec as "functionality 2 of module `app`", and a definition or req of a module below with its module; each case line does too ("fs 2 of module `app`"). The primer every agent reads first says that modules are how the [\*\*\*plain](https://plainlang.org/docs/) spec is written, not how the code is laid out: the agent works only in the current module's codebase, which holds the code of every module it requires, and organises the code as the implementation reqs say.
277
+ **Every part of \*\*\*plain is given with its module.** A codebase is built from its whole requires chain's \*\*\*plain, and each module numbers its functional specs from 1, so every agent is shown each section grouped under the module each item belongs to - `<module name="base">`, then `<module name="app" role="current">` - as `<already implemented>` groups the functional specs (`moduleSection`, `functionalitiesByModule` in `prompt.ts`). A module's own items, and what it imports, are the current module's. `<spec change>` names a functional spec as "functionality 2 of module `app`", and a definition or req of a module below with its module; each case line does too ("fs 2 of module `app`"). The primer every agent reads first says that modules are how [\*\*\*plain](https://plainlang.org/docs/) is written, not how the code is laid out: the agent works only in the current module's codebase, which holds the code of every module it requires, and organises the code as the implementation reqs say.
278
278
 
279
279
  It is told, too, what to do with each functional spec the job touches, by its case (`src/regenerate/cases.ts`): a fresh project is set up first, with its unit tests where the unit testing script runs them; a new functional spec is built and unit tested; a changed one - its text, or a concept it uses - is changed in place, its code and tests to match, never built again from scratch; one regenerated again is replaced, not patched - rewritten or started over, what it replaces taken out; one taken out has its code and the tests only it had removed. A job holding several cases has a line for each. A job that touches no functional spec - implementation reqs, or definitions none uses - is mechanical: the code adapts, no new test is written, and an existing one may change only mechanically, never what it asserts. The unit test review holds each part to its case, and a mechanical job only to its reqs and to no test removed or weakened. A conformance job's agent and its reviewer are told the same, for the tests:
280
280
 
@@ -283,44 +283,44 @@ It is told, too, what to do with each functional spec the job touches, by its ca
283
283
  | fresh | the module requires none and nothing is built | set up the project and its unit tests where the unit testing script runs them, then build | set up `tests/` so the conformance testing script, which brings the tests together with `code/`, runs them, then write |
284
284
  | add | a functional spec is new | build it and write its unit tests | write its tests |
285
285
  | patch | its text changed, or a concept it uses did | change the existing code and tests to match - never build it again from scratch | rewrite its existing tests to match |
286
- | again | `regenerate` named it: it is built, and marked in the code record to be regenerated again | replace its implementation - rewrite it or start it over, doing what the spec says now; no second implementation beside the old, nothing of it left unused; its unit tests may be rewritten | its tests were written against the code it replaced: run against the new code, what they check that the spec says stays checked, and what they check that the spec leaves open - a path, a field, a message the old code chose - is rewritten to what the new code does, or taken out |
286
+ | again | `regenerate` named it: it is built, and marked in the code record to be regenerated again | replace its implementation - rewrite it or start it over, doing what \*\*\*plain says now; no second implementation beside the old, nothing of it left unused; its unit tests may be rewritten | its tests were written against the code it replaced: run against the new code, what they check that \*\*\*plain says stays checked, and what they check that \*\*\*plain leaves open - a path, a field, a message the old code chose - is rewritten to what the new code does, or taken out |
287
287
  | delete | a functional spec is gone | take out its code and the tests only it had | take out its tests |
288
288
  | mechanical | no functional spec is touched - only reqs, or definitions none uses | adapt the code; write no new test; an existing one may change only mechanically - an import, a fixture, its setup - never what it asserts | the same, for test reqs, definitions or implementation reqs alone |
289
289
 
290
- **Regenerating again.** `regenerate` with functionalities named regenerates them again though their spec did not change - made better, on another model, after many patches. Each is marked in the code record of every codebase it is built in (`regenerate_again`, committed), and nothing else changes: the record now differs from the spec at that item, so the work loop plans it as it plans any change. A functional spec of a module below is regenerated again where its code lives - the codebase at the tip of each chain built on it, never the module's own codebase left behind - marked among that codebase's required functional specs. The planner groups the ones regenerated again as it groups new ones - up to three a job, only those next to each other in one module together - and the job is given the definitions and implementation reqs as every job is; `<spec change>` lists each under "To regenerate again", with its text as it is now. The job that regenerates it records it as the spec has it, without the mark. Its conformance tests are marked with it, in the tests record of the codebase whose own functional spec it is: they were written against the code being replaced, and may hold the new code to what only the old code chose - `/healthcheck` where the spec says only that there is a health check, and the new code answers `/health`. While the code regenerates they stay as they are; once it lands, the mark is conformance work like any change, and a conformance job writes them again, in the again case above, and runs the whole suite. Until it lands, regen shows its tests as written for an earlier build, and they are not counted as conformance tested.
290
+ **Regenerating again.** `regenerate` with functionalities named regenerates them again though their \*\*\*plain did not change - made better, on another model, after many patches. Each is marked in the code record of every codebase it is built in (`regenerate_again`, committed), and nothing else changes: the record now differs from \*\*\*plain at that item, so the work loop plans it as it plans any change. A functional spec of a module below is regenerated again where its code lives - the codebase at the tip of each chain built on it, never the module's own codebase left behind - marked among that codebase's required functional specs. The planner groups the ones regenerated again as it groups new ones - up to three a job, only those next to each other in one module together - and the job is given the definitions and implementation reqs as every job is; `<spec change>` lists each under "To regenerate again", with its text as it is now. The job that regenerates it records it as \*\*\*plain has it, without the mark. Its conformance tests are marked with it, in the tests record of the codebase whose own functional spec it is: they were written against the code being replaced, and may hold the new code to what only the old code chose - `/healthcheck` where \*\*\*plain says only that there is a health check, and the new code answers `/health`. While the code regenerates they stay as they are; once it lands, the mark is conformance work like any change, and a conformance job writes them again, in the again case above, and runs the whole suite. Until it lands, regen shows its tests as written for an earlier build, and they are not counted as conformance tested.
291
291
 
292
292
  A functional spec is patched when a concept it uses changed as well as when its own text did: the harness follows each functional spec's concepts through the definitions. Fresh is only where nothing exists: a module that requires another starts from what it inherits, and its first job adds or patches.
293
293
 
294
- **Linked resources.** A file the spec links is part of it, so what it holds is compared too: each linked resource is hashed on its own (sha256 of its content) beside its link, in the trees the loop compares and in both records. A change to the file - an API surface `openapi.yaml` defines - changes the item that links it, with no change to the `.plain` text: a functional spec linking it is patched, and a definition linking it patches every functional spec using its concept. The job's diff has a hunk of its own for each such file, under the file's name - shown as a file of its own where the job is shown - saying which item links it, in which spec file (`resources/hubspot/openapi.yaml, linked by :HubSpotRestAPI: in hubspot.plain`), and that its content changed, with both hashes; the agent is told which file holds something else now, beside the item's unchanged text, and reads the file as it is now in `<linked resources>`. The records keep the hash, not the content, so what the file held before is not shown. A record written before resources were hashed is taken as built from the files as they are now: the loop hashes its links and commits it, building nothing again.
294
+ **Linked resources.** A file \*\*\*plain links is part of it, so what it holds is compared too: each linked resource is hashed on its own (sha256 of its content) beside its link, in the trees the loop compares and in both records. A change to the file - an API surface `openapi.yaml` defines - changes the item that links it, with no change to the `.plain` text: a functional spec linking it is patched, and a definition linking it patches every functional spec using its concept. The job's diff has a hunk of its own for each such file, under the file's name - shown as a file of its own where the job is shown - saying which item links it, in which \*\*\*plain file (`resources/hubspot/openapi.yaml, linked by :HubSpotRestAPI: in hubspot.plain`), and that its content changed, with both hashes; the agent is told which file holds something else now, beside the item's unchanged text, and reads the file as it is now in `<linked resources>`. The records keep the hash, not the content, so what the file held before is not shown. A record written before resources were hashed is taken as built from the files as they are now: the loop hashes its links and commits it, building nothing again.
295
295
 
296
296
  **Where a linked resource goes in the code.** A linked resource is not in the agent's workspace; it reaches the agent only in `<linked resources>`. Each text resource is given a `code-copy` - its path, without steps up - and the agent is told that when the code needs what the resource holds while it runs, it keeps exactly one copy there (or where the implementation reqs put such files) and reads it from there, and otherwise copies none, so one file is not written to every place it might be read from.
297
297
 
298
- **Linked images.** A linked `.png`, `.jpg` or `.jpeg` is an image, not text (`resources.ts`). The coding agent and the conformance agent are sent it with their first message - and again after each compaction, which sums the conversation up without its images - and `<linked resources>` lists it with its type and its number among the attachments (`<resource name="checkout mockup" path="resources/checkout.png" type="image/png">`). Their model has to read images: a job whose spec links one refuses a model that does not before any agent starts (`refuseIfModelIsBlind`; `createExecutor` refuses pi's default model the same way), saying which model and to set `coding-model` to one that reads images or describe the image in text. An image over 5 MB stops the job, naming the file. The reviewers do not see linked resources, text or images. An image is hashed like any linked file, so a new mockup patches the functional specs that link it.
298
+ **Linked images.** A linked `.png`, `.jpg` or `.jpeg` is an image, not text (`resources.ts`). The coding agent and the conformance agent are sent it with their first message - and again after each compaction, which sums the conversation up without its images - and `<linked resources>` lists it with its type and its number among the attachments (`<resource name="checkout mockup" path="resources/checkout.png" type="image/png">`). Their model has to read images: a job whose \*\*\*plain links one refuses a model that does not before any agent starts (`refuseIfModelIsBlind`; `createExecutor` refuses [pi](https://pi.dev)'s default model the same way), saying which model and to set `coding-model` to one that reads images or describe the image in text. An image over 5 MB stops the job, naming the file. The reviewers do not see linked resources, text or images. An image is hashed like any linked file, so a new mockup patches the functional specs that link it.
299
299
 
300
- A job lands once its unit tests pass and are reviewed: the code record becomes the spec the job ends on, committed with the code. Its conformance tests are not the code job's: they are a track of their own ([conformance tests in the work loop](#conformance-tests-in-the-work-loop)).
300
+ A job lands once its unit tests pass and are reviewed: the code record becomes the \*\*\*plain description the job ends on, committed with the code. Its conformance tests are not the code job's: they are a track of their own ([conformance tests in the work loop](#conformance-tests-in-the-work-loop)).
301
301
 
302
- A change that renders nothing - definitions moved to a common module, reqs reordered, specs moved between modules of the chain - is recorded, not rendered: the spec is recorded as it is now laid out and committed, with no agent and no testing script. Moving specs into a module the code was not built on is different: no change to the code brings that module's code in, so the codebase stops: it has to be started over - its code and conformance tests taken out, committed so its history keeps them, and the chain built again from the bottom. That is never done unasked. In the chat the model asks the person, saying why, and calls `regenerate` with `from_scratch: "module"` once they agree; `turri regenerate` and `spec-diff` ask at the terminal, and `--start-over` agrees in advance - with no terminal and no flag, the run stops there, exit 1, saying so.
302
+ A change that regenerates nothing - definitions moved to a common module, reqs reordered, \*\*\*plain moved between modules of the chain - is recorded, not regenerated: \*\*\*plain is recorded as it is now laid out and committed, with no agent and no testing script. Moving \*\*\*plain into a module the code was not built on is different: no change to the code brings that module's code in, so the codebase stops: it has to be started over - its code and conformance tests taken out, committed so its history keeps them, and the chain built again from the bottom. That is never done unasked. In the chat the model asks the person, saying why, and calls `regenerate` with `from_scratch: "module"` once they agree; `turri regenerate` and `change-plain` ask at the terminal, and `--start-over` agrees in advance - with no terminal and no flag, the run stops there, exit 1, saying so.
303
303
 
304
304
  ## Conformance tests
305
305
 
306
- The unit tests are written by the agent that wrote the code. Conformance tests are the other half: black box, end to end, written from the spec.
306
+ The unit tests are written by the agent that wrote the code. Conformance tests are the other half: black box, end to end, written from \*\*\*plain.
307
307
 
308
308
  ```bash
309
309
  turri conform <file.plain> # every functional spec the code is built from
310
310
  turri conform <file.plain> 1 3 # functional specs 1 and 3
311
311
  ```
312
312
 
313
- They follow the code: a functional spec gets conformance tests once its code is built. Conformance is off by default: `conformance-tests: all` (or `chosen`, or `module`) in the [config](config.md) turns it on, for modules with `***test reqs***`, and `conform` asks for it in a session. Once a codebase has conformance tests, they are always run and kept passing, whether or not the current render writes new ones, and they are carried up to the modules built on top of it.
313
+ They follow the code: a functional spec gets conformance tests once its code is built. Conformance is off by default: `conformance-tests: all` (or `chosen`, or `module`) in the [config](config.md) turns it on, for modules with `***test reqs***`, and `conform` asks for it in a session. Once a codebase has conformance tests, they are always run and kept passing, whether or not the current regeneration writes new ones, and they are carried up to the modules built on top of it.
314
314
 
315
315
  ### Conformance tests in the work loop
316
316
 
317
- In the work loop, conformance is a track beside the code's. What the conformance tests are written for is recorded apart - `tests/.turri.json`: the functional specs they test, as built, with their acceptance tests, the definitions and implementation reqs they were written against, and the test reqs they follow - and the work is from that record to what they are to be: of the functional specs the code is built from, those chosen - every one, or those `conform` names - as the spec has them, with its test reqs. A functional spec whose code is behind the spec - built from other text, or not in the code record at all, as while `regenerate` regenerates it again by name - keeps its tests until the code lands; they are taken out only once the spec and the code have both dropped it. The harness cuts the work into jobs - an agent only titles them: every functional spec tested - added or changed, asked for by `conform`, chosen, or left by the code jobs - is in one conformance job, a module's own together, as far as a guardrail lets: a new job begins only where the next functional spec would take the job's functional specs and the definitions they bring past 120 lines. The reqs they are written against go with the first job, and do not count. When the person asks for it - one at a time, separately - `conform`'s `one_by_one` (`turri conform --one-by-one`) makes it a job a functional spec instead, until conformance tests are asked for again without it. And when the person asks for them in pulses of their own grouping - 1-3 and 4-6 - `conform`'s `groups` gives each group a job of its own: a job never takes functional specs of two groups, and within a group the guardrail still cuts. Only work that touches no functional spec at all, the test reqs changed say, is a job without one. A module's conformance jobs run on its lane once its code is built - every code job of it landed - so the module is tested once, as built: one explorer, one run of the whole suite, rather than a conformance cycle after each code job; and they pass before anything is built on it. Until then they are not planned, but what is planned lists them last - `conformance tests - planned once the code is built` - wherever they are on for the whole module, so asking for them is seen to have worked; `conform` asked again for a module they are on for already says so, and changes nothing.
317
+ In the work loop, conformance is a track beside the code's. What the conformance tests are written for is recorded apart - `tests/.turri.json`: the functional specs they test, as built, with their acceptance tests, the definitions and implementation reqs they were written against, and the test reqs they follow - and the work is from that record to what they are to be: of the functional specs the code is built from, those chosen - every one, or those `conform` names - as \*\*\*plain has them, with its test reqs. A functional spec whose code is behind \*\*\*plain - built from other text, or not in the code record at all, as while `regenerate` regenerates it again by name - keeps its tests until the code lands; they are taken out only once \*\*\*plain and the code have both dropped it. The harness cuts the work into jobs - an agent only titles them: every functional spec tested - added or changed, asked for by `conform`, chosen, or left by the code jobs - is in one conformance job, a module's own together, as far as a guardrail lets: a new job begins only where the next functional spec would take the job's functional specs and the definitions they bring past 120 lines. The reqs they are written against go with the first job, and do not count. When the person asks for it - one at a time, separately - `conform`'s `one_by_one` (`turri conform --one-by-one`) makes it a job a functional spec instead, until conformance tests are asked for again without it. And when the person asks for them in pulses of their own grouping - 1-3 and 4-6 - `conform`'s `groups` gives each group a job of its own: a job never takes functional specs of two groups, and within a group the guardrail still cuts. Only work that touches no functional spec at all, the test reqs changed say, is a job without one. A module's conformance jobs run on its lane once its code is built - every code job of it landed - so the module is tested once, as built: one explorer, one run of the whole suite, rather than a conformance cycle after each code job; and they pass before anything is built on it. Until then they are not planned, but what is planned lists them last - `conformance tests - planned once the code is built` - wherever they are on for the whole module, so asking for them is seen to have worked; `conform` asked again for a module they are on for already says so, and changes nothing.
318
318
 
319
- A conformance job is a spec diff's conformance run: the tests of its change written, changed or taken out, a failure judged - the test or the code wrong - and fixed, then the whole suite with the unit tests, the tests the module inherits with them. The run that passed already was of the whole suite - the module's tests folder holds the chain's, copied up - so the suite is run once more only when the code or the tests changed after it passed with the unit tests; otherwise it is not run again. Passing, the tests record is written and committed with the tests; otherwise all of it - code fixes included - is rolled back, and the module halts until the spec or the code changes, or `conform` asks again: its conformance tests, its code - nothing more is built on code whose conformance tests did not pass - and every module built on it, which waits.
319
+ A conformance job is a \*\*\*plain diff's conformance run: the tests of its change written, changed or taken out, a failure judged - the test or the code wrong - and fixed, then the whole suite with the unit tests, the tests the module inherits with them. The run that passed already was of the whole suite - the module's tests folder holds the chain's, copied up - so the suite is run once more only when the code or the tests changed after it passed with the unit tests; otherwise it is not run again. Passing, the tests record is written and committed with the tests; otherwise all of it - code fixes included - is rolled back, and the module halts until \*\*\*plain or the code changes, or `conform` asks again: its conformance tests, its code - nothing more is built on code whose conformance tests did not pass - and every module built on it, which waits.
320
320
 
321
321
  **Up the chain.** A module built on another starts from its code and its conformance tests, copied up, and its conformance testing script runs those with its own. So a module waits for the one below it until that one's code is built and its conformance tests - those wanted, chosen or scheduled - are written and pass; only then is its codebase started from there.
322
322
 
323
- **Who chooses, and when.** With `conformance-tests: all` every functional spec is tested, and with `false` none is unless the person asks with `conform`, for the session. With `chosen` or `module`, every one with acceptance tests - the author said what to check - and those the chooser picks: an agent on `harness-model` (or `models: chooser`), in the chat and on the command line alike. It reads the module's spec and names those worth black-box tests - what a user or a client relies on, not a detail the unit tests cover - and why.
323
+ **Who chooses, and when.** With `conformance-tests: all` every functional spec is tested, and with `false` none is unless the person asks with `conform`, for the session. With `chosen` or `module`, every one with acceptance tests - the author said what to check - and those the chooser picks: an agent on `harness-model` (or `models: chooser`), in the chat and on the command line alike. It reads the module's \*\*\*plain and names those worth black-box tests - what a user or a client relies on, not a detail the unit tests cover - and why.
324
324
 
325
325
  - `chosen`: it is asked as each code pulse ends, as the pulse's last stage, of what that pulse regenerated that no conformance test is for.
326
326
  - `module`: it is asked once, when the module's last code pulse lands, of every functional spec of the module that is built and has none - and it plans them too, into groups, each a conformance pulse of its own.
@@ -329,11 +329,11 @@ Either way the choice is made inside the pulse, so it is made - and its conforma
329
329
 
330
330
  **What the person asks for comes first.** `conform` changes the module named alone, never the modules below it. For a module not regenerated yet - one above the module being regenerated, say - its tests are scheduled now and written once its code is built, before anything is built on it. For a module already regenerated whose tests are not written, while a module above it was started from it - its first pulse running, or code of its own built - the codebase above is disposable: a pulse running there is stopped, whatever `allow-to-stop-jobs` says, as the person asked; the codebase is deleted whole, its history with it; the tests are written in the module's own codebase; and the module above is regenerated from it once they pass. Asked for tests it has already, nothing is touched.
331
331
 
332
- **Scheduled ahead of the code.** `conform` may name functional specs whose code is not built yet: each call schedules them as one group, shown at once in what is planned, after the module's last code job. Its functional specs are chosen once the code record has every one as the spec has it, and its tests are written once the module's code is built. A functional spec the spec does not have - built by no code job - or a module with no test reqs is refused, and nothing is scheduled; one taken out of the spec later is dropped from its group. Groups whose code is built by then are tested together, in one job with the rest, as far as the guardrail lets.
332
+ **Scheduled ahead of the code.** `conform` may name functional specs whose code is not built yet: each call schedules them as one group, shown at once in what is planned, after the module's last code job. Its functional specs are chosen once the code record has every one as \*\*\*plain has it, and its tests are written once the module's code is built. A functional spec \*\*\*plain does not have - built by no code job - or a module with no test reqs is refused, and nothing is scheduled; one taken out of \*\*\*plain later is dropped from its group. Groups whose code is built by then are tested together, in one job with the rest, as far as the guardrail lets.
333
333
 
334
334
  While a codebase's work is being planned into jobs, with nothing running there, what is planned says so - the conformance tests of the groups being planned, or the work - rather than showing nothing until the plan is made.
335
335
 
336
- **What a conformance job tests is built.** As a conformance job starts, the harness reads the code record, `code/.turri.json`, and checks that it has every functional spec the job adds or changes tests for, as the job has it. One it does not have stops the job before any agent runs: its report says which are not built, the conformance tests halt, and the chat model tells the person. They are tried again once the code or the spec changes. Code jobs and conformance jobs are planned apart, each track on its own: a job is one or the other. A module built on another starts with an empty tests record: the tests it inherits are the module below's, and none of its own is written yet.
336
+ **What a conformance job tests is built.** As a conformance job starts, the harness reads the code record, `code/.turri.json`, and checks that it has every functional spec the job adds or changes tests for, as the job has it. One it does not have stops the job before any agent runs: its report says which are not built, the conformance tests halt, and the chat model tells the person. They are tried again once the code or \*\*\*plain changes. Code jobs and conformance jobs are planned apart, each track on its own: a job is one or the other. A module built on another starts with an empty tests record: the tests it inherits are the module below's, and none of its own is written yet.
337
337
 
338
338
  ### Conformance tests and acceptance tests, kept apart
339
339
 
@@ -342,40 +342,40 @@ The step writes two kinds of test, and never lets one stand in for the other:
342
342
  | | Written from | Labelled |
343
343
  | --- | --- | --- |
344
344
  | Conformance tests | the functional spec itself - what it says the functionality does, its edge cases, its errors - as if no acceptance tests had been given | files whose names say conformance, each starting with a comment `conformance tests of functionality 3` |
345
- | Acceptance tests | each acceptance test in the spec, implemented as a test of its own, doing what it says | files whose names say acceptance, each test with a comment `acceptance test 2 of functionality 3:` and the acceptance test's text |
345
+ | Acceptance tests | each acceptance test in \*\*\*plain, implemented as a test of its own, doing what it says | files whose names say acceptance, each test with a comment `acceptance test 2 of functionality 3:` and the acceptance test's text |
346
346
 
347
- Even when the acceptance tests seem to cover the functionality, the conformance tests are written independently: tests drawn only from the acceptance tests check what the author thought to check, and nothing the spec says beyond that. The acceptance tests reach the agent numbered, as their labels number them.
347
+ Even when the acceptance tests seem to cover the functionality, the conformance tests are written independently: tests drawn only from the acceptance tests check what the author thought to check, and nothing \*\*\*plain says beyond that. The acceptance tests reach the agent numbered, as their labels number them.
348
348
 
349
- The labels are checked, not trusted: before a passing run counts, the harness reads the tests and sends the agent back for a functionality with no labelled conformance tests, or for any acceptance test that has no test of its own. Each functionality has a label of its own, on a line of its own: a file that tests several carries one line for each, and a label naming several at once - `conformance tests of functionality 1, 2 and 3` - counts for the first alone. For a spec change that touches several functionalities, everything missing - every functionality's - is asked for in one request, the agent told to keep the labels there already, and the whole set checked again after each answer. Anyone reading the tests - or the next agent - sees at a glance which is which, and which acceptance test a test implements.
349
+ The labels are checked, not trusted: before a passing run counts, the harness reads the tests and sends the agent back for a functionality with no labelled conformance tests, or for any acceptance test that has no test of its own. Each functionality has a label of its own, on a line of its own: a file that tests several carries one line for each, and a label naming several at once - `conformance tests of functionality 1, 2 and 3` - counts for the first alone. For a \*\*\*plain change that touches several functionalities, everything missing - every functionality's - is asked for in one request, the agent told to keep the labels there already, and the whole set checked again after each answer. Anyone reading the tests - or the next agent - sees at a glance which is which, and which acceptance test a test implements.
350
350
 
351
- ### Rendered apart from the code
351
+ ### Regenerated apart from the code
352
352
 
353
- The code and its conformance tests are rendered apart, each in its own folder (see [the sandbox](sandbox.md#what-an-agent-can-reach)). The test author writes only the tests folder; its file tools can read the code too, and it is told so - read access, never write access - and to take how the software is reached from the code, never what it should do. Its shell holds the tests folder only. The coding agent that fixes the code is told the same of the tests: it can read them, never change them. Before the test author starts, an explorer - an agent in the code's folder with the file tools alone: it reads the code, runs nothing and changes nothing - hands over everything the author needs, in parts: how to build and run it; how the conformance tests reach it as the project's conformance testing script runs them - the explorer is given the script, and the prepare script before it where there is one, and says what they build or installs and what the tests depend on or start (a package, a module, an entry point, by its exact name); how each functionality is reached from outside (the command, or the route, method and the request and response fields); what it needs around it; and a plan for the conformance tests, its expectations taken from the spec. The account is checked before it is used: it has to say how the functionality under test is reached and what to test for it (for a spec diff, some of the module the change touches), and the plan has to carry out every acceptance test of it (for a spec diff, of every functionality the change touches), each named "acceptance test N", with how each of its steps is done from outside and what it asserts. One that does not is sent back saying what is missing. It is kept focused: the interface to what is under test, not a survey of the codebase, in words rather than code, under 12,000 characters. Each hand-over ends its turn, and it hands over three times at most. If it never completes it, what it wrote as it worked goes along with it, so nothing it found is lost. The tests are written from that account and the spec, and every assertion comes from the spec. `run_conformance_tests` puts the whole suite together with a copy of the build in a throwaway directory, so tests cannot accumulate state between attempts and nothing they write reaches the code.
353
+ The code and its conformance tests are regenerated apart, each in its own folder (see [the sandbox](sandbox.md#what-an-agent-can-reach)). The test author writes only the tests folder; its file tools can read the code too, and it is told so - read access, never write access - and to take how the software is reached from the code, never what it should do. Its shell holds the tests folder only. The coding agent that fixes the code is told the same of the tests: it can read them, never change them. Before the test author starts, an explorer - an agent in the code's folder with the file tools alone: it reads the code, runs nothing and changes nothing - hands over everything the author needs, in parts: how to build and run it; how the conformance tests reach it as the project's conformance testing script runs them - the explorer is given the script, and the prepare script before it where there is one, and says what they build or installs and what the tests depend on or start (a package, a module, an entry point, by its exact name); how each functionality is reached from outside (the command, or the route, method and the request and response fields); what it needs around it; and a plan for the conformance tests, its expectations taken from \*\*\*plain. The account is checked before it is used: it has to say how the functionality under test is reached and what to test for it (for a \*\*\*plain diff, some of the module the change touches), and the plan has to carry out every acceptance test of it (for a \*\*\*plain diff, of every functionality the change touches), each named "acceptance test N", with how each of its steps is done from outside and what it asserts. One that does not is sent back saying what is missing. It is kept focused: the interface to what is under test, not a survey of the codebase, in words rather than code, under 12,000 characters. Each hand-over ends its turn, and it hands over three times at most. If it never completes it, what it wrote as it worked goes along with it, so nothing it found is lost. The tests are written from that account and \*\*\*plain, and every assertion comes from \*\*\*plain. `run_conformance_tests` puts the whole suite together with a copy of the build in a throwaway directory, so tests cannot accumulate state between attempts and nothing they write reaches the code.
354
354
 
355
355
  While it writes the tests, the conformance agent can put a question to the explorer - `ask_explorer`, three times a run: how a functionality is reached, what a field is called. A fresh explorer, in the code's folder, given the account it handed over and the question, reads the code and answers in words; it runs and changes nothing. And `my_diff` shows it the tests folder's diff from where the run started, as its reviewer is shown it.
356
356
 
357
357
  ### When a conformance test fails
358
358
 
359
- The harness runs the project's conformance testing script on the whole suite. When it passes, the unit testing script runs too - and then, with `review: true` in the config, the review gate: a reviewer reads the tests this run added or changed, and the code, and checks that they test black box - through the entry points the test reqs allow, never mocking or replacing any part of the software under test - that every test asserts what the spec says, with no placeholder that cannot fail, and that each acceptance test does every step it lists and asserts every expectation it states. It must pass, as the suite and the unit tests must: when it does not, the conformance agent gets exactly what is missing and what is bad, file by file, and the round goes again. One reviewer does every review of the run, as the unit tests' does: the first time it is shown the diff of the tests folder from the module's last commit, each time after the diff since its last review, and every time the conformance agent's account through `submit_work` - checked against the diff, never taken instead of it. The first review is asked for every problem at once; each after it is given what the last one found, checks that first, and raises something new only when it is serious - a test that cannot fail, mocks the software, or leaves out what the spec asks for. It asks only for what can be seen from outside: where the spec says one part calls another, the outcome, never the call. The reviewer is the exacting developer, as the unit tests' is, and marks each problem blocking or not: blocking when the functionality is not yet tested black box - a test or an acceptance test missing, cut down or skipping what it checks, the software mocked or not reached from outside, a test that cannot fail.
359
+ The harness runs the project's conformance testing script on the whole suite. When it passes, the unit testing script runs too - and then, with `review: true` in the config, the review gate: a reviewer reads the tests this run added or changed, and the code, and checks that they test black box - through the entry points the test reqs allow, never mocking or replacing any part of the software under test - that every test asserts what \*\*\*plain says, with no placeholder that cannot fail, and that each acceptance test does every step it lists and asserts every expectation it states. It must pass, as the suite and the unit tests must: when it does not, the conformance agent gets exactly what is missing and what is bad, file by file, and the round goes again. One reviewer does every review of the run, as the unit tests' does: the first time it is shown the diff of the tests folder from the module's last commit, each time after the diff since its last review, and every time the conformance agent's account through `submit_work` - checked against the diff, never taken instead of it. The first review is asked for every problem at once; each after it is given what the last one found, checks that first, and raises something new only when it is serious - a test that cannot fail, mocks the software, or leaves out what \*\*\*plain asks for. It asks only for what can be seen from outside: where \*\*\*plain says one part calls another, the outcome, never the call. The reviewer is the exacting developer, as the unit tests' is, and marks each problem blocking or not: blocking when the functionality is not yet tested black box - a test or an acceptance test missing, cut down or skipping what it checks, the software mocked or not reached from outside, a test that cannot fail.
360
360
 
361
361
  The tests are reviewed twice at most, as the unit tests are: the first review that sends them back goes to the conformance agent as it is, and the second the arbiter weighs first, as it does the unit tests' (see [the code and its unit tests are reviewed](#the-code-and-its-unit-tests-are-reviewed)): it upholds what leaves the functionality not tested black box, and dismisses what is out of scope or a nitpick. Only what it upholds goes back to the conformance agent; when it upholds nothing, the tests are approved as they are, and what it let go is kept in the result and the notes' pitfalls. The review optimises the tests, it does not stop the run: what the second review sends back is worked on once, and then the tests go on without another review - once the suite and the unit tests pass, which they still must. All three passing is done.
362
362
 
363
- A spec diff's conformance run holds its tests to the same bar. The functionalities the change touches - a line of their functional spec, or of one of their acceptance tests, added or removed - are worked out from the diff. The conformance agent is shown their acceptance tests, numbered as they are labelled; the run does not finish until each one is a labelled test of its own; and the review checks each of them as it would a functionality's own.
363
+ A \*\*\*plain diff's conformance run holds its tests to the same bar. The functionalities the change touches - a line of their functional spec, or of one of their acceptance tests, added or removed - are worked out from the diff. The conformance agent is shown their acceptance tests, numbered as they are labelled; the run does not finish until each one is a labelled test of its own; and the review checks each of them as it would a functionality's own.
364
364
 
365
365
  A failing run's output goes to the judge and whoever fixes it whole when it is up to 60,000 characters, and otherwise its last 60,000 - where a test run says what failed and why - with the file the whole of it is kept in.
366
366
 
367
- Why something failed is never lost. Every agent that writes or fixes code is told that where the code catches an error and turns it into a response, a status, a result or a retry, it logs the error with its whole trace, and what it hands on names the cause - never a bare "failed". When the output does not show why the software failed, the judge says the code is what is wrong, for hiding it, and the coding agent makes the cause show first, then fixes it. No agent may make the code behave differently when a test runs it. Both the conformance agent and the coding agent can run the conformance suite themselves, to reproduce a failure and check their fix - three times a turn: the third ends the turn, and the harness runs it and judges. The conformance agent is told that a failure of the software itself - it does not build or start, or does what the spec says it must not - is not the tests' to work around. When it fails, a judge - an agent that reads the code and the tests, changes neither, and holds both to the spec - decides which is wrong. It has the file tools and the web (`web_search`, `web_fetch`), to look up what a service the code calls answers - no shell: it judges from the code, the tests, the spec, the conformance testing script word for word and the failing run's output, and its file tools write nothing. The explorer's account of how the code is invoked is in its prompt too, marked as written before the run and possibly wrong: the judge checks what it uses of it against the script and the files, and gives in `evidence` what it found itself. The script is fixed - neither agent can change it - so it is never the culprit: what it does with the tests, the tests fit; what it needs of the build, the code provides.
367
+ Why something failed is never lost. Every agent that writes or fixes code is told that where the code catches an error and turns it into a response, a status, a result or a retry, it logs the error with its whole trace, and what it hands on names the cause - never a bare "failed". When the output does not show why the software failed, the judge says the code is what is wrong, for hiding it, and the coding agent makes the cause show first, then fixes it. No agent may make the code behave differently when a test runs it. Both the conformance agent and the coding agent can run the conformance suite themselves, to reproduce a failure and check their fix - three times a turn: the third ends the turn, and the harness runs it and judges. The conformance agent is told that a failure of the software itself - it does not build or start, or does what \*\*\*plain says it must not - is not the tests' to work around. When it fails, a judge - an agent that reads the code and the tests, changes neither, and holds both to \*\*\*plain - decides which is wrong. It has the file tools and the web (`web_search`, `web_fetch`), to look up what a service the code calls answers - no shell: it judges from the code, the tests, \*\*\*plain, the conformance testing script word for word and the failing run's output, and its file tools write nothing. The explorer's account of how the code is invoked is in its prompt too, marked as written before the run and possibly wrong: the judge checks what it uses of it against the script and the files, and gives in `evidence` what it found itself. The script is fixed - neither agent can change it - so it is never the culprit: what it does with the tests, the tests fit; what it needs of the build, the code provides.
368
368
 
369
- - **the code:** the coding agent - in the code's folder, reading the tests but never changing them - fixes it, and keeps its unit tests passing. The judge quotes the spec's own words the code does not meet, or the testing script's for what it needs of the build (`script_needs`: a build output, an entry point, a module) - each checked by the harness against the text it quotes. The acceptance tests are in that text, labelled as their tests are: for a spec change, those of every functional spec it touches, not only the last one's;
370
- - **the tests:** the conformance agent corrects them to what the spec says;
371
- - **the spec:** two functional specs cannot both hold, whatever the code does;
372
- - **the environment:** neither the code nor the tests can fix it - only the person can, in what the run is given: a credential missing, empty or rejected (a 401 from a provider for a token no test made up), an account or quota a service refuses, a service the spec names that cannot be reached. What a test sets up itself - a credential, a variable, a fixture - is the tests'.
369
+ - **the code:** the coding agent - in the code's folder, reading the tests but never changing them - fixes it, and keeps its unit tests passing. The judge quotes \*\*\*plain's own words the code does not meet, or the testing script's for what it needs of the build (`script_needs`: a build output, an entry point, a module) - each checked by the harness against the text it quotes. The acceptance tests are in that text, labelled as their tests are: for a \*\*\*plain change, those of every functional spec it touches, not only the last one's;
370
+ - **the tests:** the conformance agent corrects them to what \*\*\*plain says;
371
+ - **\*\*\*plain:** two functional specs cannot both hold, whatever the code does;
372
+ - **the environment:** neither the code nor the tests can fix it - only the person can, in what the run is given: a credential missing, empty or rejected (a 401 from a provider for a token no test made up), an account or quota a service refuses, a service \*\*\*plain names that cannot be reached. What a test sets up itself - a credential, a variable, a fixture - is the tests'.
373
373
 
374
374
  The environment is judged what is wrong twice in a row before it counts. The first time, the conformance agent checks that the tests do not cause it themselves and, when they do not, changes nothing; the second, the run stops, and the person is told what to provide and where the run read it from - the testing scripts run in their own environment, so a credential comes from their shell's variables or a `.env` the script loads.
375
375
 
376
- When the code and the tests could both be wrong, the judge is told to choose the tests. A spec conflict has to name the two functionalities, each by its module and id - they can be in different modules, since a module's codebase and its conformance suite hold the functionalities of the modules it requires too (functionality 1 of `accounts` and functionality 4 of `cognio`). In a functionality's conformance run one of them must be the functionality under test - a conflict between two earlier ones would have come up when the later of them was tested (a spec diff's run may name any two). One that breaks these rules is sent back to the judge. A valid one is recorded, and the tests go back to the conformance agent, so the next judgement is of a new run. It counts only once the same two functionalities have been named three times. Then the run stops, and the person gets the conflict whole: both functional specs as they read, and each time what could not hold. The conversation's agent runs `analyze-2-func-specs` on the pair, then `resolve-spec-conflict` for the ways out, and puts the decision to the person - it changes nothing in the spec before they have decided.
376
+ When the code and the tests could both be wrong, the judge is told to choose the tests. A \*\*\*plain conflict has to name the two functionalities, each by its module and id - they can be in different modules, since a module's codebase and its conformance suite hold the functionalities of the modules it requires too (functionality 1 of `accounts` and functionality 4 of `cognio`). In a functionality's conformance run one of them must be the functionality under test - a conflict between two earlier ones would have come up when the later of them was tested (a \*\*\*plain diff's run may name any two). One that breaks these rules is sent back to the judge. A valid one is recorded, and the tests go back to the conformance agent, so the next judgement is of a new run. It counts only once the same two functionalities have been named three times. Then the run stops, and the person gets the conflict whole: both functional specs as they read, and each time what could not hold. The conversation's agent runs `analyze-2-func-specs` on the pair, then `resolve-spec-conflict` for the ways out, and puts the decision to the person - it changes nothing in \*\*\*plain before they have decided.
377
377
 
378
- The judge holds only what the spec says against the code: anything it leaves open - a name, coordinates, a version, a path, a package - is what the code already has, and the tests follow it. The coding agents keep the build's identity - name, coordinates, version, package, main class - as it is unless the spec asks for another. And the conformance agent is given the code's build files (`pom.xml`, `package.json`, `pyproject.toml`, `go.mod`...) word for word, read by the harness: the one place to take what its tests' build points at from, never a guess from a folder name.
378
+ The judge holds only what \*\*\*plain says against the code: anything it leaves open - a name, coordinates, a version, a path, a package - is what the code already has, and the tests follow it. The coding agents keep the build's identity - name, coordinates, version, package, main class - as it is unless \*\*\*plain asks for another. And the conformance agent is given the code's build files (`pom.xml`, `package.json`, `pyproject.toml`, `go.mod`...) word for word, read by the harness: the one place to take what its tests' build points at from, never a guess from a folder name.
379
379
 
380
380
  When nothing changes - the same failure seen three times in the run, in a row or not, so a run swinging between two failures counts too (runs that hang until the time limit count as well) - the explorer is asked again, shown its last account and the failure, for what the tests lack; most often it is how they reach the software. Its new account goes to the conformance agent. If the same happens three rounds more, the run stops and says so, instead of spending the rest of its 20 attempts on it. Two failures are the same once what changes from run to run is taken out of their lines - numbers, times, paths, colour codes, and the ids a service makes up for each response, a UUID or a correlation id. Nothing changes either when the agent sent to fix the code or the tests changes no file: two such fixes in a row, and the run stops. The conformance agent has the testing script in its prompt, and is told to fit the tests' own build to it. The code fixer has the testing scripts its fixes are run by - the conformance testing script, the prepare script before it, and the unit testing script - word for word in its task: what the conformance testing script needs of the build, it reads there, not only in the judge's quote of it.
381
381
 
@@ -391,11 +391,11 @@ Before each run the harness checks for itself: both kinds of test are there and
391
391
 
392
392
  Conformance and acceptance tests live in the module's `tests` folder and nowhere else. One found in the code folder - by its label, or as a test file under a name or folder that says conformance or acceptance - is sent back: to the agent writing the tests, to move it; to an agent writing the code, to remove it, since those tests are not its to write. The conformance testing script refuses them too (see `implement-conformance-testing-script`), so a suite in the wrong place fails rather than passing unnoticed.
393
393
 
394
- No agent runs the testing scripts itself. They are in its prompt so it knows what judges its work, but they are not in its workspace: it calls `run_unit_tests` and `run_conformance_tests`, which run them as the harness does. Its file tools refuse to write a copy of them, or a `.plain` spec, into the codebase, and its working notes refuse a line telling the next agent to run them.
394
+ No agent runs the testing scripts itself. They are in its prompt so it knows what judges its work, but they are not in its workspace: it calls `run_unit_tests` and `run_conformance_tests`, which run them as the harness does. Its file tools refuse to write a copy of them, or a `.plain` file, into the codebase, and its working notes refuse a line telling the next agent to run them.
395
395
 
396
396
  ### Verified
397
397
 
398
- After rendering a hello-world Python spec's functionality 1, the conformance test runs the app as a subprocess and asserts on stdout, exit code and time - no import of internals:
398
+ After regenerating functionality 1 of a hello-world Python \*\*\*plain, the conformance test runs the app as a subprocess and asserts on stdout, exit code and time - no import of internals:
399
399
 
400
400
  ```python
401
401
  completed = subprocess.run([sys.executable, str(executable)], capture_output=True, text=True, timeout=1)
@@ -407,23 +407,23 @@ Code that prints `goodbye` instead fails the test; the agent fixes the code, and
407
407
 
408
408
  ## Agent sessions
409
409
 
410
- An agent's task - the spec, how to read it, what to do, the rules, the working notes as they were - is its **system prompt**, not its first message: every agent turri starts opens with a one-line "begin". Compaction sums up the conversation and never the system prompt, so however long an agent works, what it works from stays word for word as it was, and stays in the cached prefix of every call. The one exception is a skill's executor, which is given a step at a time.
410
+ An agent's task - its \*\*\*plain, how to read it, what to do, the rules, the working notes as they were - is its **system prompt**, not its first message: every agent turri starts opens with a one-line "begin". Compaction sums up the conversation and never the system prompt, so however long an agent works, what it works from stays word for word as it was, and stays in the cached prefix of every call. The one exception is a skill's executor, which is given a step at a time.
411
411
 
412
- The agents that work through a job keep **one session for it**: the coding agent of a render or a spec change, its unit test reviewer, the conformance agent, its test reviewer, the code fixer of a conformance run, and the regression repair agent. The code fixer used to start fresh for every fix; now each fix starts from what the ones before it tried. The agents whose value is having taken no side stay fresh, given what they need as text: the arbiter, the judge that says whether the code, the tests or the spec is wrong, the explorer, the planners, the diagnosis and a skill's review judges. A job that fails and is retried is undone whole, and every agent of the retry starts fresh.
412
+ The agents that work through a job keep **one session for it**: the coding agent of a regeneration or a \*\*\*plain change, its unit test reviewer, the conformance agent, its test reviewer, the code fixer of a conformance run, and the regression repair agent. The code fixer used to start fresh for every fix; now each fix starts from what the ones before it tried. The agents whose value is having taken no side stay fresh, given what they need as text: the arbiter, the judge that says whether the code, the tests or \*\*\*plain is wrong, the explorer, the planners, the diagnosis and a skill's review judges. A job that fails and is retried is undone whole, and every agent of the retry starts fresh.
413
413
 
414
- An agent kept through a job re-reads everything it has done on every call. So between turns, once its conversation - what it has done, past its instructions - passes `compact-at` tokens (100,000 unless [the project config](config.md) says otherwise), the harness compacts it, with instructions for its role: the coding agent and the fixer keep what is done, what still fails and why, the decisions and every review problem's fate; a reviewer keeps every problem it raised and where each stands, and what it has already checked. pi's own compaction, when the context window is nearly full, stays on beneath it.
414
+ An agent kept through a job re-reads everything it has done on every call. So between turns, once its conversation - what it has done, past its instructions - passes `compact-at` tokens (100,000 unless [the project config](config.md) says otherwise), the harness compacts it, with instructions for its role: the coding agent and the fixer keep what is done, what still fails and why, the decisions and every review problem's fate; a reviewer keeps every problem it raised and where each stands, and what it has already checked. [pi](https://pi.dev)'s own compaction, when the context window is nearly full, stays on beneath it.
415
415
 
416
416
  What each agent of a job did - its turns, its compactions, its tokens and cost - is at the end of the job's log in `.turri/jobs/` (kept in [debug mode](config.md#debug-mode)), and in `pulses`.
417
417
 
418
418
  ## Working notes
419
419
 
420
- Every job's agents start fresh, and without help each one would spend its first turns finding its bearings. So each agent working on a codebase - render, spec change, conformance, regression repair - starts with the notes the agents before it left, and before it finishes it updates them: a line added, changed or removed, never the whole thing rewritten. There are two sets: the code's, in `code/`, for the agents that change the code, and the conformance tests', in `tests/`, for the conformance agent. What one learns of testing the module black box - where the tests are, what they assume - would steer a coding agent towards the tests rather than the spec, so it is never in the code's notes; the judge, which weighs the tests against the code, reads both. Each set goes where its folder goes - copied up the chain, committed, rolled back. Six sections:
420
+ Every job's agents start fresh, and without help each one would spend its first turns finding its bearings. So each agent working on a codebase - regenerate, \*\*\*plain change, conformance, regression repair - starts with the notes the agents before it left, and before it finishes it updates them: a line added, changed or removed, never the whole thing rewritten. There are two sets: the code's, in `code/`, for the agents that change the code, and the conformance tests', in `tests/`, for the conformance agent. What one learns of testing the module black box - where the tests are, what they assume - would steer a coding agent towards the tests rather than \*\*\*plain, so it is never in the code's notes; the judge, which weighs the tests against the code, reads both. Each set goes where its folder goes - copied up the chain, committed, rolled back. Six sections:
421
421
 
422
422
  | | |
423
423
  | --- | --- |
424
424
  | Where things are | entry points, layout, where each functionality lives |
425
425
  | How to build, run and test | the commands that work, what had to be installed |
426
- | Assumptions | what an agent assumed where the spec is silent - a format, a default, a choice it leaves open - and the tests that assert it, when any do; one no test asserts is written down all the same |
426
+ | Assumptions | what an agent assumed where \*\*\*plain is silent - a format, a default, a choice it leaves open - and the tests that assert it, when any do; one no test asserts is written down all the same |
427
427
  | Pitfalls | what went wrong and what fixed it - and what the debugger found, filed by turri itself |
428
428
  | Pulses | written by turri alone, as each pulse ends: the last ten, a line each |
429
429
 
@@ -436,9 +436,9 @@ A pulse's line says what it regenerated, whether it landed, how it went - the ro
436
436
 
437
437
  It is written once anything the pulse did not land is rolled back, and committed - into the pulse's own commit when it landed, a commit of its own (`pulse 3 rolled back: …`) when it did not - so the next pulse, starting from the last commit, keeps it. `update_notes` refuses the section. What the debugger finds is filed in the pitfalls the moment it finds it, not left to the coding agent to write down.
438
438
 
439
- A spec gap - what the spec should say and does not, a behaviour you would want to decide - is not a note: the notes are the next agent's, and a gap is yours. An agent reports one with `report_spec_gap`, giving the question it leaves and the assumption it made meanwhile; turri writes that assumption into the notes' assumptions, so the code built on it is known for what it is. The gaps a pulse's agents report are said in its report - "Spec gaps its agents met ... Put each to the user", each with its assumption - so the conversation asks you, and writes the ones you decide into the spec; the pulse that builds the answer finds the assumption it replaces in the notes, and the tests it names. A headless run has no one to ask: it prints each gap under its pulse, and lists them in its run report's `spec_gaps` ([running unattended](headless.md#the-run-report)). However many gaps a pulse's agents report, they are put to you - never a reason to stop the pulse; the tool is guarded like any other. A notes file from before keeps no spec gaps section: its lines are dropped as it is read.
439
+ A \*\*\*plain gap - what \*\*\*plain should say and does not, a behaviour you would want to decide - is not a note: the notes are the next agent's, and a gap is yours. An agent reports one with `report_spec_gap`, giving the question it leaves and the assumption it made meanwhile; turri writes that assumption into the notes' assumptions, so the code built on it is known for what it is. The gaps a pulse's agents report are said in its report - "Spec gaps its agents met ... Put each to the user", each with its assumption - so the conversation asks you, and writes the ones you decide into \*\*\*plain; the pulse that builds the answer finds the assumption it replaces in the notes, and the tests it names. A headless run has no one to ask: it prints each gap under its pulse, and lists them in its run report's `spec_gaps` ([running unattended](headless.md#the-run-report)). However many gaps a pulse's agents report, they are put to you - never a reason to stop the pulse; the tool is guarded like any other. A notes file from before keeps no section of gaps: its lines are dropped as it is read.
440
440
 
441
- Stubborn on the specs, flexible on the assumptions: the spec is never an assumption and never copied into the notes, and where the two disagree the spec wins. An agent builds on the assumptions already there, and changes one the moment the code or the spec shows it wrong.
441
+ Stubborn on \*\*\*plain, flexible on the assumptions: \*\*\*plain is never an assumption and never copied into the notes, and where the two disagree \*\*\*plain wins. An agent builds on the assumptions already there, and changes one the moment the code or \*\*\*plain shows it wrong.
442
442
 
443
443
  Every line says when and where it came from, stamped by the harness rather than written by the agent:
444
444
 
@@ -461,14 +461,14 @@ Two records per module, each committed with what it describes in the module's `.
461
461
 
462
462
  | | |
463
463
  | --- | --- |
464
- | `code/.turri.json` | the code record: the spec the code is built from - its whole requires chain's: the definitions and implementation reqs of the modules below, each tagged with its module, their functional specs among the ones it inherits, and its own - without the test reqs and the acceptance tests, which are for conformance only |
464
+ | `code/.turri.json` | the code record: the \*\*\*plain description the code is built from - its whole requires chain's: the definitions and implementation reqs of the modules below, each tagged with its module, their functional specs among the ones it inherits, and its own - without the test reqs and the acceptance tests, which are for conformance only |
465
465
  | `tests/.turri.json` | the tests record: the functional specs the conformance tests are written for - of the code record's, with their acceptance tests - the definitions and implementation reqs they were written against, and the test reqs they follow |
466
466
 
467
- Nothing about how a build went: whether tests passed and which files a job touched are in the history, and how each pulse went is in the [ledger](using.md#the-ledger), which nothing reads to decide what to build. And nothing else is stored: what is left to build is worked out from the records whenever a job ends or the spec changes - the code work from the code record to the spec now (`src/regenerate/drift.ts`), the conformance work from the tests record to what the tests are to be written for. Only the running job is kept; what the panel shows as planned is worked out again. The tests record never goes ahead of the code's: a conformance test exercises functionality, and only what is in the code can be tested.
467
+ Nothing about how a build went: whether tests passed and which files a job touched are in the history, and how each pulse went is in the [ledger](using.md#the-ledger), which nothing reads to decide what to build. And nothing else is stored: what is left to build is worked out from the records whenever a job ends or \*\*\*plain changes - the code work from the code record to \*\*\*plain now (`src/regenerate/drift.ts`), the conformance work from the tests record to what the tests are to be written for. Only the running job is kept; what the panel shows as planned is worked out again. The tests record never goes ahead of the code's: a conformance test exercises functionality, and only what is in the code can be tested.
468
468
 
469
469
  What goes into them:
470
470
 
471
- - **A code job landed:** the code record becomes the spec the job ends on.
471
+ - **A code job landed:** the code record becomes the \*\*\*plain description the job ends on.
472
472
  - **A conformance job landed:** the tests record becomes what its tests are written for.
473
473
  - **A module started from another's code:** that code's record, as a lower module's - see [where things go](#where-things-go) - and an empty tests record: the tests it inherits are the module below's.
474
474
  - **A functional spec named to `regenerate`:** it is marked to be regenerated again in the code record, so the next job regenerates it again; that job's record drops the mark. Its conformance tests, when it has them, are marked in the tests record too, and the conformance job that writes them again for the new code drops that mark.