@turri-dev/cli 0.1.11-next.be75b46 → 0.1.11
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/README.md +7 -7
- package/dist/{spec-diff-cli.js → change-plain-cli.js} +3 -3
- package/dist/cli.js +1 -1
- package/dist/extension.js +4 -4
- package/dist/genome.js +5 -5
- package/dist/identity.js +8 -6
- package/dist/loop-cli.d.ts +1 -1
- package/dist/loop-cli.js +1 -1
- package/dist/regenerate/activity.js +2 -2
- package/dist/self-invocation.js +6 -6
- package/dist/skill.d.ts +3 -3
- package/dist/skill.js +2 -2
- package/dist/spec-tools.js +2 -2
- package/dist/stacks.js +1 -1
- package/dist/tools.js +1 -1
- package/docs/README.md +13 -13
- package/docs/authoring-plain.md +33 -33
- package/docs/config.md +25 -25
- package/docs/deploy.md +5 -5
- package/docs/development.md +12 -12
- package/docs/headless.md +18 -18
- package/docs/hosting.md +14 -14
- package/docs/images/how-turri-works.svg +1 -1
- package/docs/installation.md +13 -13
- package/docs/parser.md +6 -6
- package/docs/regenerating.md +78 -78
- package/docs/sandbox.md +7 -7
- package/docs/skills-and-gates.md +19 -19
- package/docs/theming.md +12 -12
- package/docs/using.md +50 -50
- package/genome/skills/brood/SKILL.md +11 -11
- package/genome/skills/brood/references/product.md +4 -4
- package/genome/skills/brood/references/testing.md +1 -1
- package/genome/skills/bud/SKILL.md +6 -6
- package/genome/skills/mature/SKILL.md +4 -4
- package/genome/skills/spawn/SKILL.md +4 -4
- package/package.json +1 -1
- /package/dist/{spec-diff-cli.d.ts → change-plain-cli.d.ts} +0 -0
package/docs/authoring-plain.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Authoring \*\*\*plain
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
turri builds code from [\*\*\*plain](https://plainlang.org/docs/) - its documentation is the language's whole reference. Regenerating turns \*\*\*plain into code; authoring is the half that decides what gets built. The code is only ever as good as the \*\*\*plain description - a fact in the wrong section is silently ignored, a functional spec that is too big comes out half-built, two functional specs that contradict each other break each other's tests. So this repo carries as much for writing \*\*\*plain as for regenerating it: the authoring rules, a library of skills that apply them, and independent review of what they write.
|
|
4
4
|
|
|
5
|
-
The rule underneath all of it:
|
|
5
|
+
The rule underneath all of it: **\*\*\*plain is the source of truth**. The generated code in `plain_modules/` is never edited by hand. A bug is fixed in \*\*\*plain, and a change that is wanted goes into \*\*\*plain - that is what persists and what the next regeneration builds from.
|
|
6
6
|
|
|
7
7
|
## A \*\*\*plain project
|
|
8
8
|
|
|
@@ -16,7 +16,7 @@ my-project/
|
|
|
16
16
|
plain_modules/ # generated - code, tests, history; never edited by hand
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
## What
|
|
19
|
+
## What \*\*\*plain is made of
|
|
20
20
|
|
|
21
21
|
A `.plain` file is one module: optional YAML frontmatter, then up to four sections, in this order.
|
|
22
22
|
|
|
@@ -39,13 +39,13 @@ The frontmatter connects modules:
|
|
|
39
39
|
| `exported_concepts` | which concepts a module that `requires` this one may use |
|
|
40
40
|
| `required_concepts` | concepts an import module expects the importing module to define |
|
|
41
41
|
|
|
42
|
-
Beyond that:
|
|
42
|
+
Beyond that: \*\*\*plain links to files under `resources/` with markdown link syntax, and the file's contents go to the coding agents with the \*\*\*plain description; lines starting with `>` are comments for people; and files are processed with Liquid first, so a template can be included with parameters.
|
|
43
43
|
|
|
44
|
-
**Section ownership is the rule that bites.**
|
|
44
|
+
**Section ownership is the rule that bites.** turri reads each kind of fact only from the section that owns it. A tech choice written into a functional spec, or a behaviour written into the implementation reqs, is not flagged - it is simply not read.
|
|
45
45
|
|
|
46
46
|
## The standard library
|
|
47
47
|
|
|
48
|
-
turri ships a standard library of import modules in `stdlib/` that settle everything about a generic piece of software on one stack except what it does: its language and framework, layout, configuration, error handling, logging, shutdown, and how it is unit and conformance tested. A
|
|
48
|
+
turri ships a standard library of import modules in `stdlib/` that settle everything about a generic piece of software on one stack except what it does: its language and framework, layout, configuration, error handling, logging, shutdown, and how it is unit and conformance tested. A module's \*\*\*plain imports one and writes only its own concepts and functional specs:
|
|
49
49
|
|
|
50
50
|
```plain
|
|
51
51
|
---
|
|
@@ -82,19 +82,19 @@ It is built in three layers, and a stack imports the other two:
|
|
|
82
82
|
|
|
83
83
|
Each conformance template imports its kind's `conformance/common`: a backend's tests start the built service on a free port and reach it over HTTP only, checking a failure by status and `error.code`; a frontend's run the served build in Chromium through Playwright with the backend stood in; a command-line tool's run the built tool as a process; a library's go through its public entry point.
|
|
84
84
|
|
|
85
|
-
- **Conformance tests apart.**
|
|
86
|
-
- **A reserved name.** An import that starts with `stdlib/` is always turri's template, never a file of the project's. A project with a module at such a path - `stdlib/backend/python-fastapi.plain` beside the
|
|
87
|
-
- **No concepts.** Its requirements are on the predefined `:Implementation:`, `:UnitTests:` and `:ConformanceTests:` only, so it never collides with
|
|
85
|
+
- **Conformance tests apart.** \*\*\*plain without the conformance template has no test reqs, so no conformance tests are written or run for it. Turning them on later is adding that one import.
|
|
86
|
+
- **A reserved name.** An import that starts with `stdlib/` is always turri's template, never a file of the project's. A project with a module at such a path - `stdlib/backend/python-fastapi.plain` beside the project's \*\*\*plain, in its `template/` folder or in `PLAIN_TEMPLATE_DIRS` - gets an error saying the name is reserved, so which one the project's \*\*\*plain builds on never depends on what is on disk beside it.
|
|
87
|
+
- **No concepts.** Its requirements are on the predefined `:Implementation:`, `:UnitTests:` and `:ConformanceTests:` only, so it never collides with \*\*\*plain's own definitions.
|
|
88
88
|
- **Pinned to a toolchain.** It names its stack's toolchain - Python 3.12, Node.js 24, Java 21, Go 1.25, Rust - which the agents use from this machine; `turri doctor` says when the machine lacks it.
|
|
89
89
|
- **Not storage, not the testing scripts.** A module with a database says which on top of its stack. It still needs its unit testing script, and a conformance testing script when it has conformance tests.
|
|
90
|
-
- **Known to the agents.** The `stdlib` rule, in every
|
|
91
|
-
- **Only what this machine can build.** The agents use this machine's toolchains and install none, so a Go stack on a laptop without Go stops at its first build. Every
|
|
90
|
+
- **Known to the agents.** The `stdlib` rule, in the system prompt of every agent that writes \*\*\*plain, says when to import which, and lists every template with what it is and the folder it is in, read from `stdlib/` when the rules load. `spawn` and `brood` import a stack when the one chosen is in it, and its conformance template when conformance tests are on.
|
|
91
|
+
- **Only what this machine can build.** The agents use this machine's toolchains and install none, so a Go stack on a laptop without Go stops at its first build. Every agent that writes \*\*\*plain, and the conversation, are told which of the standard library's languages the machine can build now - Python needs `uv`, TypeScript and every frontend `node` and `npm`, Go `go`, Rust `cargo`, Java a JDK (`src/stack.ts`, `toolchainsBlock`) - and `spawn` and `brood` offer, and choose, only stacks in those. A stack the person names in a language the machine lacks is not refused: they are told what to install first, and that `turri doctor` checks it.
|
|
92
92
|
|
|
93
93
|
A requirement beyond the stack - storage, an outside service - is added on top of it. A module that differs from its stack on something the stack settles - another framework, another layout - writes its own instead: an import cannot be taken back in part.
|
|
94
94
|
|
|
95
95
|
## The rules
|
|
96
96
|
|
|
97
|
-
`genome/rules/` holds the authoring rules. They are in the system prompt of every agent that writes
|
|
97
|
+
`genome/rules/` holds the authoring rules. They are in the system prompt of every agent that writes \*\*\*plain - the conversation, the interview skills, the reviewers - so they are not something an agent has to decide to go and read.
|
|
98
98
|
|
|
99
99
|
| rule | covers |
|
|
100
100
|
| --- | --- |
|
|
@@ -103,40 +103,40 @@ A requirement beyond the stack - storage, an outside service - is added on top o
|
|
|
103
103
|
| `func-specs.md` | voice, the complexity limit, chronological order, no conflicts, language agnosticism, testability, acceptance tests |
|
|
104
104
|
| `impl-reqs.md` | HOW not WHAT, unit tests live here, what belongs and what does not |
|
|
105
105
|
| `test-reqs.md` | conformance tests only, what belongs, test types |
|
|
106
|
-
| `concise-specs.md` (+ two example banks) | keeping
|
|
106
|
+
| `concise-specs.md` (+ two example banks) | keeping \*\*\*plain short enough for a person to review: no obvious lines, plain words, no uncheckable adjectives, no hedging |
|
|
107
107
|
| `bullet-continuation.md` | bullets and continuation lines in every section |
|
|
108
108
|
| `linked-resources.md` | a linked resource is one text file on disk, or a PNG or JPEG image for a model that reads images; protocol artifacts are linked, never transcribed |
|
|
109
109
|
| `import-modules.md`, `requires-modules.md` | the two ways modules build on each other |
|
|
110
110
|
| `exported-concepts.md`, `required-concepts.md` | which concepts cross module boundaries |
|
|
111
|
-
| `integrations.md` (+ standalone, embedded, embedded testing) |
|
|
112
|
-
| `turri-regeneration.md` | turri's model of itself: a
|
|
111
|
+
| `integrations.md` (+ standalone, embedded, embedded testing) | \*\*\*plain for REST API integrations, deployed standalone or embedded in an existing codebase |
|
|
112
|
+
| `turri-regeneration.md` | turri's model of itself: a \*\*\*plain change regenerated as a \*\*\*plain diff, wherever it sits, in the chain's tip; what each kind of change sets off; what a coding agent sees; how bad code is fixed; where the cost is - so \*\*\*plain is placed by what it means, never to spare regeneration |
|
|
113
113
|
| `stdlib.md` | the standard library: when to import which template, and every template with what it is and where it is, read from `stdlib/` |
|
|
114
114
|
|
|
115
|
-
The ones that shape
|
|
115
|
+
The ones that shape \*\*\*plain most:
|
|
116
116
|
|
|
117
117
|
- **One functionality is at most ~200 lines of code.** A bigger one is split before it is written (`analyze-if-func-spec-too-complex`, `break-down-func-spec`).
|
|
118
|
-
- **Functional specs are in build order.** Each is
|
|
118
|
+
- **Functional specs are in build order.** Each is regenerated on top of the ones before it - which is what a functional spec may assume, not what a change costs: a functional spec inserted anywhere is regenerated alone.
|
|
119
119
|
- **They state facts, with a concrete subject.** "A :User: can add a :Task:" - not "Implement adding tasks", not "The system should…".
|
|
120
120
|
- **Nothing a test cannot check.** No `robust`, `seamless`, `as appropriate`; state the checkable fact or cut the word.
|
|
121
|
-
- **No two specs contradict each other.** A conflict is found and resolved when a spec is added, not when its tests fail.
|
|
121
|
+
- **No two functional specs contradict each other.** A conflict is found and resolved when a functional spec is added, not when its tests fail.
|
|
122
122
|
|
|
123
|
-
## Writing
|
|
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. Two build a project from scratch, and write each
|
|
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. 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 what your message leaves open:
|
|
126
126
|
|
|
127
|
-
| skill | phases | how a
|
|
127
|
+
| skill | phases | how a \*\*\*plain change is written |
|
|
128
128
|
| --- | --- | --- |
|
|
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
|
|
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 only when the user named one this machine cannot build - otherwise turri chooses one; the stack and the unit tests are written as files, with conformance tests off unless the user asks for them; then a
|
|
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 only when the user named one this machine cannot build - otherwise turri chooses one; 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
|
-
`mature` starts from
|
|
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
|
|
|
134
|
-
For an existing project, `bud` works the same way, scoped to one feature: intent → scope → product. It first asks how many questions the product phase may ask - light, medium, thorough or best judgement, as `brood` does - then a short feature-intent interview, then product questions - a trigger and its outcome, an edge case, a rule - and every answer is a
|
|
134
|
+
For an existing project, `bud` works the same way, scoped to one feature: intent → scope → product. It first asks how many questions the product phase may ask - light, medium, thorough or best judgement, as `brood` does - then a short feature-intent interview, then product questions - a trigger and its outcome, an edge case, a rule - and every answer is a \*\*\*plain change, a git diff written with `change_plain` and built the moment it is written, before the next question. What the questions leave open it decides itself, a \*\*\*plain change each. A change to something already specified, built or still to build, is put to the user first and is a \*\*\*plain diff too: what is left to build is worked out again from \*\*\*plain. It ends on the person's confirmation of a short summary of the feature's changes.
|
|
135
135
|
|
|
136
136
|
What keeps the interview honest is the harness, not the interviewer:
|
|
137
137
|
|
|
138
|
-
- **Every question offers choices** (`ask_user` refuses a question without them), and each answer maps to one
|
|
139
|
-
- **Every answer is written before the next question.** In the product phase of `brood` and `bud`, `ask_user` refuses a new question until the last answer is a
|
|
138
|
+
- **Every question offers choices** (`ask_user` refuses a question without them), and each answer maps to one \*\*\*plain change.
|
|
139
|
+
- **Every answer is written before the next question.** In the product phase of `brood` and `bud`, `ask_user` refuses a new question until the last answer is a \*\*\*plain change - see [skills and gates](skills-and-gates.md).
|
|
140
140
|
- **Each phase ends on the person's confirmation** of a short summary, not on the interviewer's word.
|
|
141
141
|
|
|
142
142
|
## The skills
|
|
@@ -146,21 +146,21 @@ Every skill in `genome/skills/` can be run from a conversation; most are also us
|
|
|
146
146
|
| to… | skills |
|
|
147
147
|
| --- | --- |
|
|
148
148
|
| start a project | `brood`, `spawn`, `init-plain-project` |
|
|
149
|
-
| make
|
|
150
|
-
| add to
|
|
149
|
+
| make rough \*\*\*plain build | `mature` |
|
|
150
|
+
| add to \*\*\*plain | `bud`, `add-functional-spec`, `add-functional-specs`, `add-concept`, `add-implementation-requirement`, `add-test-requirement`, `add-acceptance-test`, `add-resource`, `add-template` |
|
|
151
151
|
| check what is written | `analyze-if-func-spec-too-complex`, `analyze-2-func-specs`, `analyze-func-specs`, `resolve-section-ownership` |
|
|
152
152
|
| fix what is written | `break-down-func-spec`, `resolve-spec-conflict`, `debug-specs` |
|
|
153
153
|
| restructure modules | `create-import-module`, `create-requires-module`, `refactor-module`, `consolidate-concepts` |
|
|
154
154
|
| set up the project to build | `implement-unit-testing-script`, `implement-conformance-testing-script`, `check-plain-env` |
|
|
155
155
|
|
|
156
|
-
`debug-specs` is the one for a running application that misbehaves: it reads the generated code to find the cause, traces it back to
|
|
156
|
+
`debug-specs` is the one for a running application that misbehaves: it reads the generated code to find the cause, traces it back to \*\*\*plain, and fixes only the `.plain` files.
|
|
157
157
|
|
|
158
|
-
## Checking
|
|
158
|
+
## Checking \*\*\*plain
|
|
159
159
|
|
|
160
160
|
```bash
|
|
161
161
|
turri validate app.plain # or validate in a conversation
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
It parses
|
|
164
|
+
It parses \*\*\*plain with this repo's own parser, resolves its imports and required modules, and reports every syntax, concept and structure error with its line - no model, no API key. The interview skills run it before a phase ends, and `change_plain` refuses a change that leaves a file that does not parse. Pass the project directory to check every module at once.
|
|
165
165
|
|
|
166
|
-
What `check` cannot see - a fact in the wrong section, a spec that is too big, two that conflict, wording no test can check - is what the rules, the skills and the reviewers are for.
|
|
166
|
+
What `check` cannot see - a fact in the wrong section, a functional spec that is too big, two that conflict, wording no test can check - is what the rules, the skills and the reviewers are for.
|
package/docs/config.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# The project config
|
|
2
2
|
|
|
3
|
-
A project says how its
|
|
3
|
+
A project says how its \*\*\*plain is 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](https://pi.dev)'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
4
|
|
|
5
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`:
|
|
6
6
|
|
|
7
|
-
| vendor | harness-model | coding-model | key pi reads |
|
|
7
|
+
| vendor | harness-model | coding-model | key [pi](https://pi.dev) reads |
|
|
8
8
|
| --- | --- | --- | --- |
|
|
9
9
|
| `anthropic` | `anthropic/claude-opus-5-5` | `anthropic/claude-haiku-5-5` | `ANTHROPIC_API_KEY` |
|
|
10
10
|
| `openai` | `openai/gpt-6-astra` | `openai/gpt-6-luna` | `OPENAI_API_KEY` |
|
|
@@ -13,13 +13,13 @@ A project says how its specs are built in `config.turri.yaml`, at the project ro
|
|
|
13
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` |
|
|
14
14
|
| `other` | `anthropic/claude-opus-5-5` | `google/gemini-3.1-flash-lite` | `ANTHROPIC_API_KEY`, `GEMINI_API_KEY` |
|
|
15
15
|
|
|
16
|
-
Amazon Bedrock asks three more things, from pi's catalogue: whose models (`--maker`) - any maker pi has there, Anthropic, OpenAI, xAI, Meta, Mistral, Qwen, DeepSeek, Amazon, Moonshot, Z.ai, ... - the geography of the inference profile they run in (`--region`) - `global`, `us`, `eu`, `jp`, `au`, `apac`, `in`, `ca` or `us-gov`, as the maker's models are served, or `in-region`, a model served in the AWS region it is called in - and which two. The pair offered is turri's own where it has one - the table's, for Anthropic's and OpenAI's in the geographies they are served in - and otherwise the catalogue's: the strongest model that reasons to talk to, by price, and the cheapest costing at least a fifth of it to code, ties to the newest. Enter takes it; `c` chooses each from the maker's models there. It says which `AWS_REGION` to set for the geography: pi calls Bedrock in `AWS_REGION`, else the profile's region, else `us-east-1` - so every geography but `global`, `us` and `in-region` needs it set (`eu-central-1` for `eu`, `ap-northeast-1` for `jp`, `ap-southeast-2` for `au`, `ap-southeast-1` for `apac`, `ap-south-1` for `in`, `ca-central-1` for `ca`, `us-gov-west-1` for `us-gov`). A `config.turri.yaml` already there keeps everything but its two models, which it sets; `--force` writes the whole file again.
|
|
16
|
+
Amazon Bedrock asks three more things, from [pi](https://pi.dev)'s catalogue: whose models (`--maker`) - any maker [pi](https://pi.dev) has there, Anthropic, OpenAI, xAI, Meta, Mistral, Qwen, DeepSeek, Amazon, Moonshot, Z.ai, ... - the geography of the inference profile they run in (`--region`) - `global`, `us`, `eu`, `jp`, `au`, `apac`, `in`, `ca` or `us-gov`, as the maker's models are served, or `in-region`, a model served in the AWS region it is called in - and which two. The pair offered is turri's own where it has one - the table's, for Anthropic's and OpenAI's in the geographies they are served in - and otherwise the catalogue's: the strongest model that reasons to talk to, by price, and the cheapest costing at least a fifth of it to code, ties to the newest. Enter takes it; `c` chooses each from the maker's models there. It says which `AWS_REGION` to set for the geography: [pi](https://pi.dev) calls Bedrock in `AWS_REGION`, else the profile's region, else `us-east-1` - so every geography but `global`, `us` and `in-region` needs it set (`eu-central-1` for `eu`, `ap-northeast-1` for `jp`, `ap-southeast-2` for `au`, `ap-southeast-1` for `apac`, `ap-south-1` for `in`, `ca-central-1` for `ca`, `us-gov-west-1` for `us-gov`). A `config.turri.yaml` already there keeps everything but its two models, which it sets; `--force` writes the whole file again.
|
|
17
17
|
|
|
18
|
-
`--harness-model` and `--coding-model` name the two models instead, for any vendor: provider/model-id without a thinking level - `turri init-config --harness-model amazon-bedrock/global.xai.grok-4.7 --coding-model amazon-bedrock/global.xai.grok-4.6`. They are written wherever the vendor's own would be - the two models with their thinking, the commented-out `judge-model` and `models:` examples - and the vendor, maker and geography are read from them. `--judge-model` names the strong one the judging examples use, the harness model unless given. Each is checked against pi's catalogue first: one it does not have, or that is not a chat model, is named, with the closest it has, and nothing is written.
|
|
18
|
+
`--harness-model` and `--coding-model` name the two models instead, for any vendor: provider/model-id without a thinking level - `turri init-config --harness-model amazon-bedrock/global.xai.grok-4.7 --coding-model amazon-bedrock/global.xai.grok-4.6`. They are written wherever the vendor's own would be - the two models with their thinking, the commented-out `judge-model` and `models:` examples - and the vendor, maker and geography are read from them. `--judge-model` names the strong one the judging examples use, the harness model unless given. Each is checked against [pi](https://pi.dev)'s catalogue first: one it does not have, or that is not a chat model, is named, with the closest it has, and nothing is written.
|
|
19
19
|
|
|
20
20
|
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)).
|
|
21
21
|
|
|
22
|
-
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.
|
|
22
|
+
They are an example, not a requirement - any model [pi](https://pi.dev) supports works, signed in any way [pi](https://pi.dev) 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](https://pi.dev) 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.
|
|
23
23
|
|
|
24
24
|
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.
|
|
25
25
|
|
|
@@ -27,12 +27,12 @@ Beside a `config.yaml` - another tool's, say - the new file takes from it the ke
|
|
|
27
27
|
|
|
28
28
|
## Where it is read from
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
\*\*\*plain belongs to its **project**: the nearest folder, from its 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 \*\*\*plain description'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 \*\*\*plain in `plain/`, with `plain/config.turri.yaml`, builds `plain/app.plain` by `plain/config.turri.yaml` even when `turri` runs in the folder above.
|
|
31
31
|
|
|
32
32
|
When it is read:
|
|
33
33
|
|
|
34
|
-
- **In the chat**, afresh: the chat's agent is told what it says on every turn, and each
|
|
35
|
-
- **On the command line**, once, when the command starts. `turri regenerate` takes `module:` from the folder it is run in, and the rest from
|
|
34
|
+
- **In the chat**, afresh: the chat's agent is told what it says on every turn, and each regeneration reads it when it is queued. An edit to the file holds from the next turn and the next regeneration, with no restart. The agent is told the config of the session's folder and of the projects one folder down.
|
|
35
|
+
- **On the command line**, once, when the command starts. `turri regenerate` takes `module:` from the folder it is run in, and the rest from \*\*\*plain's own project.
|
|
36
36
|
|
|
37
37
|
## Changing it from the chat
|
|
38
38
|
|
|
@@ -80,15 +80,15 @@ models: # each agent role's model, thinking and tur
|
|
|
80
80
|
| key | what it sets | left out |
|
|
81
81
|
| --- | --- | --- |
|
|
82
82
|
| `module` | the `.plain` file `turri regenerate` and the chat's `regenerate` build when none is named, from the project root | a file has to be named |
|
|
83
|
-
| `harness-model` | the model `turri` starts on - the one you talk to - and, in the conversation, the planner that cuts the work into jobs (on whatever model the chat is on when it plans); under `turri regenerate`, the planner too | pi's configured model |
|
|
84
|
-
| `coding-model` | every
|
|
83
|
+
| `harness-model` | the model `turri` starts on - the one you talk to - and, in the conversation, the planner that cuts the work into jobs (on whatever model the chat is on when it plans); under `turri regenerate`, the planner too | [pi](https://pi.dev)'s configured model |
|
|
84
|
+
| `coding-model` | every regeneration: functionalities, \*\*\*plain diffs, conformance tests, repairs, planning \*\*\*plain diffs, the explorer | `harness-model` |
|
|
85
85
|
| `judge-model` | the judge and the test review of a conformance run | `coding-model` |
|
|
86
86
|
| `conformance-tests` | `all` (or `true`): conformance tests for every functional spec of every module with test reqs, written once each module's code is built, before anything is built on it. `chosen`: for the functional specs chosen - every one with acceptance tests, and those the chooser picks as each code pulse ends, from what that pulse regenerated. `module`: the same, but the chooser is asked once, when the whole module is regenerated, and plans the conformance pulses too. Under both, the choice is made inside the pulse, before anything is built on the module, and the pulse's report says what was chosen and why; those the person asks for with `conform` are written too; once chosen, a functional spec keeps them, and they are rewritten when it changes - see [who chooses, and when](regenerating.md#conformance-tests-in-the-work-loop). `false`: none written, and none of the existing ones run - until the conversation asks with `conform` | `false` |
|
|
87
87
|
| `conformance-budget` | under `conformance-tests: chosen` or `module`: how many of a module's functional specs may be chosen for conformance tests, beside those with acceptance tests - a count (`2`) or a share of its functional specs (`30%`, rounded up, at least one). Every choice for the module counts, whenever it was made; the chooser is told what is left, and can choose no more. Your own `conform` is not limited. A stack's `config.turri.<stack>.yaml` can set its own | no limit |
|
|
88
88
|
| `review` | `true` or `false`: whether the code and its unit tests - and the conformance tests - are reviewed once they pass: two reviews at most, the second weighed by the arbiter; off, a job lands once its tests pass. A module's first pulse of one functional spec - the project set up and the smallest thing that runs - lands on its unit tests with no review - see [regenerating the code](regenerating.md#the-code-and-its-unit-tests-are-reviewed) | `false` |
|
|
89
89
|
| `mutation-testing` | `true` or `false`: whether the coding agent and the reviewer have `can_it_fail` - one change put in the code for one run of the unit testing script, to see that a test catches it; on a copy of the code, or in place and put back after the run (see [regenerating the code](regenerating.md#checking-its-own-work)). `turri regenerate --mutation-testing false` for one run | `true` |
|
|
90
|
-
| `rules-off` | a list of rule names - `integrations`, `concise-specs`, the files of `genome/rules/` without `.md` - left out of the conversation's prompt and every
|
|
91
|
-
| `allow-to-stop-jobs` | `true` or `false`: whether turri stops a running job
|
|
90
|
+
| `rules-off` | a list of rule names - `integrations`, `concise-specs`, the files of `genome/rules/` without `.md` - left out of the conversation's prompt and every \*\*\*plain-writing agent's: a rule this project's own skills or AGENTS.md replace, such as one that says to probe a live API before any \*\*\*plain is written. The project's alone | none |
|
|
91
|
+
| `allow-to-stop-jobs` | `true` or `false`: whether turri stops a running job \*\*\*plain has moved on from - a functional spec it regenerates changed, or a file one links was edited - rolls it back and regenerates \*\*\*plain as it now is. `false`: the job runs to its end and lands, and what changed since is regenerated on top of it by the next job - see [regenerating the code](regenerating.md). Your own `halt` stops a job either way | `true` |
|
|
92
92
|
| `release-after-pulse` | `true` or `false`: whether every pulse that lands code releases it, in the chat, as its last stage - before the module's next pulse starts, whatever the chat is doing: an agent on the coding model looks for the project's release guidance as the chat does (what was passed to `release` this conversation, AGENTS.md, the project's skills) and, when it says to release after a build, does what it says - see [deploy](deploy.md#after-every-pulse). One release a pulse that lands; a release that fails is said in the pulse's report, and what it landed stays | `false` |
|
|
93
93
|
| `unittests-script` | the unit testing script, by path from the project root - it runs the code's static checks too, exiting 80 when only they fail (see [the static checks](regenerating.md#the-static-checks)) | looked for - see below |
|
|
94
94
|
| `conformance-tests-script` | the conformance testing script, by path from the project root | looked for - see below |
|
|
@@ -98,7 +98,7 @@ models: # each agent role's model, thinking and tur
|
|
|
98
98
|
| `debug` | `true` or `false`: whether turri keeps what it writes only for a person debugging it - every agent's whole log and saved session, each pulse's log, the whole outputs of its test runs and services, its agents' temporary files, and the dependencies installed in the modules a chain has left behind. `false`: only what turri reads to work is kept. `TURRI_DEBUG=1` - or `turri --debug` - turns it on for one run, and `TURRI_DEBUG=0` off; the project's alone. See [debug mode](#debug-mode) | `false` |
|
|
99
99
|
| `cache-keep` | how many megabytes of package caches the project keeps - `plain_modules/.turri/cache`, and the caches in the agents' home folders: past it, the least recently written - by the newest file in each - are removed when a run starts its first agent command, each downloaded again when it is wanted; `0` keeps none; the project's alone | 4096 |
|
|
100
100
|
| `max-specs-per-pulse` | the most functional specs the planner groups into one pulse - what builds one feature goes together, up to this many; a stack's file wins | 3 |
|
|
101
|
-
| `max-lines-per-pulse` | the most lines of
|
|
101
|
+
| `max-lines-per-pulse` | the most lines of \*\*\*plain in one pulse - its functional specs with the definitions they bring; a group past it is split again, a functional spec a pulse; a stack's file wins | 120 |
|
|
102
102
|
| `parallel-jobs` | how many jobs the chat runs at once - modules that share nothing build side by side up to it; read when the chat starts, from the folder it starts in | half this machine's cores, between one and four - see [how many jobs at once](#how-many-jobs-at-once) |
|
|
103
103
|
| `agent-env` | credentials the agents' commands need while they work - a live API probed, tests run against a real service: `files: [...]`, dotenv files by path from the project root, every variable in them; `vars: [...]`, variables by name from the environment turri was started in. A stack's `config.turri.<stack>.yaml` adds its own to the project's. See [credentials for the agents](#credentials-for-the-agents) | none: an agent's commands get no credential |
|
|
104
104
|
| `toolchains` | folders of this machine an agent's commands may read beside the system's, the `PATH`'s and those the toolchain variables point at - a toolchain installed somewhere unusual (`[/srv/zig]`). A stack's add to the project's. See [the OS sandbox](sandbox.md#the-os-sandbox) | none |
|
|
@@ -130,9 +130,9 @@ Keys are written with dashes; underscores are read the same (`conformance_tests`
|
|
|
130
130
|
|
|
131
131
|
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.
|
|
132
132
|
|
|
133
|
-
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
|
|
133
|
+
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 \*\*\*plain that leaves 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](https://pi.dev) sets it.
|
|
134
134
|
|
|
135
|
-
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.
|
|
135
|
+
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](https://pi.dev) sends them none.
|
|
136
136
|
|
|
137
137
|
## How many jobs at once
|
|
138
138
|
|
|
@@ -152,23 +152,23 @@ judge-model: google/gemini-3.1-pro:high # the same, as one string
|
|
|
152
152
|
harness-model: anthropic/claude-opus-5-5 # a model alone
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
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}`
|
|
155
|
+
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}` regenerates on the harness model, thinking less.
|
|
156
156
|
|
|
157
157
|
They are defaults. What is asked for wins over them:
|
|
158
158
|
|
|
159
159
|
| model | wins over the config |
|
|
160
160
|
| --- | --- |
|
|
161
|
-
| harness | `turri --harness-model <m>` (or pi's own `--model`), and pi's `/model` in the conversation |
|
|
161
|
+
| harness | `turri --harness-model <m>` (or [pi](https://pi.dev)'s own `--model`), and [pi](https://pi.dev)'s `/model` in the conversation |
|
|
162
162
|
| coding | `turri --coding-model <m>`, `engine` in the conversation |
|
|
163
163
|
| judge | - |
|
|
164
164
|
|
|
165
|
-
`turri regenerate`, `conform` and `
|
|
165
|
+
`turri regenerate`, `conform` and `change-plain` 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.
|
|
166
166
|
|
|
167
167
|
A job keeps the model it was queued with: choosing another holds for what is queued after.
|
|
168
168
|
|
|
169
169
|
## Conformance tests
|
|
170
170
|
|
|
171
|
-
`conformance-tests:` is the one switch, and the chat, every
|
|
171
|
+
`conformance-tests:` is the one switch, and the chat, every regeneration 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 `change-plain` - for that run, the file left as it is - a regeneration does otherwise.
|
|
172
172
|
|
|
173
173
|
`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.
|
|
174
174
|
|
|
@@ -182,7 +182,7 @@ A build needs a unit testing script - and, with conformance on, a conformance te
|
|
|
182
182
|
|
|
183
183
|
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.
|
|
184
184
|
|
|
185
|
-
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
|
|
185
|
+
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 \*\*\*plain. What they are and how they run is in [regenerating the code](regenerating.md#the-testing-scripts).
|
|
186
186
|
|
|
187
187
|
## Debug mode
|
|
188
188
|
|
|
@@ -241,17 +241,17 @@ coding-model:
|
|
|
241
241
|
|
|
242
242
|
Which stack builds a module, first match wins:
|
|
243
243
|
|
|
244
|
-
- **The one a call names.** `regenerate`, `conform`, `glimpse` and `
|
|
244
|
+
- **The one a call names.** `regenerate`, `conform`, `glimpse` and `change_plain` take a `stack`; the chat's model passes it for a module whose stack has a name of its own, leaving the session's choice as it is.
|
|
245
245
|
- **The stack named after the module** - `config.turri.backend.yaml` builds `backend.plain` - with nothing to choose or pass. Name each stack after the module it builds, and a backend and a frontend are each built with their own, side by side - in the chat, in a brood as each change is written, and on the command line.
|
|
246
|
-
- **The one chosen for the session** - 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. `/stack` alone says which is chosen now. On the command line, with `--stack <name>` on any command - `turri regenerate`, `conform`, `
|
|
246
|
+
- **The one chosen for the session** - 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. `/stack` alone says which is chosen now. On the command line, with `--stack <name>` on any command - `turri regenerate`, `conform`, `change-plain`, `glimpse`, `release`, `cultivate` - and on `turri --stack backend` for the chat; or with `TURRI_STACK` in the environment.
|
|
247
247
|
|
|
248
248
|
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.
|
|
249
249
|
|
|
250
250
|
How a stack's config is made:
|
|
251
251
|
|
|
252
|
-
- **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
|
|
253
|
-
- **Pinned to a module when it is asked for.** A module is built with the stack it was asked for with, from its first pulse to its last: the pulses planned after it, its test runs, the scripts found, its plans and its conformance tests, whatever stack is chosen meanwhile. A pulse waiting for a free slot keeps the stack it was queued with. A change to its
|
|
254
|
-
- **Refused with none, when that cannot build.** In a project of stacks, a module asked for with no stack - none named, none named after it, none chosen - is refused before anything is planned when `config.turri.yaml` alone names no unit testing script: every pulse would stop for want of one. The refusal names the stacks and the script each names. A
|
|
252
|
+
- **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 regenerates on the project's coding model, thinking `high`.
|
|
253
|
+
- **Pinned to a module when it is asked for.** A module is built with the stack it was asked for with, from its first pulse to its last: the pulses planned after it, its test runs, the scripts found, its plans and its conformance tests, whatever stack is chosen meanwhile. A pulse waiting for a free slot keeps the stack it was queued with. A change to its \*\*\*plain keeps its stack - unless it was built with none and has a stack of its own now; asked for again, its stack is worked out again. What `regenerate` says back names each module's stack, and so does a pulse's report.
|
|
254
|
+
- **Refused with none, when that cannot build.** In a project of stacks, a module asked for with no stack - none named, none named after it, none chosen - is refused before anything is planned when `config.turri.yaml` alone names no unit testing script: every pulse would stop for want of one. The refusal names the stacks and the script each names. A \*\*\*plain change `change_plain` writes is never refused: it is written, and said not to be built yet - passed the stack, everything written is built. `stack: none` builds with `config.turri.yaml` alone all the same.
|
|
255
255
|
- **The project's alone.** `module:`, `harness-model:`, `parallel-jobs:`, `rules-off:`, `compact-at:`, `ledger-keep:`, `debug:` and `cache-keep:` 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.
|
|
256
256
|
|
|
257
257
|
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, each stack named after the module it builds.
|
package/docs/deploy.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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
|
|
3
|
+
Ask to try it - "let me try it", "run the app" - at any time, even while a regeneration 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.
|
|
4
4
|
|
|
5
|
-
Every pulse that lands code - a
|
|
5
|
+
Every pulse that lands code - a regeneration, a \*\*\*plain 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 regeneration's conformance tests follow as a pulse of their own, the conformance pulse says it, once they pass too.
|
|
6
6
|
|
|
7
7
|
## When the project says how it is released
|
|
8
8
|
|
|
@@ -17,7 +17,7 @@ The chat reacts to every pulse that finishes as it finishes, without waiting for
|
|
|
17
17
|
|
|
18
18
|
## What goes in dist
|
|
19
19
|
|
|
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
|
|
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 `requires` chain - the project's `module` from `config.turri.yaml` unless another module's \*\*\*plain is named. Before the module on top has anything built, it takes the nearest one below it that has, and says so.
|
|
21
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
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.
|
|
23
23
|
|
|
@@ -45,6 +45,6 @@ Off by default: without the key, releasing after a pulse is the chat's, when its
|
|
|
45
45
|
turri release [file.plain] [--in-module <module>] [--guidance <text>] [--model <provider/id>]
|
|
46
46
|
```
|
|
47
47
|
|
|
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.
|
|
48
|
+
The same, without the chat: a one-off agent on `coding-model`, thinking low (or `--model`; without either, [pi](https://pi.dev)'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.
|
|
49
49
|
|
|
50
|
-
`turri regenerate`, `
|
|
50
|
+
`turri regenerate`, `change-plain` and `conform` end a build that landed with `To try it: turri release <spec>`.
|
package/docs/development.md
CHANGED
|
@@ -13,9 +13,9 @@ The suite runs the projects' testing scripts on this machine, as turri does. The
|
|
|
13
13
|
|
|
14
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.
|
|
15
15
|
|
|
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/`.
|
|
16
|
+
Working on turri itself, `npm link` points the global `turri` at this clone, so edits take effect immediately. `npm run chat` starts [pi](https://pi.dev) with the extension loaded from `src/`.
|
|
17
17
|
|
|
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`.
|
|
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](https://pi.dev) 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`.
|
|
19
19
|
|
|
20
20
|
## Publishing
|
|
21
21
|
|
|
@@ -33,30 +33,30 @@ The workflow signs in to npm with npm's trusted publishing (OIDC), not a token:
|
|
|
33
33
|
| `bin/turri.mjs` | the launcher: checks the Node version, then loads `src/cli.ts` |
|
|
34
34
|
| `src/cli.ts` | the `turri` command and its subcommands |
|
|
35
35
|
| `src/setup.ts`, `src/doctor-tool.ts`, `src/environment.ts`, `src/stack.ts` | `turri doctor` and the chat's `doctor` tool, and what they check - this machine, and in a project what its modules need of it |
|
|
36
|
-
| `src/extension.ts` | the pi extension: every tool and command the conversation has |
|
|
36
|
+
| `src/extension.ts` | the [pi](https://pi.dev) extension: every tool and command the conversation has |
|
|
37
37
|
| `src/skill.ts` | parses `SKILL.md` into steps and gates |
|
|
38
38
|
| `src/graph.ts` | compiles a skill into a LangGraph `StateGraph`: step -> gate -> route |
|
|
39
39
|
| `src/judge.ts` | runs independent judges, applies the quorum, builds the critique |
|
|
40
40
|
| `src/genome.ts` | `runSkill()` - the one entry point the CLI and the extension share |
|
|
41
|
-
| `src/pi.ts` | pi session factories for executors, sub-agents and judges |
|
|
42
|
-
| `src/spec-tools.ts` | `
|
|
41
|
+
| `src/pi.ts` | [pi](https://pi.dev) session factories for executors, sub-agents and judges |
|
|
42
|
+
| `src/spec-tools.ts` | `change_plain` |
|
|
43
43
|
| `src/loop-tools.ts` | `regenerate`, `drift` and `halt` - one definition each, for the conversation and the skills alike |
|
|
44
44
|
| `src/mature-tools.ts` | `mature`'s own two: `watch_jobs` and `spec_findings` |
|
|
45
|
-
| `src/plain/` | the \*\*\*plain parser - see [parser](parser.md) - and `highlight.ts`, which highlights \*\*\*plain with plyn's grammar, `plain.tmLanguage.json` (`npm run grammar:sync` refreshes it from [plyn](https://github.com/plainlang/plyn)) |
|
|
45
|
+
| `src/plain/` | the [\*\*\*plain](https://plainlang.org/docs/) parser - see [parser](parser.md) - and `highlight.ts`, which highlights \*\*\*plain with plyn's grammar, `plain.tmLanguage.json` (`npm run grammar:sync` refreshes it from [plyn](https://github.com/plainlang/plyn)) |
|
|
46
46
|
| `src/regenerate/conformance.ts` | conformance tests: writing them, and fixing the test or the code until they pass |
|
|
47
|
-
| `src/regenerate/regenerate.ts`, `src/regenerate/conform.ts` | a code job - a
|
|
47
|
+
| `src/regenerate/regenerate.ts`, `src/regenerate/conform.ts` | a code job - a \*\*\*plain diff regenerated in the code - and a conformance job |
|
|
48
48
|
| `src/regenerate/loop.ts`, `src/regenerate/records.ts`, `src/regenerate/drift.ts`, `src/regenerate/jobs.ts` | the work loop, the records and the work derived from them, and background jobs |
|
|
49
49
|
| `src/regenerate/chunk-plan.ts`, `src/regenerate/cases.ts` | cutting the work into jobs, and what a job's agents are told by its cases |
|
|
50
50
|
| `src/regenerate/regression.ts` | the whole conformance suite run, and the repair agent that may not touch tests |
|
|
51
51
|
| `src/regenerate/lineage.ts` | module history in `.plaingit` |
|
|
52
52
|
| `src/regenerate/release.ts`, `src/release-tools.ts`, `src/release-cli.ts` | deploy: the last commit to `dist/<module>`, what installs software, what it starts on the host - see [deploy](deploy.md) |
|
|
53
53
|
| `src/regenerate/confine.ts`, `src/regenerate/agent-shell.ts`, `src/regenerate/command-check.ts`, `src/regenerate/os-sandbox.ts`, `src/regenerate/audit.ts`, `src/regenerate/agent-env.ts`, `src/regenerate/shell.ts` | the file-tool fence and the walls around every agent command: the check, the OS sandbox, the audit, the module's environment, the host runner - see [sandbox](sandbox.md) |
|
|
54
|
-
| `src/regenerate/engine.ts` | choosing and resolving
|
|
55
|
-
| `src/regenerate/job-panel.ts`, `src/regenerate/transcript-view.ts`, `src/regenerate/diff-view.ts` | the job panel, the side panel's colours, and a
|
|
54
|
+
| `src/regenerate/engine.ts` | choosing and resolving the models that regenerate |
|
|
55
|
+
| `src/regenerate/job-panel.ts`, `src/regenerate/transcript-view.ts`, `src/regenerate/diff-view.ts` | the job panel, the side panel's colours, and a \*\*\*plain diff as they show it - highlighted and banded |
|
|
56
56
|
| `src/regenerate/side-panel.ts`, `src/regenerate/panel-dock.ts` | the side panel, and the chat narrowed beside it when it is docked |
|
|
57
|
-
| `src/screen-padding.ts` | the blank row above and below the whole screen and the two columns either side, in both of pi's ways of drawing it |
|
|
57
|
+
| `src/screen-padding.ts` | the blank row above and below the whole screen and the two columns either side, in both of [pi](https://pi.dev)'s ways of drawing it |
|
|
58
58
|
| `src/regenerate/spec-map.ts`, `src/regenerate/spec-map-view.ts` | regen: each item's mark, from the records, the `.plain` files and the work loop's plan (`mapPlan`), and the map drawn |
|
|
59
|
-
| `src/regenerate/debug-log.ts` | each
|
|
59
|
+
| `src/regenerate/debug-log.ts` | each regenerating agent's whole conversation, streamed to `.turri/debug/` - while its pulse runs, and kept in debug mode |
|
|
60
60
|
| `src/regenerate/pulse-files.ts` | what a pulse writes only for a person - its logs, outputs, temporary files, its chain's installed dependencies - removed as it ends outside debug mode |
|
|
61
61
|
| `src/regenerate/ledger.ts`, `src/regenerate/ledger-view.ts`, `src/ledger-tools.ts`, `src/ledger-cli.ts` | the ledger: what turri did, as typed facts, in `.turri/ledger/` - `record()`, read back for the `ledger` tool, `pulses`, `diagnose` and `turri ledger` - see [the ledger](using.md#the-ledger) |
|
|
62
62
|
| `genome/` | what turri knows and can do: `genome/skills/`, the skill library, and `genome/rules/`, the \*\*\*plain authoring rules |
|
|
@@ -67,4 +67,4 @@ The workflow signs in to npm with npm's trusted publishing (OIDC), not a token:
|
|
|
67
67
|
- The executor keeps one session across steps and retries, so context builds up with attempts. Long skills want compaction or a session per step.
|
|
68
68
|
- A gate's escalation lives in memory (LangGraph's `MemorySaver`): it must be answered in the same run.
|
|
69
69
|
- The gate machinery has no automated coverage; see [trying the gate semantics](skills-and-gates.md#trying-the-gate-semantics).
|
|
70
|
-
- 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.
|
|
70
|
+
- Jobs live in memory: there is no resuming a job after [pi](https://pi.dev) exits. The work itself is on disk, so a killed job leaves a partial build rather than nothing.
|