@turri-dev/cli 0.1.18 → 0.1.19-next.ee6bc61
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.
- package/dist/chat-terminal.js +4 -0
- package/dist/chat-waiting.d.ts +64 -0
- package/dist/chat-waiting.js +86 -0
- package/dist/chats.d.ts +2 -0
- package/dist/chats.js +1 -0
- package/dist/extension.js +36 -2
- package/dist/genome.d.ts +12 -0
- package/dist/genome.js +17 -0
- package/dist/new-project.js +1 -1
- package/dist/pi-launch.js +7 -4
- package/dist/regenerate/conformance-agents.d.ts +6 -2
- package/dist/regenerate/conformance-agents.js +40 -14
- package/dist/regenerate/conformance.d.ts +0 -8
- package/dist/regenerate/conformance.js +17 -14
- package/dist/regenerate/debugger.d.ts +5 -0
- package/dist/regenerate/debugger.js +21 -2
- package/dist/regenerate/environment-error.d.ts +25 -0
- package/dist/regenerate/environment-error.js +46 -0
- package/dist/regenerate/job-panel.d.ts +2 -2
- package/dist/regenerate/job-panel.js +12 -11
- package/dist/regenerate/jobs-tree.d.ts +1 -1
- package/dist/regenerate/jobs-tree.js +5 -6
- package/dist/regenerate/jobs.d.ts +4 -0
- package/dist/regenerate/jobs.js +24 -0
- package/dist/regenerate/ledger-view.d.ts +11 -3
- package/dist/regenerate/ledger-view.js +28 -10
- package/dist/regenerate/ledger.d.ts +9 -3
- package/dist/regenerate/ledger.js +4 -3
- package/dist/regenerate/loop.js +3 -4
- package/dist/regenerate/regenerate.js +20 -8
- package/dist/regenerate/stop-report.d.ts +1 -1
- package/dist/regenerate/stop-report.js +1 -15
- package/dist/resume-line.d.ts +2 -2
- package/dist/resume-line.js +3 -3
- package/docs/authoring-plain.md +2 -2
- package/docs/chats.md +3 -1
- package/docs/hosting.md +2 -2
- package/docs/regenerating.md +8 -6
- package/docs/using.md +7 -7
- package/genome/skills/brood/SKILL.md +1 -13
- package/genome/skills/spawn/SKILL.md +11 -16
- package/package.json +1 -1
|
@@ -16,21 +16,7 @@ export function describeStop(facts) {
|
|
|
16
16
|
const tries = facts.at === "unit tests" ? (facts.attempts ?? ATTEMPTS[facts.at]) : facts.at === "conformance" ? (facts.conformance?.rounds ?? ATTEMPTS[facts.at]) : ATTEMPTS[facts.at];
|
|
17
17
|
let why;
|
|
18
18
|
let todo;
|
|
19
|
-
// Not the spec's:
|
|
20
|
-
if (facts.at === "conformance" && facts.conformance?.environment !== undefined) {
|
|
21
|
-
return [
|
|
22
|
-
`Stopped at ${what}: its conformance tests cannot pass with what their run is given - judged so ${facts.conformance.environment.times} times in a row:`,
|
|
23
|
-
facts.conformance.environment.reason.trim(),
|
|
24
|
-
"",
|
|
25
|
-
"What to do:",
|
|
26
|
-
"- Provide what the run is missing - a valid credential, an account, a service it can reach - where the conformance testing script reads it.",
|
|
27
|
-
"- The testing scripts run on this machine in your own environment: a credential they need is read from there - your shell's " +
|
|
28
|
-
"variables, or a .env the script loads.",
|
|
29
|
-
"",
|
|
30
|
-
"Then build again: it picks up here, and what is built stays built.",
|
|
31
|
-
].join("\n");
|
|
32
|
-
}
|
|
33
|
-
// Not the spec's either: the script cannot run at all, so no code would pass it.
|
|
19
|
+
// Not the spec's: the script cannot run at all, so no code would pass it.
|
|
34
20
|
if (facts.at === "unit tests" && facts.missingToolchain !== undefined) {
|
|
35
21
|
const { command } = facts.missingToolchain;
|
|
36
22
|
const needs = command !== undefined ? `\`${command}\`` : "a toolchain it needs";
|
package/dist/resume-line.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/** pi's line on the way out that says how to resume the session,
|
|
2
|
-
export declare function
|
|
1
|
+
/** pi's line on the way out that says how to resume the session, left out: turri leaves nothing behind but the command run. */
|
|
2
|
+
export declare function withoutResumeLine(text: string): string;
|
package/dist/resume-line.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** pi's line on the way out that says how to resume the session,
|
|
2
|
-
export function
|
|
3
|
-
return text.replace(/^(
|
|
1
|
+
/** pi's line on the way out that says how to resume the session, left out: turri leaves nothing behind but the command run. */
|
|
2
|
+
export function withoutResumeLine(text) {
|
|
3
|
+
return text.replace(/^(?:\x1b\[[0-9;]*m)*To resume this session:.*\n?/m, "");
|
|
4
4
|
}
|
package/docs/authoring-plain.md
CHANGED
|
@@ -122,12 +122,12 @@ The ones that shape \*\*\*plain most:
|
|
|
122
122
|
|
|
123
123
|
## Writing \*\*\*plain with turri
|
|
124
124
|
|
|
125
|
-
In a conversation (`turri`), say what you want and the matching skill runs - but the three that start a project or a feature you start yourself, by their commands: `/brood`, `/spawn` or `/bud`, with what you want after it. Asked for new software without one - `create a small server in Java Spring Boot` - turri offers `/brood`, `/spawn` or `Just do it`, with no skill; a skill picked there starts at once with what you asked for, and Just do it starts the project in the conversation as `spawn` would, writing the module, its config and its unit testing script, then the smallest thing that runs, regenerated at once, and the first slices of what you described (see [using turri](using.md)). Two build a project from scratch, and write each \*\*\*plain change as a git diff that is built in the background the moment it is written. `brood` interviews you one question at a time and writes \*\*\*plain as you answer; `spawn`, its quick twin, gets something running as soon as it can - the smallest thing that runs first, then the product a slice at a time - asking only
|
|
125
|
+
In a conversation (`turri`), say what you want and the matching skill runs - but the three that start a project or a feature you start yourself, by their commands: `/brood`, `/spawn` or `/bud`, with what you want after it. Asked for new software without one - `create a small server in Java Spring Boot` - turri offers `/brood`, `/spawn` or `Just do it`, with no skill; a skill picked there starts at once with what you asked for, and Just do it starts the project in the conversation as `spawn` would, writing the module, its config and its unit testing script, then the smallest thing that runs, regenerated at once, and the first slices of what you described (see [using turri](using.md)). Two build a project from scratch, and write each \*\*\*plain change as a git diff that is built in the background the moment it is written. `brood` interviews you one question at a time and writes \*\*\*plain as you answer; `spawn`, its quick twin, gets something running as soon as it can - the smallest thing that runs first, then the product a slice at a time - asking what to build and the stack, in one question each, only when your message does not say:
|
|
126
126
|
|
|
127
127
|
| skill | phases | how a \*\*\*plain change is written |
|
|
128
128
|
| --- | --- | --- |
|
|
129
129
|
| `brood` | intent → stack → testing → product, feature by feature | first, how many questions the stack and product phases may ask - light 3, medium 5, thorough 10 or best judgement, broader with fewer, covering the same ground - and what they leave open turri decides itself, each decision a \*\*\*plain change of its own; every product answer is still a \*\*\*plain change, built before the next question; in testing, whether there are conformance tests, their `***test reqs***` and script - written as files, building nothing; then one \*\*\*plain change per answer, across whatever sections it needs, as a git diff with `change_plain`, regenerated as a \*\*\*plain diff pulse and conformance tested as it is built |
|
|
130
|
-
| `spawn` | start → skeleton → regenerate | built for the time to first regeneration: what to build is asked only when the message does not say, and the stack
|
|
130
|
+
| `spawn` | start → skeleton → regenerate | built for the time to first regeneration: what to build is asked only when the message does not say, and the stack in exactly one question when the message names none - stacks this machine can build, turri's choice recommended first; the rest of the technology turri chooses itself; the stack and the unit tests are written as files, with conformance tests off unless the user asks for them; then a \*\*\*plain change for the smallest thing that runs starts the first build - a module's first pulse of one functional spec is not reviewed - and the main slice of what the user described and at most one more follow - none when they described no feature, and never one of turri's own - each a functional spec on its happy path, as git diffs with `change_plain`, one after another with no answer between them. The rest - the next slices, then validation and edge cases as changes to those functional specs - is asked for in the conversation once the user has tried what landed: `go on` for the next slice it proposed |
|
|
131
131
|
|
|
132
132
|
`mature` starts from \*\*\*plain you already have, rough or hand-written, and runs on its own until it is fully regenerated - every functionality built from \*\*\*plain as it stands, its tests passing. It regenerates what is not built and watches the agents building it; when one struggles on something \*\*\*plain leaves open or unclear - sent back again and again, the judge going back and forth, a \*\*\*plain conflict - it writes what \*\*\*plain should say as a \*\*\*plain diff, stops that build, and regenerates it again. What the builds had to decide themselves - their assumptions, pitfalls, a failed build's diagnosis - goes into \*\*\*plain the same way, when a user, a caller or a test can see it. It never asks: it takes the reading that fits the rest of the \*\*\*plain description, and marks each such decision in its report. It leaves code, environment and turri problems to the builds, and stops when a functionality keeps struggling after its \*\*\*plain was clarified, when two cycles change nothing, or after twenty.
|
|
133
133
|
|
package/docs/chats.md
CHANGED
|
@@ -37,13 +37,15 @@ A pulse's end is told to the chat that asked for it, shown or not - its agent re
|
|
|
37
37
|
|
|
38
38
|
A line above the editor names each chat once there are two, a `│` between them: its number, its title - "new chat" until something is said in it, then its first message, until `/name` gives it one - and, after it, what it is doing: a spinner while it works, `?` while a question waits in it, `•` when it said something since you last looked. The chat shown is in the accent colour.
|
|
39
39
|
|
|
40
|
+
A message you send while a chat's agent works is shown under the chat at once, shaded and marked `not read yet`, and stays under what the agent writes and the tools it calls until the agent reads it - at the end of its current step - when it goes into the chat as a normal message, where it was read. `alt+up` takes the messages waiting back into the editor (`src/chat-waiting.ts`). While a skill runs in the chat - `/brood`, `/spawn`, `/bud` - its own agent is the one at work, and the chat's waits for the whole run: what you type then goes to the skill's agent, shown waiting until it reads it, at the end of its current step - and is in the chat from then, where it was read. The chat's agent is told what you said to the skill when the run ends. A message the skill's agent has not read when the run ends goes to the chat's agent instead.
|
|
41
|
+
|
|
40
42
|
On macOS, `alt` is Option (⌥), and reaches turri only when the terminal sends Option as Meta - otherwise ⌥N is the dead key for ñ and ⌥1 types `¡`, and nothing reaches turri. turri says so as a session's second chat opens. To turn it on: Ghostty, `macos-option-as-alt = true` in its config; iTerm2, Profiles → Keys → Left Option key: Esc+; Terminal.app, Profiles → Keyboard → Use Option as Meta key; Kitty, `macos_option_as_alt yes`; WezTerm, `send_composed_key_when_left_alt_is_pressed = false`. `/chat` works without it.
|
|
41
43
|
|
|
42
44
|
- **A hidden chat's questions** wait until you show it, then come up one after another. What it says in passing is said as you show it; what it keeps on the screen - a skill's progress, the job panel - is put back each time; what you had typed in its editor and not sent is still there.
|
|
43
45
|
- **The side panel** (`ctrl+h`) is the session's, not a chat's: docked beside the chat or over it, it stays as another chat is shown, and opening it from any chat finds it as it was left.
|
|
44
46
|
- **A long command** - `/regenerate`, planning a module from scratch - does its work in the background once it is under way: the chat, and switching to another, stay free while the planner plans.
|
|
45
47
|
- **`ctrl+c`** reaches the chat shown and nothing else: another chat's turn and skill go on, and so do the pulses - `/halt` stops one. A skill stopped keeps its run, for the model to continue with `resume`. At a question - the chat's `ask_user`, a skill's interview - `ctrl+c` declines it, and the asker is told so and goes on - each question it is pressed at, however many in a row. A skill is stopped by `ctrl+c` with no question open. A second press straight after one that stopped something does nothing, so pressing twice to be sure does not leave turri; once the chat is doing nothing, the next one does - with what every other chat is doing. A host has the same as `interrupt(id)`, and `decline(id)` for a question ([hosting](hosting.md)).
|
|
46
|
-
- **The last chat** is not closed: `/quit` leaves turri.
|
|
48
|
+
- **The last chat** is not closed: `/quit` leaves turri. Leaving turri leaves the terminal as it was: the conversation is not written out to it, nor a line on how to resume - the command run is all that stays. `turri --continue` opens the chats again.
|
|
47
49
|
- **`/fork`** and **`/reload`** work on the chat shown, as [pi](https://pi.dev)'s do: the chat's history forked, or turri's extension rebuilt in it.
|
|
48
50
|
- **A chat shown mid-turn** draws its reply as far as it is written, and follows it from there.
|
|
49
51
|
|
package/docs/hosting.md
CHANGED
|
@@ -157,7 +157,7 @@ const stop = onLedgerEvent((entry, project) => {
|
|
|
157
157
|
if (entry.kind === "provider.error" && !entry.transient) notify(`the model provider: ${entry.error}`);
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
-
// The project's runs, the most recent first, each with its pulses - how each ended, how long, what it cost.
|
|
160
|
+
// The project's runs, the most recent first, each with its pulses, the most recent first - how each ended, how long, what it cost.
|
|
161
161
|
const runs = runViews(projectDir);
|
|
162
162
|
|
|
163
163
|
// One pulse, from this session or an earlier one: its rounds, test runs, verdicts, healers, refusals, history.
|
|
@@ -168,7 +168,7 @@ const { jobs, more } = earlierPulses(ledgerProjects(projectDir), new Set(turri.j
|
|
|
168
168
|
```
|
|
169
169
|
|
|
170
170
|
- **Live.** `onLedgerEvent(listener)` is told every event as turri records it, with the project it is about, until what it returns is called; a listener that throws misses that event and nothing else. It is the pulse's own detail - its stages, test runs, verdicts, refusals - where `onJobChange` is the job as a whole.
|
|
171
|
-
- **Read back.** `readLedger(project, { job, run, kinds, since })` is the project's events, oldest first, the gzipped runs too; `runViews` and `pulseView` gather them into runs and pulses, and `describePulseView` and `describeRuns` say them in lines, as `turri ledger` prints them. `ledgerProjects(dir)` finds the ledgers of a folder and the projects under it. `earlierPulses(projects, known, runs = 3)` gives the last runs before this one as `Job`s - the shape a host already draws for this session's - each marked `earlier: { run, runMode, lines }`, `lines` what the ledger says of it; `more` is how many runs are beyond them. They are read only: never started, halted or waited for. turri's own side panel lists them so, as **earlier sessions**.
|
|
171
|
+
- **Read back.** `readLedger(project, { job, run, kinds, since })` is the project's events, oldest first, the gzipped runs too; `runViews` and `pulseView` gather them into runs and pulses, and `describePulseView` and `describeRuns` say them in lines, as `turri ledger` prints them. `ledgerProjects(dir)` finds the ledgers of a folder and the projects under it. `earlierPulses(projects, known, runs = 3)` gives the last runs before this one as `Job`s - the shape a host already draws for this session's - each marked `earlier: { run, runMode, lines }`, `lines` what the ledger says of it, and with its `diff` and `diffWhere` - the \*\*\*plain diff it regenerated, as last steered, and where its lines are written - as a pulse of this session has them (a pulse recorded before `job.diff` was has none); `more` is how many runs are beyond them. They are read only: never started, halted or waited for. turri's own side panel lists them so, as **earlier sessions**.
|
|
172
172
|
- **What it is for.** Looking up, never deciding: what is built and what is left come from the records and the work loop, as before. Its events and their fields are `LedgerEvent`'s - a kind is added, never changed, and every event carries `v: 1`.
|
|
173
173
|
|
|
174
174
|
## Running it
|
package/docs/regenerating.md
CHANGED
|
@@ -90,7 +90,7 @@ The agents with one thing to decide have a budget of tool calls: the judge 30, t
|
|
|
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 \*\*\*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.
|
|
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. **A testing script no code could pass** stops the pulse at the debugger's first look, too: it says (`at_fault`) when the unit testing script itself is wrong - it throws the tests' exit code away, checks the wrong folder, calls a tool wrongly - or when this machine lacks what it runs, an interpreter or a toolchain the harness's own check did not see in the output (a script that prints `python: command not found` and goes on to exit 1). The coding agent may change neither the script nor the machine, so no round would pass it: the pulse stops, rolled back and not retried, and the person is told what to change in the script, or what to install - see [when the environment lacks something](#when-the-environment-lacks-something).
|
|
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.
|
|
@@ -250,10 +250,11 @@ No agent installs anything on the machine, and none makes up a credential. When
|
|
|
250
250
|
> To fix: install java on this machine, so the testing script finds it on its PATH.
|
|
251
251
|
> Then re-run: `turri regenerate d365_version_api.plain`, or say "resume" in the chat.
|
|
252
252
|
|
|
253
|
-
It is raised
|
|
253
|
+
It is raised three ways:
|
|
254
254
|
|
|
255
255
|
- **by an agent**, which calls `report_environment_error` - only the agents that write and run code have it: the coding agent, the code fixer, the repair agent and the conformance agent; explorers, reviewers and judges observe, and never stop a pulse this way - with what is missing, what needs it and the command that showed it. Its shell runs behind walls the testing scripts do not, so what failed there may run here: the harness first runs the testing script itself - the unit one, the conformance one for the conformance agent. If it passes, the report does not stand: the agent is told the machine has what the work needs and goes on. If it cannot find its toolchain, the report stands. If it fails otherwise, the agent is shown its output once, and a report made again after that stands. A report that stands ends its turn, the pulse stops, and what it said goes to you as it is;
|
|
256
|
-
- **by the harness itself**: a testing script - the unit or the conformance one, in a code pulse, a conformance pulse or the whole-suite run - that cannot find its toolchain (exit 69 or 127, a `command not found` the run ended on), or a credential `agent-env:` names that is not there when the pulse starts - before any agent does. What the harness found it works out at once - the diagnosis, not after a second failure - to say how to fix it on this machine
|
|
256
|
+
- **by the harness itself**: a testing script - the unit or the conformance one, in a code pulse, a conformance pulse or the whole-suite run - that cannot find its toolchain (exit 69 or 127, a `command not found` the run ended on), or a credential `agent-env:` names that is not there when the pulse starts - before any agent does. What the harness found it works out at once - the diagnosis, not after a second failure - to say how to fix it on this machine;
|
|
257
|
+
- **by the debugger or the judge**, which say a testing script fails whatever the code and its tests are - the script itself is wrong, or this machine lacks what it runs - or that the conformance run lacks what only the person can give it: a credential, a service. The debugger stops the pulse at once (see [the tests must actually pass](#the-tests-must-actually-pass)); the judge once it has said so twice in a row (see [when a conformance test fails](#when-a-conformance-test-fails)). What it found goes to you as it said it, with what to change.
|
|
257
258
|
|
|
258
259
|
**Hidden by turri's own sandbox, not missing.** An agent's commands run behind the OS sandbox, which reads only the toolchain folders it knows; a toolchain kept somewhere else - a version manager's install it does not recognise - is on the machine, but out of the agent's sight. When a report names a file that is on this machine, outside the project and the system's folders (`sandboxGapOf` in `environment-error.ts`), the stop says so, and the fix is a line of config, not an install:
|
|
259
260
|
|
|
@@ -364,14 +365,15 @@ A \*\*\*plain diff's conformance run holds its tests to the same bar. The functi
|
|
|
364
365
|
|
|
365
366
|
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
367
|
|
|
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
|
|
368
|
+
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: what it does with the tests, the tests fit; what it needs of the build, the code provides. It is the culprit only when no code and no tests could pass it.
|
|
368
369
|
|
|
369
370
|
- **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
371
|
- **the tests:** the conformance agent corrects them to what \*\*\*plain says;
|
|
371
372
|
- **\*\*\*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
|
+
- **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, an interpreter or a toolchain this machine lacks. What a test sets up itself - a credential, a variable, a fixture - is the tests', and a package the code or the tests can declare is the agents';
|
|
374
|
+
- **the testing script:** the conformance testing script, or the prepare script, is itself wrong - it fails whatever the code and the tests are: it throws the tests' exit code away, runs the wrong folder, calls a tool wrongly. Only the person can change it.
|
|
373
375
|
|
|
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
|
|
376
|
+
The environment, or the testing script, 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 pulse stops, rolled back and not retried, 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 - or what to change in the script.
|
|
375
377
|
|
|
376
378
|
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
379
|
|
package/docs/using.md
CHANGED
|
@@ -16,7 +16,7 @@ Three skills you start yourself, by their commands or by picking them when turri
|
|
|
16
16
|
| skill | how it works |
|
|
17
17
|
| --- | --- |
|
|
18
18
|
| `brood` | first, how many questions the stack and product phases may ask - light (3), medium (5), thorough (10) or best judgement, broader with fewer, turri deciding what they leave open; then intent, stack, then testing - conformance tests on or off (into `config.turri.yaml`), their `***test reqs***` and the conformance testing script, which build nothing - then the product feature by feature, where every answer becomes one \*\*\*plain change - a git diff of the `.plain` files, written with `change_plain` and regenerated as a \*\*\*plain diff pulse the moment it is written, with its conformance tests when they are on |
|
|
19
|
-
| `spawn` | its quick twin, for something running in minutes: asks what you want to build only when your message does not say, and
|
|
19
|
+
| `spawn` | its quick twin, for something running in minutes: asks what you want to build only when your message does not say, and the stack in one question only when you named none - turri's choice recommended first; the rest of the technology it chooses itself - conformance tests off, unless you ask for them - then writes the smallest thing that runs, which starts the first build at once, and the main slice of what you described and one more on their happy path, each a \*\*\*plain diff queued as it is written - nothing you did not describe: named only the kind of software, you get it running, and say what it does. You try each as it lands, and say `go on` for the next slice it proposed, or what to change instead - every change is a \*\*\*plain diff, and what is left to build is worked out again from \*\*\*plain |
|
|
20
20
|
| `mature` | for \*\*\*plain you already have, rough or hand-written: on its own until it is fully regenerated - regenerates what is not built, watches the agents building it, and when one struggles on something \*\*\*plain leaves open, settles it in \*\*\*plain as a \*\*\*plain diff, stops that build and regenerates it again; decides open choices itself and marks them in its report |
|
|
21
21
|
|
|
22
22
|
Peeking is safe while a question is open - a skill's or the chat's: `ctrl+h` opens the side panel over the question, which waits under it as it was - the panel says `your question is waiting`, and `ctrl+h` or `esc` takes you back to answer it. (The question has the keys, so turri catches `ctrl+h` itself while one is open.) The dialog holds the question alone - no hint and no invitation; the `ctrl+h` under the job panel breathes until it is first pressed.
|
|
@@ -59,7 +59,7 @@ A pulse is one unit of work regenerating the code. It was called a job, and stil
|
|
|
59
59
|
|
|
60
60
|
A regeneration takes minutes, so in the TUI every tool that regenerates starts the work as a pulse and returns straight away. The conversation carries on; pulses on the same module - or on modules of one `requires` chain - queue behind each other, in the order they were asked for, from the first pulse on: one queued while the module's \*\*\*plain is only a scaffold, with no functional specs yet, or while it does not parse, still holds its module, so nothing on the module runs beside it. Pulses on modules that share nothing run side by side, each with its own progress panel - two modules or ten. How many run at once is capped by what the machine has room for: past `parallel-jobs` (see [the project config](config.md#how-many-jobs-at-once)), a pulse whose turn has come waits for a free slot, and says so.
|
|
61
61
|
|
|
62
|
-
- **The panel** above the input, while something runs, shows on top what finished - a line a module, its pulses
|
|
62
|
+
- **The panel** above the input, while something runs, shows on top what finished - a line a module, the module that finished last on top, its pulses newest first, each with its mark (green, red or amber, as in the side panel), number and kind - what it regenerated is in the side panel - `cognio ✓ 4 conformance · ✓ 3 regenerate · … 2 earlier`, the newest that fit the width - then a rule, and under it each running pulse, the newest first - `cognio · regenerate pulse 5`, `cognio · conformance pulse 6` - its time and cost, and what its agents are doing. A module whose work is being planned into pulses shows at once, before any pulse runs - `shorty · planning the pulses · 12s` - the planner is an agent, and takes a while; a `/regenerate` says it began the moment it is sent. Pulses are numbered within their module, as regen numbers them. `ctrl+o` expands the agents' trace alone; what finished stays a line a module. The line of keys under it - `ctrl+o to expand the trace · ctrl+h to peek at regen` - has each key breathing, fully there to a little faint and back, until it is first pressed: once `ctrl+o` has opened the trace, or the side panel has been opened, that key is still for the rest of the session and the other breathes on. What waits is not in it, and it shows no \*\*\*plain diff - the side panel has both. With nothing running it is gone.
|
|
63
63
|
- **A pulse's change** is what its agent works from, not a text diff of the module's file: the items `<spec change>` gives the agent - only what the pulse's functional specs use, an import's items as well as the module's own, a code pulse's without the test reqs - each in the file it is written in, under its section, in the file's order (`change-view.ts`).
|
|
64
64
|
- **A \*\*\*plain diff**, in the side panel, reads as an editor shows a diff: its [\*\*\*plain](https://plainlang.org/docs/) highlighted as [plyn](https://github.com/plainlang/plyn) highlights it - section headers, concepts, names in backticks, text in quotes, links, the front matter - each added line filled green and each removed one red, the text on top, the fill the width of the panel ([colours](theming.md#plain-diffs)). It is shown file by file, each file's lines together under its name, with what it adds and takes out - the module being regenerated first, the rest by name, and none the diff does not change. Each line has its number in that file: a \*\*\*plain diff is of \*\*\*plain as read, with what it imports laid in, so a line is placed in the file it is written in - its links read as the parser renders them - and a removed line, in no file now, goes with the change it is part of and has no number. A line is never put in a file on a guess: one that cannot be placed is listed last, under "not found in the spec's files". Where lines of a file are not in the diff, `↕ 28 lines` says how many, as GitHub does - `↑` above the first - and names the section the lines under it are in when it is another than the one above, `↕ 28 lines · ***functional specs***`, as GitHub names a hunk's function: each section is named once.
|
|
65
65
|
- **The side panel** (`ctrl+h`, as it was left - but on the pulse that last failed, stopped or did not pass, when one has since it was last opened: the live panel that showed it is gone with the last pulse, and its announcement in the chat says `ctrl+h shows this pulse`; **`/pulses`** on the pulses; not `ctrl+j`, which a terminal without the Kitty keyboard protocol sends as a line feed, the same as `shift+enter`, and which a dialog takes for `enter`; both stay [pi](https://pi.dev)'s new-line keys. `ctrl+h` is the byte old terminals sent for backspace; a terminal set to send `^H` for its Backspace key would open the panel on it) takes the whole screen - the panel or the chat, one at a time - or, `s`, sits beside the chat: the chat on the left, the panel in the right half of the screen, and `s` again over the whole screen. It opens as it was last left, for the conversation; a terminal under 104 columns - 100 inside the screen's padding, a blank row above and below everything and two columns either side - has no room for both and shows the panel over the whole screen. It opens on **regen**: the module's \*\*\*plain itself, in full, with how much of it the code has been regenerated from drawn onto it.
|
|
@@ -84,7 +84,7 @@ A regeneration takes minutes, so in the TUI every tool that regenerates starts t
|
|
|
84
84
|
|
|
85
85
|
One module is shown at a time, with a tab for each module of the chain on the line under the top line, in the chain's order - the module it is built on to the left: `d365_version_api [d365_http_client] d365_utils 12 ›`. A tab regenerating spins, one stuck says `!`; what does not fit is counted at either end. `←` `→` go from one tab to the next. The module shown is the one in focus - the one regenerating now, else the one asked for, else the first - until you pick another tab; it goes back to following once another module is in focus, or the one in focus starts regenerating. Under the module's own text is what it imports, under **imported**, a folded block a file, `▸ from stdlib/backend/python-fastapi · 7 reqs · all built`, closed until opened. The modules it requires are tabs of their own: a chain of many modules is never drawn nested, one in the next. A map longer than the screen has a minimap down its right edge, a cell a slice in the colour of its most pressing mark, the slice shown solid. The map is read from the files - the code record, the `.plain` files, the tests record - so it is right the moment turri opens a project, before anything runs; the work loop's plan adds the pulses on top. It maps the files asked to build this conversation, else `module:` in `config.turri.yaml`, else the `.plain` files of the folder that no other one there imports or requires - the folder's files looked at again only once one of them, or its config, changes. `↑` `↓` move row by row, `enter` or `space` open and close an item or an import block - a functional spec opens to its sub-bullets and its `***acceptance tests***`, nested under it as \*\*\*plain has them - `←` `→` go to the next module's tab, `o` and `c` open or close everything shown, `pgup` `pgdn` and the wheel scroll, `g`/`G` go to the top and the bottom.
|
|
86
86
|
|
|
87
|
-
`p` goes to the **pulses** - and back - onto the pulse that regenerates the item under the cursor, and back onto the first item the pulse under the cursor regenerates. The pulses are every pulse as three sections - running, queued, finished - each opened and closed on its own (running and queued start open) - and a fourth, **earlier sessions**, closed, when the [ledger](#the-ledger) has pulses of sessions before this one: its last three runs', each pulse read only - opened, what the ledger says of it (how it ended, its rounds and test runs, the healers, what turri refused and committed, its last stages and its log) - and a line for how many more runs it has. A pulse is one line: its module, kind and number (`hubspot · regenerate pulse 1`, `hubspot · conformance pulse 2`) - so it is named wherever a pulse is named in a line (the job panel, the `pulses` tool, `/halt`, the command line), never by what it regenerates, which is in it, opened - its time (none while it is queued: it has not started) and its cost - a finished one's mark green when it passed, red when it failed or did not pass, amber when it was stopped. Opened, a running one shows what it is doing; a queued one, what it waits for; a finished one, its agents and what each spent, and whether it did not pass. Under it is a row for each file its \*\*\*plain diff changes - the file of the module being regenerated first and open, the rest by name and closed - each opening onto that file's lines. A file with nothing added or taken out is not listed. `↑` `↓` move, `enter` or `space` open and close what is under the cursor, `→` `←` open and close (`←` on a closed pulse goes to its section, on a closed file to its pulse), `o` and `c` open or close every pulse of the section - or, on a file, every file of its pulse - `pgup` `pgdn` and the wheel scroll, `g`/`G` go to the top and the bottom. The cursor stays on its row when the pulse under it moves on; a pulse opened closes when it moves to another section. What is open is kept while the panel is closed. What the agents said and did is not shown - it is in each pulse's log (see [Agent logs](#agent-logs)).
|
|
87
|
+
`p` goes to the **pulses** - and back - onto the pulse that regenerates the item under the cursor, and back onto the first item the pulse under the cursor regenerates. The pulses are every pulse as three sections - running, queued, finished - each opened and closed on its own (running and queued start open), the newest first in each - running by when it started, queued by when it was queued, finished by when it ended - and a fourth, **earlier sessions**, closed, when the [ledger](#the-ledger) has pulses of sessions before this one: its last three runs', each pulse read only - opened, what the ledger says of it (how it ended, its rounds and test runs, the healers, what turri refused and committed, its last stages and its log), and under it a row for each file its \*\*\*plain diff changes, as a pulse of this session has - and a line for how many more runs it has. A pulse is one line: its module, kind and number (`hubspot · regenerate pulse 1`, `hubspot · conformance pulse 2`) - so it is named wherever a pulse is named in a line (the job panel, the `pulses` tool, `/halt`, the command line), never by what it regenerates, which is in it, opened - its time (none while it is queued: it has not started) and its cost - a finished one's mark green when it passed, red when it failed or did not pass, amber when it was stopped. Opened, a running one shows what it is doing; a queued one, what it waits for; a finished one, its agents and what each spent, and whether it did not pass. Under it is a row for each file its \*\*\*plain diff changes - the file of the module being regenerated first and open, the rest by name and closed - each opening onto that file's lines. A file with nothing added or taken out is not listed. `↑` `↓` move, `enter` or `space` open and close what is under the cursor, `→` `←` open and close (`←` on a closed pulse goes to its section, on a closed file to its pulse), `o` and `c` open or close every pulse of the section - or, on a file, every file of its pulse - `pgup` `pgdn` and the wheel scroll, `g`/`G` go to the top and the bottom. The cursor stays on its row when the pulse under it moves on; a pulse opened closes when it moves to another section. What is open is kept while the panel is closed. What the agents said and did is not shown - it is in each pulse's log (see [Agent logs](#agent-logs)).
|
|
88
88
|
|
|
89
89
|
`ctrl+h` again, or `esc`, closes it and goes back to the chat. Beside the chat, one side has the keys and the other is drawn faint: `ctrl+h` switches sides - from the chat to the panel, from the panel to the chat, the panel staying and following the pulses - `esc` gives the chat the keys too, and a click gives them to the side clicked. `ctrl+c` closes the panel; so do `s`, over the whole screen, then `esc`. ([pi](https://pi.dev)'s regular screen, `--tui-mode regular`, reads no mouse: there it is the keys alone.) While the panel has the keys, every key is the panel's, whatever else happens: a question the chat model asks in the background (`ask_user`) waits in the chat, unanswered - an `enter` in the panel never answers it - and the panel's top line says "the chat is waiting for your answer". Back in the chat, the question is there, with the keys.
|
|
90
90
|
- `turri` runs [pi](https://pi.dev) in fullscreen mode, so the conversation stays where you scroll it while the pulses redraw (PgUp/PgDn, the wheel); `--tui-mode regular` goes back to the terminal's own scrollback.
|
|
@@ -96,7 +96,7 @@ A regeneration takes minutes, so in the TUI every tool that regenerates starts t
|
|
|
96
96
|
- **Nothing is queued.** What is left to build is worked out from what each codebase is built from and \*\*\*plain as it is now - again whenever a pulse ends or \*\*\*plain changes - and the first pulse of it runs; see [a whole module](regenerating.md#a-whole-module). Changes that overlap never pile up: the next pulse builds \*\*\*plain as it is. The pulses planned after the one running are listed behind it, as queued, and so is each module waiting for the one it is built on - "waits for base" - until it can be planned. A change inside what the running pulse regenerates - a functional spec it regenerates reworded or given a sub-bullet, a definition or req it is given, a file they link - steers it: its agent is told, and it lands \*\*\*plain as it is now there, twice a pulse at most. Otherwise a pulse building something \*\*\*plain no longer wants is stopped and rolled back - unless `allow-to-stop-jobs: false` in `config.turri.yaml`, which has it land first and the change regenerated on top. To drop something, take it out of \*\*\*plain - one \*\*\*plain diff. Stopping a pulse leaves its change in \*\*\*plain: the codebase waits until its \*\*\*plain changes or it is asked for again.
|
|
97
97
|
- **A change to a module below** is made in the codebase at the tip of the chain, where its code lives; the codebase below is left as it was, and is brought up to its own \*\*\*plain only when a new module is to start from it. \*\*\*plain moved into a module the code was not built on stops the codebase: no change to its code brings that module in, so it has to be started over - its code and conformance tests taken out, kept in its history, and built again from the bottom of the chain. That is never done unasked: the chat asks you, saying why, and regenerates it from scratch once you agree; on the command line `turri regenerate` asks at the terminal, and `--start-over` agrees in advance.
|
|
98
98
|
- **Conformance tests are a track of their own.** A code pulse lands once its unit tests pass and are reviewed. Then, before the next one builds on it, a conformance pulse writes and runs the tests of what it built - from the test reqs and acceptance tests - with the whole suite the module inherits, and, where one fails, fixes the test or the code, whichever is wrong; what they are written for is recorded in `tests/.turri.json`. With `conformance-tests: false` none is written until you ask - `conform`, for a module or some of its functional specs. A conformance pulse that does not pass is undone whole and halts the conformance tests alone: the code goes on being built.
|
|
99
|
-
- **A pulse that fails** - its work errors, or it does not pass - is run once more. Failing again, it stops, and so does every pulse queued behind it on the same module, without running - the other modules' pulses go on. The harness then works out why: an agent that can read the project's \*\*\*plain, code, tests, testing scripts and logs, and turri's own source, skills and rules, says what happened, why, whether the fix belongs in \*\*\*plain, the environment, the code or turri itself, and exactly what to do.
|
|
99
|
+
- **A pulse that fails** - its work errors, or it does not pass - is run once more; one stopped on what only you can fix - the machine lacks something, a testing script no code could pass - is not. Failing again, it stops, and so does every pulse queued behind it on the same module, without running - the other modules' pulses go on. The harness then works out why: an agent that can read the project's \*\*\*plain, code, tests, testing scripts and logs, and turri's own source, skills and rules, says what happened, why, whether the fix belongs in \*\*\*plain, the environment, the code or turri itself, and exactly what to do.
|
|
100
100
|
- **When a pulse finishes** the transcript shows its line - `✓`, `✗` or `■`, its module, kind and number, how long it took and what it cost, never what it regenerated - `✓ shorty · conformance pulse 4 finished after 3m 47s · 488.6k tok · $0.02` - and the chat, which gets its whole report, reacts then and there, whatever else is running or queued, without waiting for you to speak: at once when it is idle, else as soon as the reply it is in ends. It does what the project's guidance says to do when a pulse finishes - release what was built, say - or tells you what finished and what it means. Ask to try it ("let me try it") and the chat releases what is built to `dist/<module>` and starts it on your machine, even while other pulses run. See [deploy](deploy.md). The chat reacts to it then and there, whatever else is running or queued, without waiting for you to speak - at once when it is idle, else as soon as the reply it is in ends: it does what the project's guidance says to do when a pulse finishes (release what was built, say), or tells you in a line or two what finished.
|
|
101
101
|
- **When a pulse stops** - a gate still failing after 20 attempts - it says where it stopped, why in plain words, and what to change in \*\*\*plain - which section, and how. Running the same build again picks up from there.
|
|
102
102
|
|
|
@@ -185,7 +185,7 @@ It is in `.turri/ledger/` in the project, a JSON line an event, one file a run -
|
|
|
185
185
|
| | |
|
|
186
186
|
| --- | --- |
|
|
187
187
|
| runs | `run.started` (how it was started, turri's version and commit, the machine), `run.ended` |
|
|
188
|
-
| pulses | `job.queued`, `job.started`, every `job.stage`, `job.retried`, `job.finished` - its status, whether it landed, how long it ran, what it cost, how it ended |
|
|
188
|
+
| pulses | `job.queued`, `job.diff` (its \*\*\*plain diff, whole, and where its lines are written - again each time steering moves it), `job.started`, every `job.stage`, `job.retried`, `job.finished` - its status, whether it landed, how long it ran, what it cost, how it ended |
|
|
189
189
|
| the work loop | `loop.halted`, `loop.stopped` (a pulse \*\*\*plain moved on from), `planner.failed`, `planner.fellBack` |
|
|
190
190
|
| the model | `model.call` (time and tokens), `model.turn`, `model.compaction`, `provider.retry`, `provider.stall`, `provider.error`, `turn.stopped` (a turn turri ended itself, and why) |
|
|
191
191
|
| tools and tests | `tool.call` (the tool, how long, whether it failed - never its arguments or result), `script.run` (the testing script, its exit, how long, whether the time limit stopped it, the failure's fingerprint, and `mutated` for a `can_it_fail` run on code broken on purpose) |
|
|
@@ -195,9 +195,9 @@ It is in `.turri/ledger/` in the project, a JSON line an event, one file a run -
|
|
|
195
195
|
| the history | `history.committed`, `history.failed`, `history.reset`, `history.rolledBack` |
|
|
196
196
|
| the environment | `environment.error` |
|
|
197
197
|
|
|
198
|
-
Never in it: prompts, replies, thinking, tool arguments and results, file contents. What an event does carry - a stage, an error's first line - is masked as the logs are.
|
|
198
|
+
Never in it: prompts, replies, thinking, tool arguments and results, file contents - the one body it keeps is each pulse's \*\*\*plain diff, so what an earlier session regenerated can be read back. What an event does carry - a stage, an error's first line - is masked as the logs are.
|
|
199
199
|
|
|
200
|
-
`turri ledger` prints the last runs, a line a pulse; `turri ledger <pulse>` one pulse - its rounds, its test runs and how many failed the same way, the verdicts, the healers, what turri refused, what its history recorded, its log; `--json` the events themselves, for `jq`. In the chat, `ledger` is the way in - a pulse of this session or an earlier one, the events of some kinds counted (how often the debugger failed this week: `kinds: [healer.failed], since: 7d`), the last runs - and `pulses` lists the last three earlier runs under this session's pulses, `pulses` and `diagnose` tell one of them by its id, and `diagnose` adds the ledger's facts to a pulse of this session; the side panel's pulses list has them as **earlier sessions** (see [the side panel](#in-a-conversation)).
|
|
200
|
+
`turri ledger` prints the last runs, a line a pulse - runs and pulses newest first, as every list of the ledger's is, the events and a pulse's history and stages too; `turri ledger <pulse>` one pulse - its rounds, its test runs and how many failed the same way, the verdicts, the healers, what turri refused, what its history recorded, its log, and the \*\*\*plain diff it regenerated; `--json` the events themselves, for `jq`. In the chat, `ledger` is the way in - a pulse of this session or an earlier one, the events of some kinds counted (how often the debugger failed this week: `kinds: [healer.failed], since: 7d`), the last runs - and `pulses` lists the last three earlier runs under this session's pulses, `pulses` and `diagnose` tell one of them by its id, and `diagnose` adds the ledger's facts to a pulse of this session; the side panel's pulses list has them as **earlier sessions** (see [the side panel](#in-a-conversation)).
|
|
201
201
|
|
|
202
202
|
It is for looking up, never for deciding: what to build comes from the records alone (see [what the code is built from](regenerating.md#what-the-code-is-built-from)), so deleting `.turri/ledger/` loses nothing but what can be looked up. When a run first writes to the project, the files of runs that have ended are gzipped and the oldest pruned past `ledger-keep:` megabytes - 100 unset, `0` for none at all; a run still going is never touched. `.turri` ignores itself, so the ledger is never committed, and nothing of it is sent anywhere. A ledger that cannot be written is said once and given up on, never failing the work.
|
|
203
203
|
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: brood
|
|
3
|
-
description:
|
|
4
|
-
`***plain` spec authoring in four phases - intent, stack, testing, product - where every answer
|
|
5
|
-
in the product interview becomes one spec change, written as a git diff of the .plain files and
|
|
6
|
-
built the moment it is written, so code appears while the interview is still going. It first asks
|
|
7
|
-
how many questions the stack and product phases may ask - light, medium, thorough or best
|
|
8
|
-
judgement, broader with fewer - and decides what they leave open itself, each decision a spec
|
|
9
|
-
change of its own. The testing
|
|
10
|
-
phase comes first, so each change is conformance tested as it is built: it decides on
|
|
11
|
-
conformance tests and writes the test reqs and the conformance testing script. Use when the user starts a new project or wants to build
|
|
12
|
-
something new from scratch and settle it with you step by step; when they want it built fast from
|
|
13
|
-
what they want alone, use its quick twin, `spawn`. Not for adding a
|
|
14
|
-
feature to an existing project (use `bud`) or for editing generated code (the .plain
|
|
15
|
-
specs are the source of truth).
|
|
3
|
+
description: start a new project through an interview, built as you answer.
|
|
16
4
|
allowed-tools: [read, write, edit, bash, ls, grep, find, change_plain]
|
|
17
5
|
metadata:
|
|
18
6
|
# Started only by the person, with its command - /brood - never by the model on its own.
|
|
@@ -1,25 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spawn
|
|
3
|
-
description:
|
|
4
|
-
The quick twin of `brood`, built for the shortest time to first regeneration: something running
|
|
5
|
-
in minutes, then grown a step at a time, the way a developer starts - the smallest thing that runs first, then the
|
|
6
|
-
main thing half-built, run and tried, then the next. Asks what the user wants to build only when
|
|
7
|
-
their message does not say, and the stack only when it cannot choose one this machine builds;
|
|
8
|
-
sets up the module, writes a first spec - the smallest thing that runs - that starts the first build at once, then the
|
|
9
|
-
first slices of the product on their happy path, and hands over: the user tries each slice as it
|
|
10
|
-
lands and says what next. Conformance tests are off unless the user asks for them. No gates. Use
|
|
11
|
-
when the user wants to start a new project fast, or says to just build it. For a full interview
|
|
12
|
-
that settles the stack, the testing and every feature with the user, use `brood`. Not for adding a
|
|
13
|
-
feature to an existing project (use `bud`).
|
|
3
|
+
description: "start a new project fast: running in minutes, then grown a step at a time."
|
|
14
4
|
allowed-tools: [read, write, edit, bash, ls, grep, find, change_plain]
|
|
15
5
|
metadata:
|
|
16
6
|
# Started only by the person, with its command - /spawn - never by the model on its own.
|
|
17
7
|
command-only: true
|
|
18
8
|
# What each phase does, in a line - shown under the skill's progress while it runs.
|
|
19
9
|
phases:
|
|
20
|
-
start: "what
|
|
21
|
-
skeleton: "
|
|
22
|
-
regenerate: "
|
|
10
|
+
start: "what to build, and on which stack"
|
|
11
|
+
skeleton: "the smallest project that runs"
|
|
12
|
+
regenerate: "the first features, a build each"
|
|
23
13
|
# It writes its spec changes one after another on its own: no answer between them.
|
|
24
14
|
paced: false
|
|
25
15
|
---
|
|
@@ -49,10 +39,15 @@ Read what is already there first: an existing `.plain` file, `config.turri.yaml`
|
|
|
49
39
|
|
|
50
40
|
### start
|
|
51
41
|
|
|
52
|
-
Find out what to build and on which stack
|
|
42
|
+
Find out what to build and on which stack, each asked only when the user's message does not say - the stack in exactly one question.
|
|
53
43
|
|
|
54
44
|
- **What to build.** When the user's message says what kind of software it is - a web app, an API, a CLI - ask nothing: that is enough to start. Otherwise ask one open question with `ask_user` and `free_form: true`: what should it do? Ask no follow-ups. An answer that names only the kind of software is enough too: the first spec is built, and what it does comes later, from the user.
|
|
55
|
-
- **The stack.**
|
|
45
|
+
- **The stack named.** When the user's message names the stack - a language, a framework or both: `/spawn a small python fast api server` - take it and ask nothing about technology; what it leaves open, choose yourself within it. Only a named stack in a language the machine lacks is asked about, as below.
|
|
46
|
+
- **A stack the project already settled** - its config, its template, its imports - is kept: no question about it either.
|
|
47
|
+
- **The stack - exactly one question**, when neither the message nor the project names one. Ask one `ask_user` question about the stack, and no other about technology: the framework, the storage, the libraries, the tests, the layout are yours to choose from the stack picked, as a careful engineer would. The stack has to be one this machine can build: the agents use its toolchains and install none. `<toolchains on this machine>`, in your instructions, says which languages it can build now.
|
|
48
|
+
- **The options**, three or four, each the stack and what it is in a few words: the standard library's stacks for the kind of software it is (the stdlib rule, in `<plain-rules>`), in languages the machine can build now. First the one you would choose, marked `(recommended)`. In the question's `context`, in a line, what you will build first.
|
|
49
|
+
- **A stack the user named in a language the machine lacks** is asked about in the same one question, as an option after the recommended one: `<stack> - once <toolchain> is installed`. Say in the `context` what to install and that `turri doctor` checks it.
|
|
50
|
+
- **The answer is the stack** - an option, or what they typed under "Something else…" - and nothing about it is asked again. A stack in a language the machine lacks: say what to install, that `turri doctor` checks it and that `/spawn` starts again once it is there, and stop - write nothing.
|
|
56
51
|
|
|
57
52
|
Then say in three lines what you will build first and on which stack, and carry on. Ask for no confirmation, and write nothing to disk in this step.
|
|
58
53
|
|