@turri-dev/cli 0.1.4-next.5a94e68 → 0.1.4-next.8254fbc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.pi/themes/turri-dark.json +67 -66
- package/.pi/themes/turri-light.json +71 -73
- package/README.md +40 -128
- package/assets/jellyfish/dark-00.png +0 -0
- package/assets/jellyfish/dark-01.png +0 -0
- package/assets/jellyfish/dark-02.png +0 -0
- package/assets/jellyfish/dark-03.png +0 -0
- package/assets/jellyfish/dark-04.png +0 -0
- package/assets/jellyfish/dark-05.png +0 -0
- package/assets/jellyfish/dark-06.png +0 -0
- package/assets/jellyfish/dark-07.png +0 -0
- package/assets/jellyfish/dark-08.png +0 -0
- package/assets/jellyfish/dark-09.png +0 -0
- package/assets/jellyfish/dark-10.png +0 -0
- package/assets/jellyfish/dark-11.png +0 -0
- package/assets/jellyfish/dark-12.png +0 -0
- package/assets/jellyfish/dark-13.png +0 -0
- package/assets/jellyfish/dark-14.png +0 -0
- package/assets/jellyfish/light-00.png +0 -0
- package/assets/jellyfish/light-01.png +0 -0
- package/assets/jellyfish/light-02.png +0 -0
- package/assets/jellyfish/light-03.png +0 -0
- package/assets/jellyfish/light-04.png +0 -0
- package/assets/jellyfish/light-05.png +0 -0
- package/assets/jellyfish/light-06.png +0 -0
- package/assets/jellyfish/light-07.png +0 -0
- package/assets/jellyfish/light-08.png +0 -0
- package/assets/jellyfish/light-09.png +0 -0
- package/assets/jellyfish/light-10.png +0 -0
- package/assets/jellyfish/light-11.png +0 -0
- package/assets/jellyfish/light-12.png +0 -0
- package/assets/jellyfish/light-13.png +0 -0
- package/assets/jellyfish/light-14.png +0 -0
- package/dist/brand.js +7 -7
- package/dist/cultivate-cli.js +16 -23
- package/dist/extension.js +15 -21
- package/dist/loop-cli.js +8 -8
- package/dist/module-report.js +5 -4
- package/dist/regenerate/plain-palette.js +51 -36
- package/dist/regenerate/side-panel.js +1 -1
- package/dist/regenerate/spec-map-view.js +9 -5
- package/dist/release-cli.js +3 -8
- package/dist/validate-cli.js +3 -8
- package/docs/README.md +5 -12
- package/docs/authoring-plain.md +37 -119
- package/docs/config.md +50 -176
- package/docs/deploy.md +21 -80
- package/docs/development.md +13 -41
- package/docs/headless.md +30 -136
- package/docs/images/how-turri-works.svg +29 -31
- package/docs/images/turri-banner.png +0 -0
- package/docs/installation.md +13 -40
- package/docs/parser.md +15 -43
- package/docs/regenerating.md +231 -964
- package/docs/sandbox.md +38 -152
- package/docs/skills-and-gates.md +50 -173
- package/docs/theming.md +45 -46
- package/docs/using.md +66 -356
- package/genome/rules/bullet-continuation.md +5 -13
- package/genome/rules/concise-specs-examples.md +2 -4
- package/genome/rules/concise-specs-integration-examples.md +2 -6
- package/genome/rules/concise-specs.md +1 -2
- package/genome/rules/func-specs.md +1 -0
- package/genome/rules/integration-embedded-testing.md +1 -4
- package/genome/rules/integrations.md +1 -2
- package/genome/rules/project-model.md +14 -35
- package/genome/rules/stdlib.md +14 -49
- package/genome/rules/turri-regeneration.md +48 -0
- package/genome/skills/add-implementation-requirement/SKILL.md +1 -2
- package/genome/skills/analyze-if-func-spec-too-complex/SKILL.md +3 -8
- package/genome/skills/brood/SKILL.md +37 -127
- package/genome/skills/brood/references/intent.md +4 -12
- package/genome/skills/brood/references/product.md +24 -76
- package/genome/skills/brood/references/stack.md +7 -29
- package/genome/skills/brood/references/testing.md +11 -42
- package/genome/skills/bud/SKILL.md +32 -109
- package/genome/skills/bud/references/intent.md +4 -11
- package/genome/skills/implement-conformance-testing-script/SKILL.md +3 -6
- package/genome/skills/implement-unit-testing-script/SKILL.md +1 -2
- package/genome/skills/mature/SKILL.md +21 -69
- package/genome/skills/spawn/SKILL.md +28 -113
- package/package.json +1 -1
package/docs/config.md
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
# The project config
|
|
2
2
|
|
|
3
|
-
A project says how its specs are built in `config.turri.yaml`, at the project root. Everything in it
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
parts are on different stacks - a backend and a frontend - adds a file per stack,
|
|
7
|
-
`config.turri.<stack>.yaml`, beside it, and chooses the stack to build with (see
|
|
8
|
-
[stacks](#stacks)). turri never writes a `config.yaml`: it may be another tool's, and
|
|
9
|
-
is read only by a project that has no file of turri's yet (see [the old config.yaml](#the-old-configyaml)).
|
|
10
|
-
|
|
11
|
-
`turri init-config` starts one: the two models, a strong one to talk to and a smaller one to write the code. It
|
|
12
|
-
asks which vendor's models you use - `--vendor` says it without asking, and with neither, as from a script, it is
|
|
13
|
-
`other`:
|
|
3
|
+
A project says how its specs are built in `config.turri.yaml`, at the project root. Everything in it is optional: with no file at all, turri finds the testing scripts on its own, turns conformance tests on wherever a module has test reqs, and runs on pi's configured model. A project whose parts are on different stacks - a backend and a frontend - adds a file per stack, `config.turri.<stack>.yaml`, beside it, and chooses the stack to build with (see [stacks](#stacks)). turri never writes a `config.yaml`: it may be another tool's, and is read only by a project that has no file of turri's yet (see [the old config.yaml](#the-old-configyaml)).
|
|
4
|
+
|
|
5
|
+
`turri init-config` starts one: the two models, a strong one to talk to and a smaller one to write the code. It asks which vendor's models you use - `--vendor` says it without asking, and with neither, as from a script, it is `other`:
|
|
14
6
|
|
|
15
7
|
| vendor | harness-model | coding-model | key pi reads |
|
|
16
8
|
| --- | --- | --- | --- |
|
|
@@ -21,64 +13,30 @@ asks which vendor's models you use - `--vendor` says it without asking, and with
|
|
|
21
13
|
| `amazon-bedrock`, OpenAI | `amazon-bedrock/<region>.openai.gpt-6-astra` | `amazon-bedrock/<region>.openai.gpt-6-luna` | `AWS_PROFILE` or `AWS_BEARER_TOKEN_BEDROCK`, and `AWS_REGION` |
|
|
22
14
|
| `other` | `anthropic/claude-opus-5-5` | `google/gemini-3.1-flash-lite` | `ANTHROPIC_API_KEY`, `GEMINI_API_KEY` |
|
|
23
15
|
|
|
24
|
-
Amazon Bedrock asks two more things - whose models, Anthropic's or OpenAI's (`--maker`), and the region of the
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
They are an example, not a requirement - any model [pi](https://pi.dev) supports works, signed in any way pi
|
|
34
|
-
supports; `other` is the starting point for another provider. What we recommend is that split, a capable model to
|
|
35
|
-
talk to and a smaller, cheaper one for the coding. Once written, it says what to do next: the key to set in your
|
|
36
|
-
shell - or `/login` in turri, which pi keeps in `~/.pi/agent/auth.json` - and that the file belongs to that folder:
|
|
37
|
-
turri reads the nearest `config.turri.yaml` upwards from where it starts, so one written anywhere else is not seen.
|
|
38
|
-
|
|
39
|
-
Below them it writes every other setting out, each with what it does and the value turri uses for it - `review: false`,
|
|
40
|
-
`turn-limit: 120`, `parallel-jobs` as this machine's cores make it - so the file says how the project is built, and you
|
|
41
|
-
change one by changing it. The optional ones, which have no value of their own - the testing scripts (written in by the
|
|
42
|
-
skill that writes them), `module`, `conformance-budget`, `judge-model`, `models` - are there commented out, each with an
|
|
43
|
-
example: uncomment one to use it. A key taken out of the file is still read as the table below says.
|
|
44
|
-
|
|
45
|
-
Beside a `config.yaml` - another tool's, say - the new file takes from it the keys turri reads too, each in its place, its
|
|
46
|
-
testing scripts above all, and says which it left (see [the old config.yaml](#the-old-configyaml)); `config.yaml`
|
|
47
|
-
is left as it is. A `config.turri.yaml` already there keeps everything but its two models, which it sets - `--force` writes the whole
|
|
48
|
-
file again - and a `config.yaml` turri read until then is copied to it first. It takes a folder other than the current
|
|
49
|
-
one as its argument.
|
|
16
|
+
Amazon Bedrock asks two more things - whose models, Anthropic's or OpenAI's (`--maker`), and the region of the inference profile they run in (`--region`): `global`, `us`, `eu`, `jp` or `au` for Anthropic's, `global` or `us` for OpenAI's. It says which `AWS_REGION` to set for it - pi calls Bedrock in `us-east-1` when none is. A `config.turri.yaml` already there keeps everything but its two models, which it sets; `--force` writes the whole file again.
|
|
17
|
+
|
|
18
|
+
Each is written with how hard it thinks - `harness-model: openai/gpt-6-astra:medium`, `coding-model: openai/gpt-6-luna:low` - so the file shows it. The reviews and judges run on the coding model but think medium (see [models per role](#models-per-role)).
|
|
19
|
+
|
|
20
|
+
They are an example, not a requirement - any model [pi](https://pi.dev) supports works, signed in any way pi supports; `other` is the starting point for another provider. What we recommend is that split, a capable model to talk to and a smaller, cheaper one for the coding. Once written, it says what to do next: the key to set in your shell - or `/login` in turri, which pi keeps in `~/.pi/agent/auth.json` - and that the file belongs to that folder: turri reads the nearest `config.turri.yaml` upwards from where it starts, so one written anywhere else is not seen.
|
|
21
|
+
|
|
22
|
+
Below them it writes every other setting out, each with what it does and the value turri uses for it - `review: false`, `turn-limit: 120`, `parallel-jobs` as this machine's cores make it - so the file says how the project is built, and you change one by changing it. The optional ones, which have no value of their own - the testing scripts (written in by the skill that writes them), `module`, `conformance-budget`, `judge-model`, `models` - are there commented out, each with an example: uncomment one to use it. A key taken out of the file is still read as the table below says.
|
|
23
|
+
|
|
24
|
+
Beside a `config.yaml` - another tool's, say - the new file takes from it the keys turri reads too, each in its place, its testing scripts above all, and says which it left (see [the old config.yaml](#the-old-configyaml)); `config.yaml` is left as it is. A `config.turri.yaml` already there keeps everything but its two models, which it sets - `--force` writes the whole file again - and a `config.yaml` turri read until then is copied to it first. It takes a folder other than the current one as its argument.
|
|
50
25
|
|
|
51
26
|
## Where it is read from
|
|
52
27
|
|
|
53
|
-
A spec belongs to its **project**: the nearest folder, from the spec's own folder up, that holds a
|
|
54
|
-
`config.turri.yaml`, a stack's `config.turri.<stack>.yaml`, the old `config.yaml` or a `plain_modules/`.
|
|
55
|
-
Without any of them, the spec's own folder is the project. That folder's config is the one read, and
|
|
56
|
-
its `plain_modules/` is where the code is built, wherever turri was started. So a project that keeps
|
|
57
|
-
its specs in `plain/`, with `plain/config.turri.yaml`, builds `plain/app.plain` by
|
|
58
|
-
`plain/config.turri.yaml` even when `turri` runs in the folder above.
|
|
28
|
+
A spec belongs to its **project**: the nearest folder, from the spec's own folder up, that holds a `config.turri.yaml`, a stack's `config.turri.<stack>.yaml`, the old `config.yaml` or a `plain_modules/`. Without any of them, the spec's own folder is the project. That folder's config is the one read, and its `plain_modules/` is where the code is built, wherever turri was started. So a project that keeps its specs in `plain/`, with `plain/config.turri.yaml`, builds `plain/app.plain` by `plain/config.turri.yaml` even when `turri` runs in the folder above.
|
|
59
29
|
|
|
60
30
|
When it is read:
|
|
61
31
|
|
|
62
|
-
- **In the chat**, afresh: the chat's agent is told what it says on every turn, and each render
|
|
63
|
-
|
|
64
|
-
no restart. The agent is told the config of the session's folder and of the projects one folder
|
|
65
|
-
down.
|
|
66
|
-
- **On the command line**, once, when the command starts. `turri regenerate` takes `module:` from
|
|
67
|
-
the folder it is run in, and the rest from the spec's own project.
|
|
32
|
+
- **In the chat**, afresh: the chat's agent is told what it says on every turn, and each render reads it when it is queued. An edit to the file holds from the next turn and the next render, with no restart. The agent is told the config of the session's folder and of the projects one folder down.
|
|
33
|
+
- **On the command line**, once, when the command starts. `turri regenerate` takes `module:` from the folder it is run in, and the rest from the spec's own project.
|
|
68
34
|
|
|
69
35
|
## Changing it from the chat
|
|
70
36
|
|
|
71
|
-
`/turri-config` changes any key in the chat, and writes it into the `config.turri.yaml` of the folder turri was started in -
|
|
72
|
-
its comments, and the commented-out examples, kept. Alone, it lists every key with what it is now, and asks for the
|
|
73
|
-
value of the one you pick the way the key takes it: `true` or `false`, one of its words, a number from a few offered or
|
|
74
|
-
typed, a model from those this machine can reach and then how hard it thinks, a script or a `.plain` file the project
|
|
75
|
-
has, rules ticked on and off. `/turri-config review` asks for review's value; `/turri-config review false` sets it, and
|
|
76
|
-
`/turri-config review unset` takes it out, back to its default. Completion offers the keys, then each one's values.
|
|
77
|
-
Each role's model and turn limit is `models.<role>` and `models.<role>.turn-limit` - `models.coding`,
|
|
78
|
-
`models.planner.turn-limit`.
|
|
37
|
+
`/turri-config` changes any key in the chat, and writes it into the `config.turri.yaml` of the folder turri was started in - its comments, and the commented-out examples, kept. Alone, it lists every key with what it is now, and asks for the value of the one you pick the way the key takes it: `true` or `false`, one of its words, a number from a few offered or typed, a model from those this machine can reach and then how hard it thinks, a script or a `.plain` file the project has, rules ticked on and off. `/turri-config review` asks for review's value; `/turri-config review false` sets it, and `/turri-config review unset` takes it out, back to its default. Completion offers the keys, then each one's values. Each role's model and turn limit is `models.<role>` and `models.<role>.turn-limit` - `models.coding`, `models.planner.turn-limit`.
|
|
79
38
|
|
|
80
|
-
Each change says when it takes effect. None needs turri started again - what turri fixes as it starts is changed as it
|
|
81
|
-
runs:
|
|
39
|
+
Each change says when it takes effect. None needs turri started again - what turri fixes as it starts is changed as it runs:
|
|
82
40
|
|
|
83
41
|
| when | keys |
|
|
84
42
|
| --- | --- |
|
|
@@ -90,10 +48,7 @@ runs:
|
|
|
90
48
|
| the next pulse that lands - the running one too | `release-after-pulse` |
|
|
91
49
|
| the next regeneration that names no `.plain` file | `module` |
|
|
92
50
|
|
|
93
|
-
A coding model chosen this session - `--coding-model`, or `engine` - gives way to one set here: the last word wins. It
|
|
94
|
-
says, too, what wins over the change: `models.chat` over `harness-model` (and so on), and a stack's
|
|
95
|
-
`config.turri.<stack>.yaml`, which is not changed here, while that stack is chosen. In a project still read from
|
|
96
|
-
`config.yaml`, the first change copies it to `config.turri.yaml` first - see [the old config.yaml](#the-old-configyaml).
|
|
51
|
+
A coding model chosen this session - `--coding-model`, or `engine` - gives way to one set here: the last word wins. It says, too, what wins over the change: `models.chat` over `harness-model` (and so on), and a stack's `config.turri.<stack>.yaml`, which is not changed here, while that stack is chosen. In a project still read from `config.yaml`, the first change copies it to `config.turri.yaml` first - see [the old config.yaml](#the-old-configyaml).
|
|
97
52
|
|
|
98
53
|
## The keys
|
|
99
54
|
|
|
@@ -145,15 +100,11 @@ models: # each agent role's model, thinking and tur
|
|
|
145
100
|
| `models` | each agent role's own model, thinking and turn limit - see [models per role](#models-per-role) | every role on `coding-model`, the conversation's side on `harness-model` |
|
|
146
101
|
| `testing-scripts-run-on` | what the testing scripts run on - always on this machine, in your environment. `in-place`: the real build and tests folders, the script at its own path, from the project - so a script that finds a host codebase from its own path finds it. `copy`: a fresh copy of the code, staged in `plain_modules/.turri/scripts/`, with the script copied beside it. `can_it_fail` works on either: on a copy it changes the copy, in place the code itself for the one run, put back after it (see [the testing scripts](regenerating.md#the-testing-scripts)) | `in-place` |
|
|
147
102
|
|
|
148
|
-
Keys are written with dashes; underscores are read the same (`conformance_tests`). A key turri
|
|
149
|
-
does not know is ignored - another tool's `config.yaml`, read while it is the old file, may carry several - and so is a value of the
|
|
150
|
-
wrong type, as if it were not there. `model:`, from before there were separate models, is read as
|
|
151
|
-
`coding-model`.
|
|
103
|
+
Keys are written with dashes; underscores are read the same (`conformance_tests`). A key turri does not know is ignored - another tool's `config.yaml`, read while it is the old file, may carry several - and so is a value of the wrong type, as if it were not there. `model:`, from before there were separate models, is read as `coding-model`.
|
|
152
104
|
|
|
153
105
|
## Models per role
|
|
154
106
|
|
|
155
|
-
`models:` gives each kind of agent its own model, thinking level and turn limit. Each entry is a model
|
|
156
|
-
(`provider/id`, or `provider/id:thinking`) or `{ model, thinking, turn-limit }`, any of which may be left out:
|
|
107
|
+
`models:` gives each kind of agent its own model, thinking level and turn limit. Each entry is a model (`provider/id`, or `provider/id:thinking`) or `{ model, thinking, turn-limit }`, any of which may be left out:
|
|
157
108
|
|
|
158
109
|
| role | the agents |
|
|
159
110
|
| --- | --- |
|
|
@@ -171,37 +122,21 @@ wrong type, as if it were not there. `model:`, from before there were separate m
|
|
|
171
122
|
| `arbiter` | the arbiters that weigh a second review |
|
|
172
123
|
| `debugger` | the fresh look at unit tests that keep failing the same way, or a coding agent going round in circles. Unnamed, `judge-model` when it is set, else the harness model - not `default` |
|
|
173
124
|
|
|
174
|
-
What an entry leaves out it takes from `default`: `reviewer: { thinking: low }` runs the default model, thinking
|
|
175
|
-
little. A turn limit is the role's own, else `default`'s, else `turn-limit:`, else two minutes. A stack's `config.turri.<stack>.yaml` lays its own `models:` over the project's, role by role - all but
|
|
176
|
-
`chat`, the project's alone.
|
|
125
|
+
What an entry leaves out it takes from `default`: `reviewer: { thinking: low }` runs the default model, thinking little. A turn limit is the role's own, else `default`'s, else `turn-limit:`, else two minutes. A stack's `config.turri.<stack>.yaml` lays its own `models:` over the project's, role by role - all but `chat`, the project's alone.
|
|
177
126
|
|
|
178
|
-
A role whose thinking nothing names - neither its entry, `default`'s, nor a `:level` on the model it runs on - thinks
|
|
179
|
-
as its kind of work needs: **low** for the agents that do the work (`coding`, `conformance`, `explorer`, `release`),
|
|
180
|
-
which work from specs that leave little to guess and take many turns, and **medium** for the ones that judge
|
|
181
|
-
(`reviewer`, `test-reviewer`, `judge`, `arbiter`, `debugger`, `planner`, `chooser`, `diagnosis`), where a wrong
|
|
182
|
-
call costs pulses. A judging role that falls back on the coding model takes its model alone, not its thinking. The
|
|
183
|
-
conversation keeps its own level, as pi sets it.
|
|
127
|
+
A role whose thinking nothing names - neither its entry, `default`'s, nor a `:level` on the model it runs on - thinks as its kind of work needs: **low** for the agents that do the work (`coding`, `conformance`, `explorer`, `release`), which work from specs that leave little to guess and take many turns, and **medium** for the ones that judge (`reviewer`, `test-reviewer`, `judge`, `arbiter`, `debugger`, `planner`, `chooser`, `diagnosis`), where a wrong call costs pulses. A judging role that falls back on the coding model takes its model alone, not its thinking. The conversation keeps its own level, as pi sets it.
|
|
184
128
|
|
|
185
|
-
The thinking level reaches the model as each provider takes it. OpenAI's models on Bedrock are sent it as their
|
|
186
|
-
reasoning effort (`none`, `low`, `medium`, `high`, `xhigh`) by turri itself, as pi sends them none.
|
|
129
|
+
The thinking level reaches the model as each provider takes it. OpenAI's models on Bedrock are sent it as their reasoning effort (`none`, `low`, `medium`, `high`, `xhigh`) by turri itself, as pi sends them none.
|
|
187
130
|
|
|
188
131
|
## How many jobs at once
|
|
189
132
|
|
|
190
|
-
Jobs on the same module, or on modules of one `requires` chain, always run one after another.
|
|
191
|
-
Modules that share nothing - a backend, a frontend, a worker, ten of them - build side by side, each
|
|
192
|
-
pulse's builds and tests running on this machine beside your own work. So the chat runs at most `parallel-jobs` jobs
|
|
193
|
-
at once; a job whose turn has come waits for a free slot past that, and its line says so. Unset, it is half this
|
|
194
|
-
machine's cores, at least one and at most four. The config is the only place it is set. It is the project's alone,
|
|
195
|
-
never read from a stack's file.
|
|
133
|
+
Jobs on the same module, or on modules of one `requires` chain, always run one after another. Modules that share nothing - a backend, a frontend, a worker, ten of them - build side by side, each pulse's builds and tests running on this machine beside your own work. So the chat runs at most `parallel-jobs` jobs at once; a job whose turn has come waits for a free slot past that, and its line says so. Unset, it is half this machine's cores, at least one and at most four. The config is the only place it is set. It is the project's alone, never read from a stack's file.
|
|
196
134
|
|
|
197
|
-
The testing scripts all run on this machine, each on a copy of its module's code, so they never
|
|
198
|
-
share files - but they do share its network: two modules whose conformance scripts start a server
|
|
199
|
-
on the same port collide when they run at once. Give each its own.
|
|
135
|
+
The testing scripts all run on this machine, each on a copy of its module's code, so they never share files - but they do share its network: two modules whose conformance scripts start a server on the same port collide when they run at once. Give each its own.
|
|
200
136
|
|
|
201
137
|
## Models
|
|
202
138
|
|
|
203
|
-
Each model is a model reference and a thinking level - `off`, `minimal`, `low`, `medium`, `high`,
|
|
204
|
-
`xhigh` or `max` - and either may be left out:
|
|
139
|
+
Each model is a model reference and a thinking level - `off`, `minimal`, `low`, `medium`, `high`, `xhigh` or `max` - and either may be left out:
|
|
205
140
|
|
|
206
141
|
```yaml
|
|
207
142
|
coding-model:
|
|
@@ -211,9 +146,7 @@ judge-model: google/gemini-3.1-pro:high # the same, as one string
|
|
|
211
146
|
harness-model: anthropic/claude-opus-5-5 # a model alone
|
|
212
147
|
```
|
|
213
148
|
|
|
214
|
-
What a model leaves out it takes from the one it inherits: `judge-model` from `coding-model` - its model, not its
|
|
215
|
-
thinking, which the judging roles have their own of - and `coding-model` from `harness-model`. So with only a harness model, everything runs on it;
|
|
216
|
-
`coding-model: {thinking: low}` renders on the harness model, thinking less.
|
|
149
|
+
What a model leaves out it takes from the one it inherits: `judge-model` from `coding-model` - its model, not its thinking, which the judging roles have their own of - and `coding-model` from `harness-model`. So with only a harness model, everything runs on it; `coding-model: {thinking: low}` renders on the harness model, thinking less.
|
|
217
150
|
|
|
218
151
|
They are defaults. What is asked for wins over them:
|
|
219
152
|
|
|
@@ -223,52 +156,31 @@ They are defaults. What is asked for wins over them:
|
|
|
223
156
|
| coding | `turri --coding-model <m>`, `engine` in the conversation |
|
|
224
157
|
| judge | - |
|
|
225
158
|
|
|
226
|
-
`turri regenerate`, `conform` and `spec-diff` read `--harness-model`, `--coding-model` (or `--model`),
|
|
227
|
-
`--judge-model`, `--review` and `--conformance-tests` differently: as the keys themselves, as if the file had
|
|
228
|
-
them. Each takes its key's value and its place in the order above - a `models:` entry still wins over it - so a
|
|
229
|
-
headless run is the same as a chat with those keys in the file.
|
|
159
|
+
`turri regenerate`, `conform` and `spec-diff` read `--harness-model`, `--coding-model` (or `--model`), `--judge-model`, `--review` and `--conformance-tests` differently: as the keys themselves, as if the file had them. Each takes its key's value and its place in the order above - a `models:` entry still wins over it - so a headless run is the same as a chat with those keys in the file.
|
|
230
160
|
|
|
231
161
|
A job keeps the model it was queued with: choosing another holds for what is queued after.
|
|
232
162
|
|
|
233
163
|
## Conformance tests
|
|
234
164
|
|
|
235
|
-
`conformance-tests:` is the one switch, and the chat, every render and `brood`'s testing phase
|
|
236
|
-
follow it. `false` turns them off entirely: no conformance tests are written, the ones already in a
|
|
237
|
-
codebase are not run, and no agent is shown the conformance testing script. No key is the same as
|
|
238
|
-
`false`: conformance tests are off by default. `all` (or `true`) means on wherever a module has
|
|
239
|
-
`***test reqs***` - a module without them has nothing to write conformance tests from, so it writes
|
|
240
|
-
none, but still keeps the codebase's existing ones passing. Asked in the
|
|
241
|
-
conversation (`conform`), or with `--conformance-tests all|chosen|module|false` on `turri regenerate` and
|
|
242
|
-
`spec-diff` - for that run, the file left as it is - a render does otherwise.
|
|
165
|
+
`conformance-tests:` is the one switch, and the chat, every render and `brood`'s testing phase follow it. `false` turns them off entirely: no conformance tests are written, the ones already in a codebase are not run, and no agent is shown the conformance testing script. No key is the same as `false`: conformance tests are off by default. `all` (or `true`) means on wherever a module has `***test reqs***` - a module without them has nothing to write conformance tests from, so it writes none, but still keeps the codebase's existing ones passing. Asked in the conversation (`conform`), or with `--conformance-tests all|chosen|module|false` on `turri regenerate` and `spec-diff` - for that run, the file left as it is - a render does otherwise.
|
|
243
166
|
|
|
244
|
-
`spawn` writes `conformance-tests: false` into a new project unless you ask for tests;
|
|
245
|
-
`brood` asks, whatever the key says, offering what it says first.
|
|
167
|
+
`spawn` writes `conformance-tests: false` into a new project unless you ask for tests; `brood` asks, whatever the key says, offering what it says first.
|
|
246
168
|
|
|
247
169
|
## The testing scripts
|
|
248
170
|
|
|
249
|
-
A build needs a unit testing script - and, with conformance on, a conformance testing script - to
|
|
250
|
-
decide when it is done. They are looked for at the project root, in this order:
|
|
171
|
+
A build needs a unit testing script - and, with conformance on, a conformance testing script - to decide when it is done. They are looked for at the project root, in this order:
|
|
251
172
|
|
|
252
173
|
1. named in the config - the chosen stack's file first, then `config.turri.yaml` - by path from the root;
|
|
253
174
|
2. the one `run_unittests*.sh` / `run_conformance_tests*.sh` in the project root;
|
|
254
175
|
3. the one of each in `test_scripts/`.
|
|
255
176
|
|
|
256
|
-
The optional prepare script - `prepare-environment-script:`, else the one `prepare_environment*.sh` - is looked for the
|
|
257
|
-
same way, and run on the build before the conformance testing script.
|
|
177
|
+
The optional prepare script - `prepare-environment-script:`, else the one `prepare_environment*.sh` - is looked for the same way, and run on the build before the conformance testing script.
|
|
258
178
|
|
|
259
|
-
A folder holding two of a kind is not guessed between: name the one to use. A script named inside
|
|
260
|
-
`plain_modules/` is refused - agents write there, so it could be changed by the work it judges. The
|
|
261
|
-
scripts are never linked from the specs. What they are and how they run is in
|
|
262
|
-
[regenerating the code](regenerating.md#the-testing-scripts).
|
|
179
|
+
A folder holding two of a kind is not guessed between: name the one to use. A script named inside `plain_modules/` is refused - agents write there, so it could be changed by the work it judges. The scripts are never linked from the specs. What they are and how they run is in [regenerating the code](regenerating.md#the-testing-scripts).
|
|
263
180
|
|
|
264
181
|
## Credentials for the agents
|
|
265
182
|
|
|
266
|
-
An agent's commands do not get the environment turri was started in: it holds your providers' API keys, cloud
|
|
267
|
-
credentials and tokens. They get only the path, the locale, the terminal and the user, the variables that locate your
|
|
268
|
-
toolchains (`JAVA_HOME`, `NVM_DIR`, `RUSTUP_HOME`, ... - the ones in your home found even when your shell sets none),
|
|
269
|
-
and turri's own: a home folder of the module's own (`plain_modules/.turri/home/<module>`, kept between pulses, with a
|
|
270
|
-
git identity of its own), a `TMPDIR`, the package caches in `plain_modules/.turri/cache`, and git stopped at the module
|
|
271
|
-
folder, so a project that is itself a repository is never found from the code.
|
|
183
|
+
An agent's commands do not get the environment turri was started in: it holds your providers' API keys, cloud credentials and tokens. They get only the path, the locale, the terminal and the user, the variables that locate your toolchains (`JAVA_HOME`, `NVM_DIR`, `RUSTUP_HOME`, ... - the ones in your home found even when your shell sets none), and turri's own: a home folder of the module's own (`plain_modules/.turri/home/<module>`, kept between pulses, with a git identity of its own), a `TMPDIR`, the package caches in `plain_modules/.turri/cache`, and git stopped at the module folder, so a project that is itself a repository is never found from the code.
|
|
272
184
|
|
|
273
185
|
A project whose agents need a credential while they work names it:
|
|
274
186
|
|
|
@@ -278,24 +190,13 @@ agent-env:
|
|
|
278
190
|
vars: [D365_TENANT_ID] # these variables, from the environment turri was started in
|
|
279
191
|
```
|
|
280
192
|
|
|
281
|
-
What it names reaches every agent with a shell, as environment variables of its commands only - the file stays where
|
|
282
|
-
it is, outside every agent's reach - and never replaces turri's own home, `TMPDIR` or caches. A stack's file adds
|
|
283
|
-
to the project's. A file that is not there, or a variable unset or empty, is reported as missing. The testing scripts
|
|
284
|
-
are not affected: they run in your own environment.
|
|
193
|
+
What it names reaches every agent with a shell, as environment variables of its commands only - the file stays where it is, outside every agent's reach - and never replaces turri's own home, `TMPDIR` or caches. A stack's file adds to the project's. A file that is not there, or a variable unset or empty, is reported as missing. The testing scripts are not affected: they run in your own environment.
|
|
285
194
|
|
|
286
|
-
Their values never appear in what an agent is shown or what turri writes: each is replaced by its name -
|
|
287
|
-
`[D365_CLIENT_SECRET]` - whole, URL-encoded, or split over a command's output as it streams: in every tool result and
|
|
288
|
-
refusal an agent is given (and so in the session transcripts, which hold only those), in the whole outputs kept for
|
|
289
|
-
`read_output`, and in the job and debug logs. A value shorter than four characters is not masked - `1` or `eu` is
|
|
290
|
-
everywhere in ordinary output.
|
|
195
|
+
Their values never appear in what an agent is shown or what turri writes: each is replaced by its name - `[D365_CLIENT_SECRET]` - whole, URL-encoded, or split over a command's output as it streams: in every tool result and refusal an agent is given (and so in the session transcripts, which hold only those), in the whole outputs kept for `read_output`, and in the job and debug logs. A value shorter than four characters is not masked - `1` or `eu` is everywhere in ordinary output.
|
|
291
196
|
|
|
292
197
|
## Stacks
|
|
293
198
|
|
|
294
|
-
One project can hold parts that share nothing but a common module - a Python backend and a React
|
|
295
|
-
frontend side by side, each importing `base` from `template/`, neither requiring the other - each
|
|
296
|
-
needing its own testing scripts. Each stack gets a file of its own beside `config.turri.yaml`,
|
|
297
|
-
`config.turri.<stack>.yaml`, holding what differs for it - typically its testing scripts, its
|
|
298
|
-
`toolchains:`, its models:
|
|
199
|
+
One project can hold parts that share nothing but a common module - a Python backend and a React frontend side by side, each importing `base` from `template/`, neither requiring the other - each needing its own testing scripts. Each stack gets a file of its own beside `config.turri.yaml`, `config.turri.<stack>.yaml`, holding what differs for it - typically its testing scripts, its `toolchains:`, its models:
|
|
299
200
|
|
|
300
201
|
```
|
|
301
202
|
config.turri.yaml # the project's: harness-model, coding-model, conformance-tests
|
|
@@ -317,50 +218,23 @@ coding-model:
|
|
|
317
218
|
|
|
318
219
|
A stack is chosen, never worked out from the spec:
|
|
319
220
|
|
|
320
|
-
- **In the chat**, with `/stack` - a list of the project's stacks and none - or `/stack backend`, `/stack none`.
|
|
321
|
-
|
|
322
|
-
stack builds. `/stack` alone says which is chosen now.
|
|
323
|
-
- **On the command line**, with `--stack <name>` on any command - `turri regenerate`, `conform`, `spec-diff`, `glimpse`,
|
|
324
|
-
`release`, `cultivate` - and on `turri --stack backend` for the chat; or with `TURRI_STACK` in the environment.
|
|
221
|
+
- **In the chat**, with `/stack` - a list of the project's stacks and none - or `/stack backend`, `/stack none`. The chat's model has a `stack` tool too, and switches the stack when you ask it to, or for work on a part another stack builds. `/stack` alone says which is chosen now.
|
|
222
|
+
- **On the command line**, with `--stack <name>` on any command - `turri regenerate`, `conform`, `spec-diff`, `glimpse`, `release`, `cultivate` - and on `turri --stack backend` for the chat; or with `TURRI_STACK` in the environment.
|
|
325
223
|
|
|
326
|
-
The choice lasts for the session only: nothing remembers it, and turri started again has none chosen. A stack the
|
|
327
|
-
project has no file for is refused, with the stacks it has. With none chosen, `config.turri.yaml` alone is used.
|
|
224
|
+
The choice lasts for the session only: nothing remembers it, and turri started again has none chosen. A stack the project has no file for is refused, with the stacks it has. With none chosen, `config.turri.yaml` alone is used.
|
|
328
225
|
|
|
329
226
|
How a stack's config is made:
|
|
330
227
|
|
|
331
|
-
- **Laid over `config.turri.yaml`, key by key.** What the stack's file gives wins; what it leaves out
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
started with. Choose the stack before building the part it is for: `/stack backend`, then
|
|
337
|
-
`regenerate backend.plain`.
|
|
338
|
-
- **The project's alone.** `module:`, `harness-model:`, `parallel-jobs:`, `rules-off:` and `compact-at:` are read
|
|
339
|
-
only from `config.turri.yaml` - there is one conversation, one module built when none is named, one machine.
|
|
340
|
-
`agent-env:` and `toolchains:` in a stack's file add to the project's.
|
|
341
|
-
|
|
342
|
-
The chat is told each stack's config and the one chosen. The skills that write testing scripts put
|
|
343
|
-
each stack's in its own file once a project has two stacks, and say which stack to choose before
|
|
344
|
-
building each part.
|
|
228
|
+
- **Laid over `config.turri.yaml`, key by key.** What the stack's file gives wins; what it leaves out is the project's. A model it names takes what it leaves out from the project's same model - above, with the stack frontend chosen, everything renders on the project's coding model, thinking `high`.
|
|
229
|
+
- **For everything built while it is chosen.** Every pulse that starts, every test run and every script found from then on is the chosen stack's; a pulse already running keeps the stack it started with. Choose the stack before building the part it is for: `/stack backend`, then `regenerate backend.plain`.
|
|
230
|
+
- **The project's alone.** `module:`, `harness-model:`, `parallel-jobs:`, `rules-off:` and `compact-at:` are read only from `config.turri.yaml` - there is one conversation, one module built when none is named, one machine. `agent-env:` and `toolchains:` in a stack's file add to the project's.
|
|
231
|
+
|
|
232
|
+
The chat is told each stack's config and the one chosen. The skills that write testing scripts put each stack's in its own file once a project has two stacks, and say which stack to choose before building each part.
|
|
345
233
|
|
|
346
234
|
## The old config.yaml
|
|
347
235
|
|
|
348
|
-
turri's settings were once in `config.yaml`, and a stack's in `config.<stack>.yaml`. A `config.yaml`
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
`config.turri.yaml` and each `config.<name>.yaml` to `config.turri.<name>.yaml` first, leaves the old
|
|
354
|
-
files as they are, and from then on reads only the new ones. `turri init-config` copies the stacks'
|
|
355
|
-
files the same way, but writes `config.turri.yaml` as its quick start, taking from `config.yaml` only
|
|
356
|
-
the keys turri reads too - `unittests-script`, `conformance-tests-script` and
|
|
357
|
-
`prepare-environment-script`, say - each in its place in the file, and saying which keys it left:
|
|
358
|
-
`template_dir`, `verbose`, `api`, the other tool's alone. The two models are the vendor's, never taken. To change a
|
|
359
|
-
setting by hand in such a project, do the same: copy the files to their new names, and edit the
|
|
360
|
-
copies - never `config.yaml`. Writing a `config.turri.yaml` of your own beside it is the same move: from then on
|
|
361
|
-
`config.yaml` is not read, its testing scripts with it. For a headless run that only needs conformance tests or
|
|
362
|
-
another judge, or review, those options leave the files alone: `--conformance-tests`, `--judge-model`, `--review true|false`, and the models' too.
|
|
363
|
-
|
|
364
|
-
Keys turri does not read - another tool's `verbose`, `api-key`, `build-folder`, ... - are ignored without a word, and so
|
|
365
|
-
is a value of the wrong type. A file that does not parse as YAML is read as empty, so its testing scripts are then
|
|
366
|
-
looked for by name.
|
|
236
|
+
turri's settings were once in `config.yaml`, and a stack's in `config.<stack>.yaml`. A `config.yaml` may be another tool's, so turri never writes one. While a project folder has no `config.turri*.yaml` at all, turri still reads its `config.yaml`, and each `config.<name>.yaml` as the stack `<name>`.
|
|
237
|
+
|
|
238
|
+
The first time turri itself writes a setting there with `/turri-config`, it copies `config.yaml` to `config.turri.yaml` and each `config.<name>.yaml` to `config.turri.<name>.yaml` first, leaves the old files as they are, and from then on reads only the new ones. `turri init-config` copies the stacks' files the same way, but writes `config.turri.yaml` as its quick start, taking from `config.yaml` only the keys turri reads too - `unittests-script`, `conformance-tests-script` and `prepare-environment-script`, say - each in its place in the file, and saying which keys it left: `template_dir`, `verbose`, `api`, the other tool's alone. The two models are the vendor's, never taken. To change a setting by hand in such a project, do the same: copy the files to their new names, and edit the copies - never `config.yaml`. Writing a `config.turri.yaml` of your own beside it is the same move: from then on `config.yaml` is not read, its testing scripts with it. For a headless run that only needs conformance tests or another judge, or review, those options leave the files alone: `--conformance-tests`, `--judge-model`, `--review true|false`, and the models' too.
|
|
239
|
+
|
|
240
|
+
Keys turri does not read - another tool's `verbose`, `api-key`, `build-folder`, ... - are ignored without a word, and so is a value of the wrong type. A file that does not parse as YAML is read as empty, so its testing scripts are then looked for by name.
|
package/docs/deploy.md
CHANGED
|
@@ -1,95 +1,41 @@
|
|
|
1
1
|
# Trying what is built: deploy
|
|
2
2
|
|
|
3
|
-
Ask to try it - "let me try it", "run the app" - at any time, even while a render is running. The
|
|
4
|
-
chat calls `deploy`: it puts the module's code, as it was last built, in `dist/<module>` in the
|
|
5
|
-
project, and starts it on your machine. An app with a backend and a frontend is started whole, and
|
|
6
|
-
you are told where to open your browser. For a command-line tool or a library you get a few commands
|
|
7
|
-
to paste, run from `dist/<module>`, and what they print.
|
|
3
|
+
Ask to try it - "let me try it", "run the app" - at any time, even while a render is running. The chat calls `deploy`: it puts the module's code, as it was last built, in `dist/<module>` in the project, and starts it on your machine. An app with a backend and a frontend is started whole, and you are told where to open your browser. For a command-line tool or a library you get a few commands to paste, run from `dist/<module>`, and what they print.
|
|
8
4
|
|
|
9
|
-
Every pulse that lands code - a render, a spec diff, a conformance run, a functionality regenerated - ends with
|
|
10
|
-
"Want to try it? Just ask me - I'll set it up from what's built so far." When a render's conformance
|
|
11
|
-
tests follow as a pulse of their own, the conformance pulse says it, once they pass too.
|
|
5
|
+
Every pulse that lands code - a render, a spec diff, a conformance run, a functionality regenerated - ends with "Want to try it? Just ask me - I'll set it up from what's built so far." When a render's conformance tests follow as a pulse of their own, the conformance pulse says it, once they pass too.
|
|
12
6
|
|
|
13
7
|
## When the project says how it is released
|
|
14
8
|
|
|
15
|
-
Every release starts the same way: the module's last commit - what last landed whole - goes in
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
is started. So the model asks itself whether there is guidance for how this project is released -
|
|
19
|
-
in what you said, the project's AGENTS.md, a skill, anything it was given - and passes it to
|
|
20
|
-
`release` whole:
|
|
21
|
-
|
|
22
|
-
- **There is guidance.** The code goes on from `dist/<module>` as the guidance says, on your machine,
|
|
23
|
-
from the host codebase - the git repository the project is in, or else where **turri** runs: the
|
|
24
|
-
scripts it names, in their order, and any change it says the host needs. The code is taken from
|
|
25
|
-
`dist`, never from `plain_modules`, where a pulse may be writing; where the host's tooling reads
|
|
26
|
-
`plain_modules` itself, the model points it at `dist`, or does by hand from `dist` what it does. When
|
|
27
|
-
to release - after every pulse, say - is the guidance's to say too. The rules below hold as they do for `dist`: the
|
|
28
|
-
model runs the project's scripts and installs what they need itself, and what keeps running - a
|
|
29
|
-
start script, a server - is started with `activate`. Nothing built is changed.
|
|
9
|
+
Every release starts the same way: the module's last commit - what last landed whole - goes in `dist/<module>`, as below. Not everything is tried from there, though. An integration that a host application loads goes on into the host's own tree, with the host's own scripts, and then the host is started. So the model asks itself whether there is guidance for how this project is released - in what you said, the project's AGENTS.md, a skill, anything it was given - and passes it to `release` whole:
|
|
10
|
+
|
|
11
|
+
- **There is guidance.** The code goes on from `dist/<module>` as the guidance says, on your machine, from the host codebase - the git repository the project is in, or else where **turri** runs: the scripts it names, in their order, and any change it says the host needs. The code is taken from `dist`, never from `plain_modules`, where a pulse may be writing; where the host's tooling reads `plain_modules` itself, the model points it at `dist`, or does by hand from `dist` what it does. When to release - after every pulse, say - is the guidance's to say too. The rules below hold as they do for `dist`: the model runs the project's scripts and installs what they need itself, and what keeps running - a start script, a server - is started with `activate`. Nothing built is changed.
|
|
30
12
|
- **There is none.** The default: it is started from `dist/<module>`, as below, as best it can be.
|
|
31
13
|
|
|
32
|
-
Guidance is whatever says it, in any words - a line in AGENTS.md such as *integrations are released
|
|
33
|
-
with `scripts/deploy_integrations.sh`, then the app is started with `scripts/start.sh`*, or the
|
|
34
|
-
same said in the chat.
|
|
14
|
+
Guidance is whatever says it, in any words - a line in AGENTS.md such as *integrations are released with `scripts/deploy_integrations.sh`, then the app is started with `scripts/start.sh`*, or the same said in the chat.
|
|
35
15
|
|
|
36
|
-
The chat reacts to every pulse that finishes as it finishes, without waiting for you to speak: guidance
|
|
37
|
-
that says to release after a build - *release each integration once it is regenerated* - is followed then.
|
|
38
|
-
It never has to work out whether what a pulse landed is already out: `release` does. When the module's
|
|
39
|
-
last commit is what its last release in this conversation shipped, it does nothing - nothing exported,
|
|
40
|
-
nothing stopped, what runs left running - and says so; `again: true` releases it anyway, for when what
|
|
41
|
-
that release said to do was not done.
|
|
16
|
+
The chat reacts to every pulse that finishes as it finishes, without waiting for you to speak: guidance that says to release after a build - *release each integration once it is regenerated* - is followed then. It never has to work out whether what a pulse landed is already out: `release` does. When the module's last commit is what its last release in this conversation shipped, it does nothing - nothing exported, nothing stopped, what runs left running - and says so; `again: true` releases it anyway, for when what that release said to do was not done.
|
|
42
17
|
|
|
43
18
|
## What goes in dist
|
|
44
19
|
|
|
45
|
-
- **The module on top.** Code accumulates up a `requires` chain: a module starts from a copy of the
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
anything built, it takes the nearest one below it that has, and says so.
|
|
49
|
-
- **Its last commit.** Each `plain_modules/<module>` is a git repository (`.plaingit`), and every unit
|
|
50
|
-
of work starts from a commit and ends with one. What a pulse is writing right now is half-done, so it
|
|
51
|
-
is left out: deploy exports the commit - `git archive` of `code/` - which is the working tree with
|
|
52
|
-
every unstaged and untracked change put back, and no `node_modules`, `.venv`, `target` or other
|
|
53
|
-
build leftovers, whatever the stack. The working tree the pulse is using is never read or touched.
|
|
54
|
-
The harness's own files - `.turri.json`, the agents' notes - are left out too.
|
|
55
|
-
- **Replaced whole.** Each deploy stops what the last one of the module started, empties
|
|
56
|
-
`dist/<module>` and exports again. Change nothing there you want to keep. `dist/` is not added to
|
|
57
|
-
`.gitignore`: whether it is committed is yours to decide.
|
|
20
|
+
- **The module on top.** Code accumulates up a `requires` chain: a module starts from a copy of the code of the one it requires. So deploy always takes the module on top of the spec's chain - the project's `module` from `config.turri.yaml` unless another spec is named. Before the module on top has anything built, it takes the nearest one below it that has, and says so.
|
|
21
|
+
- **Its last commit.** Each `plain_modules/<module>` is a git repository (`.plaingit`), and every unit of work starts from a commit and ends with one. What a pulse is writing right now is half-done, so it is left out: deploy exports the commit - `git archive` of `code/` - which is the working tree with every unstaged and untracked change put back, and no `node_modules`, `.venv`, `target` or other build leftovers, whatever the stack. The working tree the pulse is using is never read or touched. The harness's own files - `.turri.json`, the agents' notes - are left out too.
|
|
22
|
+
- **Replaced whole.** Each deploy stops what the last one of the module started, empties `dist/<module>` and exports again. Change nothing there you want to keep. `dist/` is not added to `.gitignore`: whether it is committed is yours to decide.
|
|
58
23
|
|
|
59
24
|
## Starting it
|
|
60
25
|
|
|
61
|
-
It runs on your machine, outside the [sandbox](sandbox.md) - with your toolchains, where your
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
build that downloads packages, an image pull, a guided release's project scripts: it runs them in
|
|
69
|
-
its own shell, as any agent with a shell would, and fixes what fails. Nothing is put to you - there
|
|
70
|
-
is no dialog to answer.
|
|
71
|
-
3. **Starts what serves** with `activate`: in the background, in its own process group, its
|
|
72
|
-
output in `.turri/deploy/<module>-<name>.log`. It waits until something answers at the
|
|
73
|
-
server's URL - up to a minute - so the URL you are given has answered once; one that exits first
|
|
74
|
-
comes back with the end of its output. A port something else holds is said, with what holds it,
|
|
75
|
-
and nothing is started there: the app is not moved to a port you were not told about.
|
|
76
|
-
|
|
77
|
-
What it started is listed by the `pulses` tool and by **`/halt`**, and stopped by **`/halt activated <name>`**, by
|
|
78
|
-
`halt`, by the next deploy of the module, and when the chat exits.
|
|
26
|
+
It runs on your machine, outside the [sandbox](sandbox.md) - with your toolchains, where your browser can reach it. The chat reads how the code runs (its README, manifests and entry points), then:
|
|
27
|
+
|
|
28
|
+
1. **Checks the toolchains** it needs (`node`, `python3`, `go`, ...). One is missing: it installs it with the machine's package manager (`brew` on macOS, `apt` or `dnf` on Linux).
|
|
29
|
+
2. **Installs what it needs itself.** Dependencies into a virtual environment or `node_modules`, a build that downloads packages, an image pull, a guided release's project scripts: it runs them in its own shell, as any agent with a shell would, and fixes what fails. Nothing is put to you - there is no dialog to answer.
|
|
30
|
+
3. **Starts what serves** with `activate`: in the background, in its own process group, its output in `.turri/deploy/<module>-<name>.log`. It waits until something answers at the server's URL - up to a minute - so the URL you are given has answered once; one that exits first comes back with the end of its output. A port something else holds is said, with what holds it, and nothing is started there: the app is not moved to a port you were not told about.
|
|
31
|
+
|
|
32
|
+
What it started is listed by the `pulses` tool and by **`/halt`**, and stopped by **`/halt activated <name>`**, by `halt`, by the next deploy of the module, and when the chat exits.
|
|
79
33
|
|
|
80
34
|
## After every pulse
|
|
81
35
|
|
|
82
|
-
With `release-after-pulse: true` in `config.turri.yaml`, turri releases what each pulse lands itself, as the
|
|
83
|
-
pulse's last stage (`releasing what this pulse landed`): the pulse ends once it is released, so the
|
|
84
|
-
module's next pulse starts on what is out, and the chat - waiting on your answer to a question, say - has
|
|
85
|
-
no part in it. One release a pulse that lands, in order.
|
|
36
|
+
With `release-after-pulse: true` in `config.turri.yaml`, turri releases what each pulse lands itself, as the pulse's last stage (`releasing what this pulse landed`): the pulse ends once it is released, so the module's next pulse starts on what is out, and the chat - waiting on your answer to a question, say - has no part in it. One release a pulse that lands, in order.
|
|
86
37
|
|
|
87
|
-
The release is done by an agent on the coding model, thinking low - it follows steps, and a small model does that
|
|
88
|
-
well - the same one `turri release` runs, and it finds
|
|
89
|
-
the guidance as the chat would: what was passed to `release` earlier in the conversation, the project's
|
|
90
|
-
AGENTS.md and its skills. When nothing there says to release after a build, it releases nothing and says
|
|
91
|
-
so. Its last words go in the pulse's report - "Released after the pulse: ..." - and the chat, seeing them,
|
|
92
|
-
does not release it again. A release that fails is said there too; what the pulse landed stays.
|
|
38
|
+
The release is done by an agent on the coding model, thinking low - it follows steps, and a small model does that well - the same one `turri release` runs, and it finds the guidance as the chat would: what was passed to `release` earlier in the conversation, the project's AGENTS.md and its skills. When nothing there says to release after a build, it releases nothing and says so. Its last words go in the pulse's report - "Released after the pulse: ..." - and the chat, seeing them, does not release it again. A release that fails is said there too; what the pulse landed stays.
|
|
93
39
|
|
|
94
40
|
Off by default: without the key, releasing after a pulse is the chat's, when its guidance says so.
|
|
95
41
|
|
|
@@ -99,11 +45,6 @@ Off by default: without the key, releasing after a pulse is the chat's, when its
|
|
|
99
45
|
turri release [file.plain] [--in-module <module>] [--guidance <text>] [--model <provider/id>]
|
|
100
46
|
```
|
|
101
47
|
|
|
102
|
-
The same, without the chat: a one-off agent on `coding-model`, thinking low (or `--model`; without either,
|
|
103
|
-
pi's default) is given the project's AGENTS.md and what `--guidance <text>` says, looks for guidance in
|
|
104
|
-
them, and releases as above - as the guidance says, or to `dist/<module>` - then works out how to
|
|
105
|
-
start it and starts it here, installing what it needs without asking. It stays in the foreground with the servers'
|
|
106
|
-
output; `Ctrl-C` stops them. If it does not get there, deploy from the chat instead.
|
|
48
|
+
The same, without the chat: a one-off agent on `coding-model`, thinking low (or `--model`; without either, pi's default) is given the project's AGENTS.md and what `--guidance <text>` says, looks for guidance in them, and releases as above - as the guidance says, or to `dist/<module>` - then works out how to start it and starts it here, installing what it needs without asking. It stays in the foreground with the servers' output; `Ctrl-C` stops them. If it does not get there, deploy from the chat instead.
|
|
107
49
|
|
|
108
|
-
`turri regenerate`, `spec-diff` and `conform` end a build that landed with
|
|
109
|
-
`To try it: turri release <spec>`.
|
|
50
|
+
`turri regenerate`, `spec-diff` and `conform` end a build that landed with `To try it: turri release <spec>`.
|
package/docs/development.md
CHANGED
|
@@ -5,48 +5,26 @@ npm run typecheck # types
|
|
|
5
5
|
npm test # the whole suite, about a minute
|
|
6
6
|
```
|
|
7
7
|
|
|
8
|
-
The suite runs the projects' testing scripts on this machine, as turri does. The fixture scripts stage each run in a
|
|
9
|
-
folder of their own, as test files running side by side would otherwise share one.
|
|
8
|
+
The suite runs the projects' testing scripts on this machine, as turri does. The fixture scripts stage each run in a folder of their own, as test files running side by side would otherwise share one.
|
|
10
9
|
|
|
11
10
|
## Mutation testing
|
|
12
11
|
|
|
13
|
-
`npm run mutation` runs [Stryker](https://stryker-mutator.io) over the core of regeneration - the parts in
|
|
14
|
-
`stryker.config.mjs` - one part at a time, each part's report in `reports/mutation/<part>/`. A part with a report is
|
|
15
|
-
skipped, so a run that is stopped goes on from the part it was in; `npm run mutation -- <part>` runs one again, and
|
|
16
|
-
`npm run mutation -- --summary` sums up the reports there are. It takes hours: each part runs the suite once to find
|
|
17
|
-
which tests reach which mutant (`vitest.stryker.config.ts`, the suite without the files that run real commands behind the sandbox), then each
|
|
18
|
-
mutant against those tests. `scripts/mutation.mjs` sets two things in Stryker's vitest runner the suite needs - forked
|
|
19
|
-
workers, and a test-name filter that matches vitest 5's names - again after every `npm install`.
|
|
12
|
+
`npm run mutation` runs [Stryker](https://stryker-mutator.io) over the core of regeneration - the parts in `stryker.config.mjs` - one part at a time, each part's report in `reports/mutation/<part>/`. A part with a report is skipped, so a run that is stopped goes on from the part it was in; `npm run mutation -- <part>` runs one again, and `npm run mutation -- --summary` sums up the reports there are. It takes hours: each part runs the suite once to find which tests reach which mutant (`vitest.stryker.config.ts`, the suite without the files that run real commands behind the sandbox), then each mutant against those tests. `scripts/mutation.mjs` sets two things in Stryker's vitest runner the suite needs - forked workers, and a test-name filter that matches vitest 5's names - again after every `npm install`.
|
|
20
13
|
|
|
21
|
-
The `mutation` workflow (`.github/workflows/mutation.yml`) runs it on GitHub, started by hand: Actions, mutation, Run
|
|
22
|
-
workflow. It takes the parts to run, space-separated (empty for every part), each a job of its own side by side, on
|
|
23
|
-
four cores (`TURRI_MUTATION_CONCURRENCY`; six here). Each part's `mutation.html` and `mutation.json` are uploaded as an
|
|
24
|
-
artifact, `mutation-<part>`, and summed up on the run's page. Stryker's incremental file is cached from run to run, so
|
|
25
|
-
a run tests again only the mutants whose code or tests changed; tick `fresh` to test every one again.
|
|
14
|
+
The `mutation` workflow (`.github/workflows/mutation.yml`) runs it on GitHub, started by hand: Actions, mutation, Run workflow. It takes the parts to run, space-separated (empty for every part), each a job of its own side by side, on four cores (`TURRI_MUTATION_CONCURRENCY`; six here). Each part's `mutation.html` and `mutation.json` are uploaded as an artifact, `mutation-<part>`, and summed up on the run's page. Stryker's incremental file is cached from run to run, so a run tests again only the mutants whose code or tests changed; tick `fresh` to test every one again.
|
|
26
15
|
|
|
27
|
-
Working on turri itself, `npm link` points the global `turri` at this clone, so edits
|
|
28
|
-
take effect immediately. `npm run chat` starts pi with the extension loaded from `src/`.
|
|
16
|
+
Working on turri itself, `npm link` points the global `turri` at this clone, so edits take effect immediately. `npm run chat` starts pi with the extension loaded from `src/`.
|
|
29
17
|
|
|
30
|
-
The package on npm is built: Node runs no `.ts` file inside a `node_modules`, so `npm run build` (`scripts/build.mjs`,
|
|
31
|
-
over `tsconfig.build.json`) compiles `src/` into `dist/`, file for file - each file as deep as its source, so it finds
|
|
32
|
-
`genome/`, `stdlib/` and `.pi/` the same way - with its imports' `.ts` rewritten to `.js`, and copies the other files
|
|
33
|
-
in `src/` beside them. `npm pack` and `npm publish` run it first (`prepack`), and the package holds `dist/`, not
|
|
34
|
-
`src/`. `bin/turri.mjs` runs `src/cli.ts` where there is one and `dist/cli.js` otherwise; `cli.ts` starts pi with
|
|
35
|
-
the launcher and extension beside itself, whichever they are. To try the package as users get it:
|
|
36
|
-
`npm pack`, then `npm install -g ./turri-dev-cli-<version>.tgz`.
|
|
18
|
+
The package on npm is built: Node runs no `.ts` file inside a `node_modules`, so `npm run build` (`scripts/build.mjs`, over `tsconfig.build.json`) compiles `src/` into `dist/`, file for file - each file as deep as its source, so it finds `genome/`, `stdlib/` and `.pi/` the same way - with its imports' `.ts` rewritten to `.js`, and copies the other files in `src/` beside them. `npm pack` and `npm publish` run it first (`prepack`), and the package holds `dist/`, not `src/`. `bin/turri.mjs` runs `src/cli.ts` where there is one and `dist/cli.js` otherwise; `cli.ts` starts pi with the launcher and extension beside itself, whichever they are. To try the package as users get it: `npm pack`, then `npm install -g ./turri-dev-cli-<version>.tgz`.
|
|
37
19
|
|
|
38
20
|
## Publishing
|
|
39
21
|
|
|
40
22
|
`.github/workflows/publish.yml` publishes `@turri-dev/cli`, after the typecheck and the suite pass:
|
|
41
23
|
|
|
42
|
-
- every push or merge into `main` publishes a prerelease under the `next` dist-tag - the patch after the `latest` on
|
|
43
|
-
|
|
44
|
-
- a GitHub Release tagged `vX.Y.Z`, published by hand, publishes `X.Y.Z` as `latest` (or under `next`, if the release
|
|
45
|
-
is marked a pre-release). The tag is the version: it is set in the runner and never committed, so `package.json`'s
|
|
46
|
-
version on `main` is stale by design.
|
|
24
|
+
- every push or merge into `main` publishes a prerelease under the `next` dist-tag - the patch after the `latest` on npm, with the commit's sha: `0.1.2-next.<sha>`. `latest` is not touched; `npm install -g @turri-dev/cli@next` gets it.
|
|
25
|
+
- a GitHub Release tagged `vX.Y.Z`, published by hand, publishes `X.Y.Z` as `latest` (or under `next`, if the release is marked a pre-release). The tag is the version: it is set in the runner and never committed, so `package.json`'s version on `main` is stale by design.
|
|
47
26
|
|
|
48
|
-
The workflow signs in to npm with npm's trusted publishing (OIDC), not a token: the package's settings on npmjs.com
|
|
49
|
-
trust `turri-oss/turri`, the workflow `publish.yml` and the environment `npm`. Renaming the workflow file breaks it.
|
|
27
|
+
The workflow signs in to npm with npm's trusted publishing (OIDC), not a token: the package's settings on npmjs.com trust `turri-oss/turri`, the workflow `publish.yml` and the environment `npm`. Renaming the workflow file breaks it.
|
|
50
28
|
|
|
51
29
|
## Layout
|
|
52
30
|
|
|
@@ -82,14 +60,8 @@ trust `turri-oss/turri`, the workflow `publish.yml` and the environment `npm`. R
|
|
|
82
60
|
|
|
83
61
|
## Known edges
|
|
84
62
|
|
|
85
|
-
- Judges default to the executor's model. Real separation wants a different provider - set
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
- The
|
|
89
|
-
|
|
90
|
-
- A gate's escalation lives in memory (LangGraph's `MemorySaver`): it must be answered in the same
|
|
91
|
-
run.
|
|
92
|
-
- The gate machinery has no automated coverage; see
|
|
93
|
-
[trying the gate semantics](skills-and-gates.md#trying-the-gate-semantics).
|
|
94
|
-
- Jobs live in memory: there is no resuming a job after pi exits. The work itself is on disk, so a
|
|
95
|
-
killed job leaves a partial build rather than nothing.
|
|
63
|
+
- Judges default to the executor's model. Real separation wants a different provider - set `model:` on the gate. An unconfigured model falls back to the executor's with a note rather than failing the run.
|
|
64
|
+
- The executor keeps one session across steps and retries, so context builds up with attempts. Long skills want compaction or a session per step.
|
|
65
|
+
- A gate's escalation lives in memory (LangGraph's `MemorySaver`): it must be answered in the same run.
|
|
66
|
+
- The gate machinery has no automated coverage; see [trying the gate semantics](skills-and-gates.md#trying-the-gate-semantics).
|
|
67
|
+
- Jobs live in memory: there is no resuming a job after pi exits. The work itself is on disk, so a killed job leaves a partial build rather than nothing.
|