@turri-dev/cli 0.1.27 → 0.1.28-next.d5f2680
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 +6 -6
- package/dist/advisor-chat.d.ts +63 -0
- package/dist/advisor-chat.js +290 -0
- package/dist/background-skills.d.ts +53 -0
- package/dist/background-skills.js +121 -0
- package/dist/bedrock-region.d.ts +66 -0
- package/dist/bedrock-region.js +144 -0
- package/dist/btw.d.ts +1 -1
- package/dist/btw.js +1 -1
- package/dist/change-plain-cli.js +20 -13
- package/dist/chat-idle.d.ts +7 -0
- package/dist/chat-idle.js +20 -0
- package/dist/chats.d.ts +10 -0
- package/dist/chats.js +23 -0
- package/dist/cli-options.d.ts +1 -2
- package/dist/cli-options.js +2 -7
- package/dist/cli.js +11 -3
- package/dist/config-command.d.ts +14 -0
- package/dist/config-command.js +35 -15
- package/dist/config-edit.d.ts +3 -3
- package/dist/config-edit.js +16 -12
- package/dist/config.d.ts +54 -34
- package/dist/config.js +40 -44
- package/dist/conform-cli.js +12 -10
- package/dist/conformance-switch.d.ts +34 -0
- package/dist/conformance-switch.js +108 -0
- package/dist/cultivate-cli.js +15 -5
- package/dist/drift-cli.js +2 -0
- package/dist/extension.d.ts +15 -0
- package/dist/extension.js +260 -83
- package/dist/host-session.d.ts +26 -0
- package/dist/host-session.js +30 -2
- package/dist/host.d.ts +5 -2
- package/dist/host.js +7 -1
- package/dist/init-config.d.ts +1 -1
- package/dist/init-config.js +20 -11
- package/dist/loop-cli.d.ts +3 -3
- package/dist/loop-cli.js +13 -16
- package/dist/loop-tools.js +18 -10
- package/dist/model-check.d.ts +8 -3
- package/dist/model-check.js +13 -8
- package/dist/new-project.js +12 -8
- package/dist/{validate-cli.js → parse-cli.js} +11 -5
- package/dist/parse-tool.d.ts +9 -0
- package/dist/parse-tool.js +33 -0
- package/dist/pi-launch.js +1 -1
- package/dist/plain/check.d.ts +53 -6
- package/dist/plain/check.js +217 -24
- package/dist/plain/concepts.d.ts +8 -0
- package/dist/plain/concepts.js +66 -23
- package/dist/plain/cycles.d.ts +21 -0
- package/dist/plain/cycles.js +190 -0
- package/dist/plain/errors.d.ts +4 -0
- package/dist/plain/errors.js +7 -0
- package/dist/plain/files.d.ts +18 -1
- package/dist/plain/files.js +39 -2
- package/dist/plain/graph.d.ts +33 -4
- package/dist/plain/graph.js +60 -12
- package/dist/plain/highlight.d.ts +3 -2
- package/dist/plain/highlight.js +4 -3
- package/dist/plain/index.d.ts +8 -5
- package/dist/plain/index.js +8 -5
- package/dist/plain/liquid.js +1 -6
- package/dist/plain/markdown.d.ts +32 -3
- package/dist/plain/markdown.js +146 -24
- package/dist/plain/module-concepts.js +2 -2
- package/dist/plain/parser.d.ts +83 -28
- package/dist/plain/parser.js +381 -260
- package/dist/plain/plain.tmLanguage.json +29 -3
- package/dist/plain/project.d.ts +48 -0
- package/dist/plain/project.js +155 -0
- package/dist/plain/spec.d.ts +90 -28
- package/dist/plain/spec.js +107 -133
- package/dist/plain/test-plain-file.d.ts +59 -0
- package/dist/plain/test-plain-file.js +232 -0
- package/dist/regenerate/activity.d.ts +20 -9
- package/dist/regenerate/activity.js +11 -4
- package/dist/regenerate/advisor-records.d.ts +93 -0
- package/dist/regenerate/advisor-records.js +110 -0
- package/dist/regenerate/advisor-runs.d.ts +87 -0
- package/dist/regenerate/advisor-runs.js +327 -0
- package/dist/regenerate/base-folder.d.ts +68 -0
- package/dist/regenerate/base-folder.js +168 -0
- package/dist/regenerate/cases.d.ts +9 -6
- package/dist/regenerate/cases.js +70 -14
- package/dist/regenerate/change-view.d.ts +8 -3
- package/dist/regenerate/change-view.js +71 -22
- package/dist/regenerate/chunk-plan.d.ts +36 -15
- package/dist/regenerate/chunk-plan.js +165 -59
- package/dist/regenerate/conform.d.ts +3 -0
- package/dist/regenerate/conform.js +6 -5
- package/dist/regenerate/conformance-agents.d.ts +18 -39
- package/dist/regenerate/conformance-agents.js +60 -88
- package/dist/regenerate/conformance.d.ts +23 -13
- package/dist/regenerate/conformance.js +119 -82
- package/dist/regenerate/diff-view.d.ts +1 -1
- package/dist/regenerate/diff-view.js +20 -4
- package/dist/regenerate/drift.d.ts +47 -15
- package/dist/regenerate/drift.js +101 -30
- package/dist/regenerate/jobs.d.ts +2 -2
- package/dist/regenerate/jobs.js +1 -1
- package/dist/regenerate/ledger.d.ts +19 -0
- package/dist/regenerate/loop.d.ts +62 -43
- package/dist/regenerate/loop.js +472 -341
- package/dist/regenerate/paths.d.ts +4 -0
- package/dist/regenerate/paths.js +7 -1
- package/dist/regenerate/plain-palette.js +2 -0
- package/dist/regenerate/prompt.d.ts +57 -19
- package/dist/regenerate/prompt.js +157 -122
- package/dist/regenerate/records.d.ts +43 -12
- package/dist/regenerate/records.js +102 -88
- package/dist/regenerate/regenerate.js +29 -11
- package/dist/regenerate/regression.d.ts +4 -4
- package/dist/regenerate/regression.js +14 -10
- package/dist/regenerate/renames.d.ts +42 -0
- package/dist/regenerate/renames.js +185 -0
- package/dist/regenerate/requires.d.ts +1 -1
- package/dist/regenerate/requires.js +10 -3
- package/dist/regenerate/resources.d.ts +5 -3
- package/dist/regenerate/resources.js +4 -4
- package/dist/regenerate/scripts-being-written.d.ts +19 -0
- package/dist/regenerate/scripts-being-written.js +30 -0
- package/dist/regenerate/spec-map-view.d.ts +2 -2
- package/dist/regenerate/spec-map-view.js +46 -15
- package/dist/regenerate/spec-map.d.ts +27 -5
- package/dist/regenerate/spec-map.js +92 -60
- package/dist/regenerate/spec-steps.d.ts +48 -5
- package/dist/regenerate/spec-steps.js +213 -28
- package/dist/regenerate/state.d.ts +4 -3
- package/dist/regenerate/stop-report.d.ts +1 -1
- package/dist/regenerate/stop-report.js +10 -10
- package/dist/regenerate/test-advisor.d.ts +101 -0
- package/dist/regenerate/test-advisor.js +379 -0
- package/dist/regenerate/test-kinds.d.ts +71 -28
- package/dist/regenerate/test-kinds.js +110 -63
- package/dist/regenerate/test-scripts.d.ts +2 -0
- package/dist/regenerate/test-scripts.js +4 -0
- package/dist/regenerate/testing-steps.d.ts +41 -0
- package/dist/regenerate/testing-steps.js +110 -0
- package/dist/regenerate/testing.d.ts +1 -1
- package/dist/regenerate/testing.js +5 -4
- package/dist/regenerate/unit-review.d.ts +1 -1
- package/dist/regenerate/unit-review.js +3 -3
- package/dist/regenerate-cli.js +11 -12
- package/dist/release-agent.js +4 -0
- package/dist/release-cli.js +2 -0
- package/dist/release-tools.js +2 -0
- package/dist/run-report.d.ts +2 -2
- package/dist/run-report.js +4 -3
- package/dist/self-invocation.d.ts +1 -1
- package/dist/self-invocation.js +1 -1
- package/dist/sentinel.js +1 -1
- package/dist/setup.d.ts +10 -0
- package/dist/setup.js +52 -4
- package/dist/skill.d.ts +10 -0
- package/dist/skill.js +6 -0
- package/dist/skills.js +3 -1
- package/dist/spec-tools.js +21 -31
- package/dist/test-plain-files.d.ts +41 -0
- package/dist/test-plain-files.js +177 -0
- package/docs/README.md +3 -1
- package/docs/authoring-plain.md +46 -13
- package/docs/chats.md +3 -1
- package/docs/config.md +20 -15
- package/docs/deploy.md +1 -1
- package/docs/development.md +2 -1
- package/docs/headless.md +15 -18
- package/docs/hosting.md +28 -12
- package/docs/installation.md +1 -0
- package/docs/parser.md +88 -27
- package/docs/regenerating.md +87 -52
- package/docs/sentinel.md +1 -1
- package/docs/skills-and-gates.md +3 -1
- package/docs/test-advisor.md +110 -0
- package/docs/theming.md +1 -1
- package/docs/using.md +17 -15
- package/genome/rules/bullet-continuation.md +8 -8
- package/genome/rules/concise-specs-examples.md +111 -80
- package/genome/rules/concise-specs-integration-examples.md +56 -41
- package/genome/rules/concise-specs.md +17 -16
- package/genome/rules/definitions.md +5 -5
- package/genome/rules/examples/integration-embedded-testing/run_conformance_tests_java.sh +1 -1
- package/genome/rules/func-specs.md +69 -74
- package/genome/rules/impl-reqs.md +4 -4
- package/genome/rules/integration-embedded-testing.md +20 -20
- package/genome/rules/integration-embedded.md +31 -31
- package/genome/rules/integration-standalone.md +9 -9
- package/genome/rules/integrations.md +18 -18
- package/genome/rules/linked-resources.md +19 -16
- package/genome/rules/module-structure.md +21 -14
- package/genome/rules/project-model.md +18 -17
- package/genome/rules/required-concepts.md +1 -1
- package/genome/rules/requires-modules.md +6 -5
- package/genome/rules/semantic-ids.md +49 -0
- package/genome/rules/stdlib.md +4 -5
- package/genome/rules/test-plain-files.md +130 -0
- package/genome/rules/test-reqs.md +8 -8
- package/genome/rules/turri-regeneration.md +23 -8
- package/genome/skills/analyze-2-func-specs/SKILL.md +36 -21
- package/genome/skills/analyze-func-specs/SKILL.md +46 -32
- package/genome/skills/break-down-func-spec/SKILL.md +91 -67
- package/genome/skills/consolidate-concepts/SKILL.md +10 -10
- package/genome/skills/convert-old-syntax/SKILL.md +68 -0
- package/genome/skills/convert-old-syntax/references/rubric.md +11 -0
- package/genome/skills/debug-specs/SKILL.md +62 -56
- package/genome/skills/implement-conformance-testing-script/SKILL.md +19 -15
- package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +2 -2
- package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +2 -2
- package/genome/skills/implement-unit-testing-script/SKILL.md +14 -10
- package/genome/skills/refactor-module/SKILL.md +35 -35
- package/genome/skills/resolve-section-ownership/SKILL.md +9 -9
- package/genome/skills/resolve-spec-conflict/SKILL.md +35 -29
- package/package.json +7 -6
- package/dist/regenerate/choose-conformance.d.ts +0 -32
- package/dist/regenerate/choose-conformance.js +0 -117
- /package/dist/{validate-cli.d.ts → parse-cli.d.ts} +0 -0
package/docs/regenerating.md
CHANGED
|
@@ -26,7 +26,7 @@ What a module is - each module's folder, its own git history:
|
|
|
26
26
|
| `plain_modules/<module>/tests/.turri-notes.md` | the conformance tests' own working notes: the conformance agent's, its runs' attempts, what its reviews let go, its pulses - never read by a coding agent |
|
|
27
27
|
| `plain_modules/<module>/.plaingit` | the module's history: code, tests and both records, committed together - see [using](using.md#module-history) |
|
|
28
28
|
|
|
29
|
-
A module that `requires` another starts from a copy of that module's code and tests, and builds on top of it; the latest module built in a chain is where later changes to any module of the chain are made. What that code implements comes with it, as built: the other module's definitions and implementation reqs, tagged with it, and its functional specs, as ones the new module inherits. A definition or req of the module's own \*\*\*plain that a module below already has, word for word, is not new work for it: the code implements it already.
|
|
29
|
+
A module that `requires` another starts from a copy of that module's code and tests, and builds on top of it; the latest module built in a chain is where later changes to any module of the chain are made. What that code implements comes with it, as built: the other module's definitions and implementation reqs, tagged with it, and its functional specs, as ones the new module inherits - and what its tests are written for, those functional specs with their scenarios, as ones the new module's conformance suite holds. A definition or req of the module's own \*\*\*plain that a module below already has, word for word, is not new work for it: the code implements it already.
|
|
30
30
|
|
|
31
31
|
The harness's scratch - each ignores itself, and is never part of a module's history:
|
|
32
32
|
|
|
@@ -47,6 +47,16 @@ The harness's scratch - each ignores itself, and is never part of a module's his
|
|
|
47
47
|
|
|
48
48
|
One project can hold modules that share nothing but a common module - a Python backend and a React frontend side by side, each importing `base`, neither requiring the other. Each stack gets its testing scripts, models and conformance in its own `config.turri.<stack>.yaml`, laid over `config.turri.yaml` for the modules built with it - in the chat, `regenerate` with `stack: backend`, pinned to that module's pulses, or `/stack backend` for the session; `--stack backend` on the command line: see [the project config](config.md#stacks).
|
|
49
49
|
|
|
50
|
+
### The base folder
|
|
51
|
+
|
|
52
|
+
A codebase that requires no other module starts empty - unless `base-folder:` in [the config](config.md) names a folder, by path from the project root, that it starts from instead: an existing codebase to build on, files the code is to use - images, animations, fonts - or both. A stack's `config.turri.<stack>.yaml` can name its own.
|
|
53
|
+
|
|
54
|
+
- **Copied once.** Before the codebase's first pulse, the folder's files are copied into `plain_modules/<module>/code` and committed - `start from the base folder <folder>` - and what was copied is recorded beside the code record, `code/.turri-base.json`. From a git repo, what git sees is copied - tracked files, and untracked ones it does not ignore - so no dependencies or build output; from any other folder, every file but `.git` and installed dependencies. The folder itself is never written to.
|
|
55
|
+
- **Up the chain with the code.** A module that requires another starts from that one's finished code, as always - whatever its agents did to what came from the base folder - and the record comes with it.
|
|
56
|
+
- **The agents keep it.** Every agent that changes or judges such a codebase's code - the coding agent, the reviewers, the code fixer of a conformance run and the repair agent of its whole suite - is told, in `<base folder>`, that it started from a copy of the folder and which of its files are there still - up to 200 by name, the rest counted - and that what came from it stays, used where it is, unless a functional spec asks otherwise: code in it built on, its structure, conventions and tests kept; a file in it used from its path, never copied or made again; to a reviewer, a file from it that no functional spec names is kept, neither scope crept in nor left over, and a change to it no functional spec asks for is a finding. Its existing tests run with the module's unit testing script, which `implement-unit-testing-script` writes to run them.
|
|
57
|
+
- **The \*\*\*plain may refer to it.** In words - `use the icons in assets/` - or by a link, resolved as every link is, relative to the module's file: a linked file that came from the base folder is in `<linked resources>` marked `in-codebase` with its path there, to be used from there, not copied.
|
|
58
|
+
- **Not kept in step.** A change to the folder after the codebase started - or `base-folder:` naming another - is not copied in: `drift` says so, and regenerating the module from scratch starts again from the folder as it is then. A folder named and not there stops the codebase's first pulse before it starts; `parse` and `doctor` say so beforehand.
|
|
59
|
+
|
|
50
60
|
## One job
|
|
51
61
|
|
|
52
62
|
Every piece of work on the code is a job of the work loop (see [a whole module](#a-whole-module)) - in the chat, a **pulse** - the side panel's **regen** is \*\*\*plain with how much of it the code has been regenerated from (`spec-map.ts`), and its pulses every one of them - while the code and this page call it a job: a \*\*\*plain diff that takes the code from the \*\*\*plain description it is built from to the \*\*\*plain description the job ends on. To see what the first jobs would be told:
|
|
@@ -57,7 +67,7 @@ turri regenerate <file.plain> --dry-run # plan the work, print each codebas
|
|
|
57
67
|
|
|
58
68
|
### What the agent is given
|
|
59
69
|
|
|
60
|
-
The prompt, and nothing else - the agent cannot read the `.plain` files. Every prompt for an agent that builds, tests or judges from \*\*\*plain starts with how to read it: what each section is for (the implementation reqs bind the whole codebase;
|
|
70
|
+
The prompt, and nothing else - the agent cannot read the `.plain` files. Every prompt for an agent that builds, tests or judges from \*\*\*plain starts with how to read it: what each section is for (the implementation reqs bind the whole codebase; to the conformance agents, scenarios carry the same authority as their functionality) and what the predefined concepts mean - `:Implementation:`, `:UnitTests:`, `:ConformanceTests:` and the rest, used in every module's \*\*\*plain and defined in none. It also says how a failure is fixed without hiding it: no changing test data to get a pass, no mocking the system under test, no skipping or silencing a failing test. It holds the definitions and implementation reqs in scope, every functionality already built (the required modules' too) marked as implemented, a map of the codebase as it stands, the contents of any linked resources, and the change to build, section by section, with what to do with each functional spec it touches (see [what a job is given](#what-a-job-is-given-and-what-it-records)):
|
|
61
71
|
|
|
62
72
|
```
|
|
63
73
|
<definitions> … </definitions>
|
|
@@ -68,9 +78,9 @@ The prompt, and nothing else - the agent cannot read the `.plain` files. Every p
|
|
|
68
78
|
<spec change> … </spec change>
|
|
69
79
|
```
|
|
70
80
|
|
|
71
|
-
The test reqs and the
|
|
81
|
+
The test reqs and the scenarios are not in it: they are the conformance agents'.
|
|
72
82
|
|
|
73
|
-
Every section has one name, its tag's, in every prompt: how to read \*\*\*plain introduces each one as `<definitions>`, `<implementation reqs>`, `<test reqs>`, `<functional specs>` (each functional spec a `<functionality module="…" id="…"
|
|
83
|
+
Every section has one name, its tag's, in every prompt: how to read \*\*\*plain introduces each one as `<definitions>`, `<implementation reqs>`, `<test reqs>`, `<functional specs>` (each functional spec a `<functionality module="…" id="…">`, its id its func-id), `<linked resources>` and `<spec change>` - and, to the agents that write and judge the conformance tests, `<conformance tests>` and `<acceptance tests>`, a functional spec's scenarios, each under its `# <scenario-id>` - and the prompts' own words call each section by that name. The `***definitions***` headings of a `.plain` file appear only where a \*\*\*plain change could not be told section by section and the agent is given the raw diff: it is then told which tag each heading is, and that a functional spec is a `# <func-id>` heading and its text. A coding agent's raw diff leaves out the test plain files: it never sees a scenario. \*\*\*plain in full - the planner's, the steps agent's (`spec-steps.ts`), the conformance agents' - is laid out in the same tags.
|
|
74
84
|
|
|
75
85
|
A module that `requires` another inherits its functional specs; one that `import`s another inherits its definitions, implementation reqs and test reqs.
|
|
76
86
|
|
|
@@ -142,7 +152,7 @@ And each review is shown:
|
|
|
142
152
|
|
|
143
153
|
The reviewer is the exacting developer, opinionated about everything: it raises every problem it finds, however small. Its problems go back to the coding agent, the unit testing script has to pass again, and the next review checks those problems first rather than starting over. A problem that leaves a behaviour of \*\*\*plain not implemented, implemented wrong or untested - no test, or one that cannot fail - is **blocking** and worked on first.
|
|
144
154
|
|
|
145
|
-
The work is reviewed twice at most. The first review that sends it back goes to the coding agent as it is. The second, **the arbiter** weighs before it reaches the coding agent: the distinguished engineer, on the judge model, read-only, given the same \*\*\*plain and code diff as the reviewer, the tests and every review so far. It rules on each problem. It upholds a problem when a behaviour \*\*\*plain states for this work is not implemented, implemented other than \*\*\*plain says, or untested, or when a test cannot fail: the reviewer is right, and the coding agent fixes it. It dismisses a problem that is out of scope or a nitpick: the test already tests the behaviour, it is another case of one already covered, it is a matter of style, or the code is written another way but does what \*\*\*plain says. Only what it upholds goes back. What it dismisses is let go, with why, in the working notes' pitfalls. When it upholds nothing, the work is approved as it is. The review optimises the code and its tests; it never stops the work - whether it is done is the unit testing script's to say. What the second review sends back is worked on once, and then the work goes on without another review - once its unit tests pass, which they still must. The review is told that behaviour is what a functional spec
|
|
155
|
+
The work is reviewed twice at most. The first review that sends it back goes to the coding agent as it is. The second, **the arbiter** weighs before it reaches the coding agent: the distinguished engineer, on the judge model, read-only, given the same \*\*\*plain and code diff as the reviewer, the tests and every review so far. It rules on each problem. It upholds a problem when a behaviour \*\*\*plain states for this work is not implemented, implemented other than \*\*\*plain says, or untested, or when a test cannot fail: the reviewer is right, and the coding agent fixes it. It dismisses a problem that is out of scope or a nitpick: the test already tests the behaviour, it is another case of one already covered, it is a matter of style, or the code is written another way but does what \*\*\*plain says. Only what it upholds goes back. What it dismisses is let go, with why, in the working notes' pitfalls. When it upholds nothing, the work is approved as it is. The review optimises the code and its tests; it never stops the work - whether it is done is the unit testing script's to say. What the second review sends back is worked on once, and then the work goes on without another review - once its unit tests pass, which they still must. The review is told that behaviour is what a functional spec or a req states: a page or a component only a definition names has no code yet. The conformance tests are reviewed as black-box tests (see [conformance tests](#conformance-tests)).
|
|
146
156
|
|
|
147
157
|
Every time a review sends tests back, the agent that fixes them also leaves the lesson in the working notes' pitfalls: not the fix, but the kind of test the review found weak or missing and how to write it instead - "tests assert the exact response body, never only that one came back". One that fixes the tests and leaves no lesson is asked once more. Every later agent on the codebase starts from the notes, and is told to write its tests so they would pass those reviews the first time - so the reviews of the next functionalities have less to send back, and finish sooner.
|
|
148
158
|
|
|
@@ -158,7 +168,7 @@ turri regenerate <file.plain>
|
|
|
158
168
|
|
|
159
169
|
Regenerating a module - `regenerate` in a conversation, `turri regenerate` on the command line - is not a job of its own, and nothing is queued: the work loop (`src/regenerate/loop.ts`) works out what is left to build, has it planned into jobs, and runs the first. What is left is the difference between what a codebase's code is built from - its code record - and its requires chain's \*\*\*plain as the `.plain` files have it now. When a job ends, or \*\*\*plain changes, it is worked out again; a plan is kept only while \*\*\*plain and the record it was cut from stay as they were.
|
|
160
170
|
|
|
161
|
-
Code accumulates up a `requires` chain: a module is built on a copy of the code of the one it requires. So a chain's codebase is its furthest-built module - its tip - and its record holds the whole chain: the definitions and implementation reqs of the modules below, each tagged with its module, their functional specs among the ones it inherits, and its own. A change to a module below is made there. The codebases below the tip are left as they were, their records saying what they are built from; one is brought up to its own \*\*\*plain again only when a module not built yet is to start from it - the module below first, then the new one on a copy of its code. With no module of a chain built, it is built bottom first, a module waiting while the one it is built on has work left or a job running.
|
|
171
|
+
Code accumulates up a `requires` chain: a module is built on a copy of the code of the one it requires. So a chain's codebase is its furthest-built module - its tip - and its record holds the whole chain: the definitions and implementation reqs of the modules below, each tagged with its module, their functional specs among the ones it inherits, and its own. A change to a module below is made there: a functional spec of `base` added, changed or taken out is added, patched or deleted in the tip's code as `base:add-task`, just as the tip's own are, and its conformance tests are written and kept up to date in the tip's suite. The codebases below the tip are left as they were, their records saying what they are built from; one is brought up to its own \*\*\*plain again only when a module not built yet is to start from it - the module below first, then the new one on a copy of its code. With no module of a chain built, it is built bottom first, a module waiting while the one it is built on has work left or a job running.
|
|
162
172
|
|
|
163
173
|
A module already built from \*\*\*plain as it is gets nothing. A job that does not land is rolled back, and halts its codebase: nothing more runs there until \*\*\*plain changes or the module is asked for again. On the command line, `turri regenerate` runs until nothing more can start, one line as each job starts and ends, and exits 1 when any failed.
|
|
164
174
|
|
|
@@ -176,7 +186,7 @@ A job that regenerates the whole of a new module's \*\*\*plain is too big to bui
|
|
|
176
186
|
|
|
177
187
|
Each pulse's title says what it does - at most 10 words and 70 characters, as it heads the pulse where the person watches the work. The grouping agent titles its groups; groups no agent made - the conformance tests', and a grouping that fell back - are titled by a third agent, told what each pulse does: what it builds, or, for the conformance tests, what they test. Without it, or when it fails, a pulse is titled by its functional specs' first lines, cut short.
|
|
178
188
|
|
|
179
|
-
Changes to what is built - an item edited or taken out, a functional spec built worded differently - go first, in a
|
|
189
|
+
Changes to what is built - an item edited or taken out, a functional spec built worded differently - go where the same agent places each: with the group of new functional specs it is about, by default - so one edit that adds a functional spec, changes another and takes out a third is one pulse - or first, in a pulse of its own, when it reshapes what the new work is built on (a concept many functional specs use redefined, one others rely on taken out, a large rewrite) or has nothing to do with it. A functional spec changed counts toward its group's `max-specs-per-pulse`; one taken out does not. Every answer is checked: every new functional spec once, in order, next to each other, at most `max-specs-per-pulse`; every change to what is built placed once; every req placed once; every group titled once, within the limit. One that does not hold goes back to its agent, twice at most, and then the plan is a functional spec a job with every req in the first. A group whose functional specs and the definitions they bring pass `max-lines-per-pulse` (120 unset) is split into as few pulses as fit - its functional specs kept together in runs, in order, as long as each run stays within it, `Comments (1 of 2)`, `Comments (2 of 2)` - not a functional spec a job; its reqs do not count, as a split leaves them with its first job whatever happens. The planner runs on the chat's model in a conversation, and on the harness model under `turri regenerate`. No agent reviews its plan: the harness checks it - every change in exactly one job, \*\*\*plain holding together after each, the last ending on \*\*\*plain as it is.
|
|
180
190
|
|
|
181
191
|
Each planned job knows its cases - which functional specs it adds, changes (their text, or a concept they use) and takes out, or none: reqs and definitions only - and the loop says them, with each job's title, where the person looks (`drift`, `pulses`, and what `regenerate` returns).
|
|
182
192
|
|
|
@@ -186,7 +196,7 @@ A plan is kept until \*\*\*plain, what it starts from or its steering changes. `
|
|
|
186
196
|
|
|
187
197
|
### When \*\*\*plain changes
|
|
188
198
|
|
|
189
|
-
A \*\*\*plain change is a notice, not a diff to run: **`regenerate`**, called after \*\*\*plain was edited by any means - the file tools, a skill, you in an editor - has the loop work out the work again. A job running goes on while every change it makes is still part of the work, measured from the same record; one that is making something \*\*\*plain no longer wants is stopped, rolled back, and the work planned again - a fixed rule, no agent. Say a module of 50 functionalities is regenerating and \*\*\*plain changes while
|
|
199
|
+
A \*\*\*plain change is a notice, not a diff to run: **`regenerate`**, called after \*\*\*plain was edited by any means - the file tools, a skill, you in an editor - has the loop work out the work again. A job running goes on while every change it makes is still part of the work, measured from the same record; one that is making something \*\*\*plain no longer wants is stopped, rolled back, and the work planned again - a fixed rule, no agent. Say a module of 50 functionalities is regenerating and \*\*\*plain changes while `app:export-csv` builds: it goes on if the change leaves it as it is, and the work after it is planned again from what it lands. A job stopped so says it was turri, not you, and what changed under it - the functional spec that reads otherwise now, or the file it links that holds something else (`whyNotWanted`).
|
|
190
200
|
|
|
191
201
|
**A change inside what the running job regenerates steers it** (`steering.ts`), before any of that: a functional spec it regenerates reworded or given a sub-bullet, a definition or an implementation req it is given edited, a file one of them links edited - a change to an item it already has, never an item added or removed. Its coding agent is told, in the same shape as its first change (`describeSpecChange`): in its turn when it is in one, else as its next turn once the step it is at ends - a test run, a review - even when the tests passed or the review approved; edits made before it is told are one steer, the newest of each item. The unit tests run again after it, and a review still to come sees the change as steered, within its two reviews. The job's target moves with it: it lands built from \*\*\*plain as it was steered to. A definition or req that functional specs built before the job use too is told to the agent but kept out of the record, so those functional specs - and this job's with them - are patched by the next job. What else changed is the next job's; a change that is partly a steer is split. Two steers a job: a third goes the way above, stopped or - with `allow-to-stop-jobs: false` - left to the next job. Conformance jobs are not steered: they are planned from what the code lands. A steer shows in the job's view in the panel (what it regenerates now), in the transcript (`⇢ steered job …`), under the job in `regenerate`'s answer, and in the job's report.
|
|
192
202
|
|
|
@@ -208,7 +218,7 @@ Whether something is done is never the agent's call, and never a command it chos
|
|
|
208
218
|
| `test_scripts/run_conformance_tests_<lang>.sh` | `run_conformance_tests_<lang>.sh <build> <tests>` | whether the conformance tests pass - the whole suite in `plain_modules/<module>/tests`, every functionality's and those carried up from below, at once - and the tests' static checks with them, exit 80 when only the checks fail |
|
|
209
219
|
| `test_scripts/prepare_environment_<lang>.sh` - optional | `prepare_environment_<lang>.sh <build>`, before every run of the conformance testing script | nothing on its own: it readies the environment the conformance tests run in - a `mvn install` of the build, say - and when it fails, the conformance tests are not run and the run fails as the preparation's |
|
|
210
220
|
|
|
211
|
-
The `implement-unit-testing-script` and `implement-conformance-testing-script` skills write them. They are looked for at the project root - the folder that holds `plain_modules` - in this order:
|
|
221
|
+
The `implement-unit-testing-script` and `implement-conformance-testing-script` skills write them, in the background on the coding model of the module they are for ([background skills](skills-and-gates.md)). While one is being written, a module that lacks that script waits for it - `waiting for its unit testing script, which is being written`, or its conformance testing script - rather than fail for want of it, and is looked at again once the run ends: built, once the script is there, and stopped for want of it as before, when the run wrote none (`src/regenerate/scripts-being-written.ts`). A script written for one stack holds only the modules on that stack. They are looked for at the project root - the folder that holds `plain_modules` - in this order:
|
|
212
222
|
|
|
213
223
|
1. `config.turri.yaml` - with the chosen stack's `config.turri.<stack>.yaml` over it, for a project whose parts are on different stacks - naming them by path from the root:
|
|
214
224
|
|
|
@@ -220,7 +230,7 @@ The `implement-unit-testing-script` and `implement-conformance-testing-script` s
|
|
|
220
230
|
2. the root itself: the one `run_unittests*.sh` and `run_conformance_tests*.sh` there;
|
|
221
231
|
3. `test_scripts/`: the one of each there.
|
|
222
232
|
|
|
223
|
-
The same `config.turri.yaml` holds the project's other defaults - `module`, `model`, `
|
|
233
|
+
The same `config.turri.yaml` holds the project's other defaults - `module`, `model`, `review` - for [unattended runs](headless.md). A folder holding two of a kind is not guessed between: name the one to use in `config.turri.yaml` - or, in a project of stacks, in each stack's own file, and build each module with its stack. A module of such a project built with none says so when it stops: which stacks there are, and which script each names. The scripts are not linked from \*\*\*plain; a link to one is ignored.
|
|
224
234
|
|
|
225
235
|
They are required: a build with no unit testing script, or with conformance on and no conformance testing script, stops before it starts and says which skill adds it.
|
|
226
236
|
|
|
@@ -273,24 +283,24 @@ Either way the pulse is not tried again: no second run would find what is missin
|
|
|
273
283
|
|
|
274
284
|
### What a job is given, and what it records
|
|
275
285
|
|
|
276
|
-
Every job is a \*\*\*plain diff: the agent that regenerates it is given the \*\*\*plain description the code is built from - its functional specs in `<already implemented>` - and the change to it, in `<spec change>`, section by section - not the raw diff: each of `<definitions>`, `<implementation reqs>` and `<functional specs>` in its own tag, `<definitions change="1 added, 2 changed">`, saying what is added, what changed with its text before and now, and what is removed, measured from what is built to the \*\*\*plain description the job ends on. A definition is itself by its concept: one reworded or moved is shown as changed, not as removed and added. Test reqs and
|
|
286
|
+
Every job is a \*\*\*plain diff: the agent that regenerates it is given the \*\*\*plain description the code is built from - its functional specs in `<already implemented>` - and the change to it, in `<spec change>`, section by section - not the raw diff: each of `<definitions>`, `<implementation reqs>` and `<functional specs>` in its own tag, `<definitions change="1 added, 2 changed">`, saying what is added, what changed with its text before and now, and what is removed, measured from what is built to the \*\*\*plain description the job ends on. A definition is itself by its concept: one reworded or moved is shown as changed, not as removed and added. Test reqs and scenarios are for conformance only: the code record holds neither, and no coding agent is shown them. Wherever \*\*\*plain is written back out as text - a step's \*\*\*plain diff, the planner's and every agent's view of a change - a functional spec is its `# <func-id>` heading over its text, as its file has it, and a change to one is named by its func-id ("change the text of functional spec `add-task`"), one of a module below as `<module>:<func-id>`.
|
|
277
287
|
|
|
278
|
-
**Every part of \*\*\*plain is given with its module.** A codebase is built from its whole requires chain's \*\*\*plain, and
|
|
288
|
+
**Every part of \*\*\*plain is given with its module.** A codebase is built from its whole requires chain's \*\*\*plain, and a func-id is unique only in its module, so every agent is shown each section grouped under the module each item belongs to - `<module name="base">`, then `<module name="app" role="current">` - as `<already implemented>` groups the functional specs (`moduleSection`, `functionalitiesByModule` in `prompt.ts`). A module's own items, and what it imports, are the current module's. `<spec change>` names a functional spec as "functional spec `app:add-task`", and a definition or req of a module below with its module; each case line does too ("`app:add-task` (A :User: can add a :Task:.)"). The primer every agent reads first says that modules are how [\*\*\*plain](https://plainlang.org/docs/) is written, not how the code is laid out: the agent works only in the current module's codebase, which holds the code of every module it requires, and organises the code as the implementation reqs say.
|
|
279
289
|
|
|
280
|
-
It is told, too, what to do with each functional spec the job touches, by its case (`src/regenerate/cases.ts`): a fresh project is set up first, with its unit tests where the unit testing script runs them; a new functional spec is built and unit tested; a changed one - its text, or a concept it uses - is changed in place, its code and tests to match, never built again from scratch; one regenerated again is built anew, not patched - its implementation taken out and built again, even where the old code already does what \*\*\*plain says, what it replaces taken out; one taken out has its code and the tests only it had removed. A job holding several cases has a line for each
|
|
290
|
+
It is told, too, what to do with each functional spec the job touches, by its case (`src/regenerate/cases.ts`): a fresh project is set up first, with its unit tests where the unit testing script runs them; a new functional spec is built and unit tested; a changed one - its text, or a concept it uses - is changed in place, its code and tests to match, never built again from scratch; one regenerated again is built anew, not patched - its implementation taken out and built again, even where the old code already does what \*\*\*plain says, what it replaces taken out; one taken out has its code and the tests only it had removed. A job holding several cases has a line for each, the functional specs of the modules below among them, each named `<module>:<func-id>`. A job that touches no functional spec of any module of the chain - implementation reqs, or definitions none uses - is mechanical: the code adapts, no new test is written, and an existing one may change only mechanically, never what it asserts. The unit test review holds each part to its case, and a mechanical job only to its reqs and to no test removed or weakened. A conformance job's agent and its reviewer are told the same, for the tests:
|
|
281
291
|
|
|
282
292
|
| case | when | code | conformance |
|
|
283
293
|
| --- | --- | --- | --- |
|
|
284
294
|
| fresh | the module requires none and nothing is built | set up the project and its unit tests where the unit testing script runs them, then build | set up `tests/` so the conformance testing script, which brings the tests together with `code/`, runs them, then write |
|
|
285
|
-
| add | a functional spec is new | build it and write its unit tests | write
|
|
286
|
-
| patch | its text changed, or a concept it uses did | change the existing code and tests to match - never build it again from scratch |
|
|
295
|
+
| add | a functional spec is new | build it and write its unit tests | write the tests of each of its scenarios |
|
|
296
|
+
| patch | its text changed, or a concept it uses did - for the conformance tests, or its scenarios | change the existing code and tests to match - never build it again from scratch | [scenario by scenario](#scenario-by-scenario): the tests of those added written, of those changed rewritten, of those removed deleted; those of the unchanged ones stay - run on the new code when its code changed |
|
|
287
297
|
| again | `regenerate` named it: it is built, and marked in the code record to be regenerated again | take its implementation out and build it anew, doing what \*\*\*plain says now - the old code already doing it is no reason to keep it; no second implementation beside the old, nothing of it left unused; its unit tests written anew. A coding agent that writes nothing is sent back twice to build it anew, and then the pulse does not land | its tests were written against the code it replaced: run against the new code - black box, those that pass are its tests too, and are not rewritten; one that fails is judged against \*\*\*plain like any failure: what it checks that \*\*\*plain says stays checked, and what it checks that \*\*\*plain leaves open - a path, a field, a message the old code chose - is rewritten to what the new code does, or taken out |
|
|
288
|
-
| delete | a functional spec is gone | take out its code and the tests only it had | take out its tests |
|
|
289
|
-
| mechanical | no functional spec is touched - only reqs, or definitions none uses | adapt the code; write no new test; an existing one may change only mechanically - an import, a fixture, its setup - never what it asserts | the same, for test reqs, definitions or implementation reqs alone |
|
|
298
|
+
| delete | a functional spec is gone | take out its code and the tests only it had | take out its tests, every scenario's |
|
|
299
|
+
| mechanical | no functional spec of the chain is touched - only reqs, or definitions none uses | adapt the code; write no new test; an existing one may change only mechanically - an import, a fixture, its setup - never what it asserts | the same, for test reqs, definitions or implementation reqs alone |
|
|
290
300
|
|
|
291
|
-
**Regenerating again.** `regenerate` with functionalities named regenerates them again though their \*\*\*plain did not change - made better, on another model, after many patches. Each is marked in the code record of every codebase it is built in (`regenerate_again`, committed), and nothing else changes: the record now differs from \*\*\*plain at that item, so the work loop plans it as it plans any change. A functional spec of a module below is regenerated again where its code lives - the codebase at the tip of each chain built on it, never the module's own codebase left behind - marked among that codebase's required functional specs. The planner groups the ones regenerated again as it groups new ones - up to three a job, only those next to each other in one module together - and the job is given the definitions and implementation reqs as every job is; `<spec change>` lists each under "To regenerate again", with its text as it is now. The job that regenerates it records it as \*\*\*plain has it, without the mark. Its conformance tests are marked with it, in the tests record of the codebase whose own
|
|
301
|
+
**Regenerating again.** `regenerate` with functionalities named regenerates them again though their \*\*\*plain did not change - made better, on another model, after many patches. Each is marked in the code record of every codebase it is built in (`regenerate_again`, committed), and nothing else changes: the record now differs from \*\*\*plain at that item, so the work loop plans it as it plans any change. A functional spec of a module below is regenerated again where its code lives - the codebase at the tip of each chain built on it, never the module's own codebase left behind - marked among that codebase's required functional specs. The planner groups the ones regenerated again as it groups new ones - up to three a job, only those next to each other in one module together - and the job is given the definitions and implementation reqs as every job is; `<spec change>` lists each under "To regenerate again", with its text as it is now. The job that regenerates it records it as \*\*\*plain has it, without the mark. Its conformance tests are marked with it, in the tests record of the same codebase - the tip's, whose suite holds the tests of the whole chain, a module below's among them, never the module's own codebase left behind: they were written against the code being replaced, and may hold the new code to what only the old code chose - `/healthcheck` where \*\*\*plain says only that there is a health check, and the new code answers `/health`. While the code regenerates they stay as they are; once it lands, the mark is conformance work like any change, its tests being there - and a conformance job runs them on the new code, in the again case above, with the whole suite. The mark means its tests have not yet run on its new code: the job drops it once the whole suite passes, and one that does not land keeps it. Until it lands, regen shows its tests as written for an earlier build, and they are not counted as conformance tested.
|
|
292
302
|
|
|
293
|
-
A functional spec is patched when a concept it uses changed as well as when its own text did: the harness follows each functional spec's concepts through the definitions. Fresh is only where nothing exists: a module that requires another starts from what it inherits, and its first job adds or patches.
|
|
303
|
+
A functional spec is patched when a concept it uses changed as well as when its own text did: the harness follows each functional spec's concepts through the definitions - every functional spec of the chain, those of the modules below as well as the codebase's own. Fresh is only where nothing exists: a module that requires another starts from what it inherits, and its first job adds or patches.
|
|
294
304
|
|
|
295
305
|
**Linked resources.** A file \*\*\*plain links is part of it, so what it holds is compared too: each linked resource is hashed on its own (sha256 of its content) beside its link, in the trees the loop compares and in both records. A change to the file - an API surface `openapi.yaml` defines - changes the item that links it, with no change to the `.plain` text: a functional spec linking it is patched, and a definition linking it patches every functional spec using its concept. The job's diff has a hunk of its own for each such file, under the file's name - shown as a file of its own where the job is shown - saying which item links it, in which \*\*\*plain file (`resources/hubspot/openapi.yaml, linked by :HubSpotRestAPI: in hubspot.plain`), and that its content changed, with both hashes; the agent is told which file holds something else now, beside the item's unchanged text, and reads the file as it is now in `<linked resources>`. The records keep the hash, not the content, so what the file held before is not shown. A record written before resources were hashed is taken as built from the files as they are now: the loop hashes its links and commits it, building nothing again.
|
|
296
306
|
|
|
@@ -302,72 +312,97 @@ A job lands once its unit tests pass and are reviewed: the code record becomes t
|
|
|
302
312
|
|
|
303
313
|
A change that regenerates nothing - definitions moved to a common module, reqs reordered, \*\*\*plain moved between modules of the chain - is recorded, not regenerated: \*\*\*plain is recorded as it is now laid out and committed, with no agent and no testing script. Moving \*\*\*plain into a module the code was not built on is different: no change to the code brings that module's code in, so the codebase stops: it has to be started over - its code and conformance tests taken out, committed so its history keeps them, and the chain built again from the bottom. That is never done unasked. In the chat the model asks the person, saying why, and calls `regenerate` with `from_scratch: "module"` once they agree; `turri regenerate` and `change-plain` ask at the terminal, and `--start-over` agrees in advance - with no terminal and no flag, the run stops there, exit 1, saying so.
|
|
304
314
|
|
|
315
|
+
**A pure rename.** A func-id given another name, and nothing else with it - in the \*\*\*plain diff, the functional spec's `# <func-id>` heading the only line of it that changed, and in its test plain file `func_id:`, wherever the file now is - is no work for an agent: its code does what it did, and its tests test what they did. In the trees it is a functional spec taken out and one added, identical but for their func-id - their text, their links, their scenarios. turri makes it itself, as one unit of work (`renames.ts`): the code record and the tests record rewritten to the new func-id, and the tests relabelled - `… of base:add-task` becomes `… of base:create-task`, on the whole key - committed together, or rolled back whole when any of it fails, the codebase then halted rather than the functional spec built anew. No agent runs, no testing script, no pulse, and the code is not touched. A scenario-id renamed - the same text, under the same functional spec, nothing else of it changed - has its tests relabelled the same way, none rewritten. A rename together with any other change - its text, a scenario - stays a functional spec taken out and another added, its code built anew and its tests written anew. A module file renamed gets nothing of this: `todo.plain` renamed `tasks.plain` is a new module, built from scratch, and `plain_modules/todo` is left for the person to delete. Before turri has made it, a pure rename is shown as one, never as a delete and an add: `drift` says `renames app:add-task to app:create-task`, the planner plans the work around it from the code as renamed, the regeneration shows the functional spec built, its old func-id beside it, and the ledger records it as a fact of its own (`loop.renamed`).
|
|
316
|
+
|
|
305
317
|
## Conformance tests
|
|
306
318
|
|
|
307
|
-
|
|
319
|
+
**On or off.** A project has them only with `conformance-tests: true` ([config](config.md#conformance-tests)); unset, they are off - no scenarios written or tested, no conformance testing script, no conformance pulse, the test advisor off - and everything below is what turri does once they are on. The chat always knows they are off and how they are turned on: you asking it for conformance tests, or agreeing when it offers them, has it call `turn_on_conformance_tests`, which writes `conformance-tests: true` and gives it `conform` and `evaluate_tests` back.
|
|
320
|
+
|
|
321
|
+
The unit tests are written by the agent that wrote the code. Conformance tests are the other half: black box, end to end - and what they test is the scenarios. A functional spec's scenarios are in its test plain file, `<test-dir>/<module>/<func-id>.plain` ([authoring](authoring-plain.md#what-plain-is-made-of)), with its conformance scenarios under `***conformance tests***` and its acceptance scenarios under `***acceptance tests***`, each a `# <scenario-id>` heading and its text. A functional spec with scenarios is tested; one with no test plain file is not. There is no setting for it: to have a functional spec tested, write its scenarios - in the chat, its agent writes them with `change_plain` when you ask for conformance tests. In the chat and a host, the [test advisor](test-advisor.md) checks in the background whether a new or changed functional spec needs testing, and on a yes the chat writes its scenarios - with the test reqs and the conformance testing script, when they are missing.
|
|
308
322
|
|
|
309
323
|
```bash
|
|
310
|
-
turri conform <file.plain>
|
|
311
|
-
turri conform <file.plain>
|
|
324
|
+
turri conform <file.plain> # every functional spec with scenarios
|
|
325
|
+
turri conform <file.plain> app:add-task # one, named module:func-id
|
|
312
326
|
```
|
|
313
327
|
|
|
314
|
-
They follow the code: a functional spec
|
|
328
|
+
They follow the code: a functional spec's scenarios get their tests once its code is built, for modules with `***test reqs***` and a conformance testing script. Once a codebase has conformance tests, they are always run and kept passing, and they are carried up to the modules built on top of it.
|
|
329
|
+
|
|
330
|
+
### The steps of adding tests
|
|
331
|
+
|
|
332
|
+
Nothing about testing exists until the person asks for it, or the [test advisor](test-advisor.md)'s yes arrives: a module imports its stack alone, and its functional specs have no test plain files. The first time they ask for tests in a module, or the advisor's yes arrives, the chat takes three steps, in order, each a visible change: the **test reqs** - the stack's conformance template, `stdlib/<kind>/conformance/<stack>`, imported, or the module's own `***test reqs***`; the **conformance testing script** for the module's stack, written with `implement-conformance-testing-script` when the project has none ([the testing scripts](#the-testing-scripts)) - in the background, so the chat goes straight on, and the conformance tests wait for the script; then the **scenarios**.
|
|
333
|
+
|
|
334
|
+
A step skipped - functional specs with scenarios, and no test reqs (the module's own or imported), or no conformance testing script for its stack - and turri refuses to start a conformance pulse there, the work loop's and `conform`'s alike, naming the first step missing and the next step: `app has scenarios to test - app:say-hello - but no ***test reqs***, so its conformance tests cannot be written - the test reqs are the first step of adding tests. Next step: import the stack's conformance template, stdlib/backend/conformance/python-flask, with change_plain.` Nothing is started and nothing halts: the code goes on being built, and once it is, the module waits on that step - `waiting for its test reqs: …` in the loop's status and in `drift` - until \*\*\*plain or the scripts change, when the next look starts the pulse. `parse` gives the same as a warning, never a failure, and the map's top line says what is missing. A module another requires has its conformance tests written in the tips above it, so `parse` judges it by them, and says which: `base's conformance tests are written in top, which requires it: …`. A module with no scenarios skipped nothing: it is not tested, and nothing is said.
|
|
315
335
|
|
|
316
336
|
### Conformance tests in the work loop
|
|
317
337
|
|
|
318
|
-
In the work loop, conformance is a track beside the code's. What the conformance tests are written for is recorded apart - `tests/.turri.json`: the functional specs they test, as built, with their
|
|
338
|
+
In the work loop, conformance is a track beside the code's. What the conformance tests are written for is recorded apart - `tests/.turri.json`: the functional specs they test, as built, with their scenarios, the definitions and implementation reqs they were written against, and the test reqs they follow - and the work is from that record to what they are to be: of the functional specs the code is built from - the codebase's own and those of the modules below it, whose tests the tip's suite holds - every one with scenarios, as \*\*\*plain has it, with its test reqs. So a functional spec's tests are behind - and a conformance pulse starts by itself - when a scenario is added, changed or taken out, when its text changes, when it is regenerated again, or when it is taken out; one whose scenarios are all taken out loses its tests. A scenario changed alone is conformance work only: the code record holds no scenario, so no code pulse runs for it. A functional spec whose code is behind \*\*\*plain - built from other text, or not in the code record at all, as while `regenerate` regenerates it again by name - keeps its tests until the code lands; they are taken out only once \*\*\*plain and the code have both dropped it. The harness cuts the work into jobs - an agent only titles them: every functional spec tested is in one conformance job - those of the modules below with the codebase's own, tests added, changed and taken out alike - as far as a guardrail lets: a new job begins only where the next functional spec would take the job's functional specs and the definitions they bring past 120 lines. The reqs they are written against go with the first job, and do not count. When the person asks for it - one at a time, separately - `conform`'s `one_by_one` (`turri conform --one-by-one`) makes it a job a functional spec instead, until conformance tests are asked for again without it. Only work that touches no functional spec at all, the test reqs changed say, is a job without one: it adapts the tests there are, and writes none. A module's conformance jobs run on its lane once its code is built - every code job of it landed - so the module is tested once, as built: one explorer, one run of the whole suite, rather than a conformance cycle after each code job; and they pass before anything is built on it. Until then they are not planned, but what is planned lists them last - `conformance tests of app:add-task, app:list-tasks - planned once the code is built`.
|
|
319
339
|
|
|
320
|
-
A conformance job is a \*\*\*plain diff's conformance run: the tests of its change written, changed or taken out, a failure judged - the test or the code wrong - and fixed, then the whole suite with the unit tests, the tests the module inherits with them. The run that passed already was of the whole suite - the module's tests folder holds the chain's, copied up - so the suite is run once more only when the code or the tests changed after it passed with the unit tests; otherwise it is not run again. Passing, the tests record is written and committed with the tests; otherwise all of it - code fixes included - is rolled back, and the module halts until \*\*\*plain or the code changes, or `conform` asks again: its conformance tests, its code - nothing more is built on code whose conformance tests did not pass - and every module built on it, which waits.
|
|
340
|
+
A conformance job is a \*\*\*plain diff's conformance run: the tests of its change written, changed or taken out, a failure judged - the test or the code wrong - and fixed, then the whole suite with the unit tests, the tests the module inherits with them. Its \*\*\*plain diff shows a scenario changed as a diff of its test plain file, under the file's own path, after the module's file - and only the test plain file when nothing else of the functional spec changed, with no section header of the module's over it - rebuilt from the trees as the module's file is, so a pulse shows only its own change; a code pulse's diff never has one. The run that passed already was of the whole suite - the module's tests folder holds the chain's, copied up - so the suite is run once more only when the code or the tests changed after it passed with the unit tests; otherwise it is not run again. Passing, the tests record is written and committed with the tests; otherwise all of it - code fixes included - is rolled back, and the module halts until \*\*\*plain or the code changes, or `conform` asks again: its conformance tests, its code - nothing more is built on code whose conformance tests did not pass - and every module built on it, which waits.
|
|
321
341
|
|
|
322
|
-
**Up the chain.** A module built on another starts from its code and its conformance tests, copied up, and its conformance testing script runs those with its own. So a module waits for the one below it until that one's code is built and
|
|
342
|
+
**Up the chain.** A module built on another starts from its code and its conformance tests, copied up, and its conformance testing script runs those with its own. So a module waits for the one below it until that one's code is built and the conformance tests of its scenarios are written and pass; only then is its codebase started from there. Its tests record starts as the one below's, as what it inherits: `base:add-task` with its scenarios among its required functional specs. From then on the tip's suite is where they are kept up to date: a change to `base:add-task`, or to its scenarios, is conformance work in the tip, cased and labelled `base:add-task` there, and `base`'s own tests folder, left behind, is not touched.
|
|
323
343
|
|
|
324
|
-
|
|
344
|
+
**`conform`.** The loop starts conformance pulses by itself; `conform` starts them now - every functional spec of the module with scenarios, or those named as `module:func-id`. Named, it writes their tests alone: the module's other functional specs whose tests are behind are left as they are - `drift` lists them, saying conform asked for the named ones alone - until `conform` names none or the module is asked for again (`regenerate`); one of them whose text or scenarios change meanwhile joins those named. A module none of whose functional specs has scenarios, a functional spec \*\*\*plain does not have, one with no scenarios ("write them first") or a module that skipped a step of adding tests ([above](#the-steps-of-adding-tests)) is refused, and nothing is started. `conform` changes the module named alone, never the modules below it. For a module not regenerated yet, its tests are written once its code is built, before anything is built on it. For a module already regenerated whose tests are not written, while a module above it was started from it - its first pulse running, or code of its own built - the codebase above is disposable: a pulse running there is stopped, whatever `allow-to-stop-jobs` says, as the person asked; the codebase is deleted whole, its history with it; the tests are written in the module's own codebase; and the module above is regenerated from it once they pass. With every test written for what is built, it says so, and nothing is touched.
|
|
325
345
|
|
|
326
|
-
|
|
327
|
-
- `module`: it is asked once, when the module's last code pulse lands, of every functional spec of the module that is built and has none - and it plans them too, into groups, each a conformance pulse of its own.
|
|
346
|
+
**`turri drift`** lists the conformance work one functional spec a line, its scenarios counted by case, and why else its tests are behind:
|
|
328
347
|
|
|
329
|
-
|
|
348
|
+
```
|
|
349
|
+
conformance tests: to write or change - written once the code is built, or now with conform
|
|
350
|
+
todo:add-task 2 added
|
|
351
|
+
todo:edit-task 1 added, 1 changed, 1 removed
|
|
352
|
+
todo:list-tasks its code was regenerated again - 3 to run on it
|
|
353
|
+
todo:delete-task taken out - its tests go (2 removed)
|
|
354
|
+
```
|
|
330
355
|
|
|
331
|
-
|
|
356
|
+
A functional spec with no scenarios is not listed: `parse` shows it as "no scenarios - not tested".
|
|
332
357
|
|
|
333
|
-
|
|
358
|
+
While a codebase's work is being planned into jobs, with nothing running there, what is planned says so - the conformance tests being planned, or the work - rather than showing nothing until the plan is made. A module asked for - `regenerate`, from scratch, functionalities again - shows its work as being planned from that moment, before its code is deleted and what is left is worked out, not only once the planner runs: in the loop's status, which a host draws its plan from, and in the job panel - a module the loop holds nothing of yet, as when turri was just opened, too. A \*\*\*plain change is looked at quietly.
|
|
334
359
|
|
|
335
|
-
|
|
360
|
+
**What a conformance job tests is built.** As a conformance job starts, the harness reads the code record, `code/.turri.json`, and checks that it has every functional spec the job adds or changes tests for, as the job has it. One it does not have stops the job before any agent runs: its report says which are not built, the conformance tests halt, and the chat model tells the person. They are tried again once the code or \*\*\*plain changes. Code jobs and conformance jobs are planned apart, each track on its own: a job is one or the other. A module built on another starts with the tests record below it, as what it inherits: none of its own tests is written yet.
|
|
336
361
|
|
|
337
|
-
|
|
362
|
+
### Scenario by scenario
|
|
338
363
|
|
|
339
|
-
|
|
364
|
+
A conformance job goes down to the scenarios. For each functional spec it touches it compares the scenarios with the tests record by kind and scenario-id, as functional specs are compared by func-id, and its agent and its reviewer are told each scenario's case by the label its tests carry:
|
|
340
365
|
|
|
341
|
-
|
|
366
|
+
| scenario | the tests |
|
|
367
|
+
| --- | --- |
|
|
368
|
+
| added | written |
|
|
369
|
+
| changed - its text, or a file it links | rewritten to the scenario as it reads now |
|
|
370
|
+
| removed | deleted, every test labelled with it - and nothing else |
|
|
371
|
+
| unchanged | left exactly as they are |
|
|
372
|
+
| unchanged, its functional spec's code changed - its text or a file it links patched, it was regenerated again, or a concept it uses changed | run on the new code: those that pass stay as they are, and one that fails is fixed against its scenario, read with the functional spec's text - no test holds the new code to what only the old code did |
|
|
342
373
|
|
|
343
|
-
|
|
344
|
-
| --- | --- | --- |
|
|
345
|
-
| Conformance tests | the functional spec itself - what it says the functionality does, its edge cases, its errors - as if no acceptance tests had been given | files whose names say conformance, each starting with a comment `conformance tests of functionality 3` |
|
|
346
|
-
| Acceptance tests | each acceptance test in \*\*\*plain, implemented as a test of its own, doing what it says | files whose names say acceptance, each test with a comment `acceptance test 2 of functionality 3:` and the acceptance test's text |
|
|
374
|
+
A scenario given another scenario-id, and nothing else with it, is relabelled by turri itself, its tests not rewritten (see [a pure rename](#what-a-job-is-given-and-what-it-records)); renamed with any other change of its functional spec's, it is one removed and one added, and so is one moved between `***conformance tests***` and `***acceptance tests***`, as its label changes; one moved between two test plain files of the same functional spec is nothing. A functional spec whose text and scenarios both changed gets both cases. The tests record stores nothing new for it: each scenario's `{id, text}`, as written. The reviewer holds the agent to the cases: the tests of an unchanged scenario come out unchanged - unless the code changed under it and a test failed on it - and none labelled with a removed scenario is left.
|
|
347
375
|
|
|
348
|
-
|
|
376
|
+
### Exactly the scenarios, labelled
|
|
377
|
+
|
|
378
|
+
The conformance agent carries out a functional spec's scenarios, and nothing else: each conformance scenario and each acceptance scenario gets at least one test that does what it says and asserts what it expects. It writes no test of its own beside them - no edge case or error the scenarios do not name, however much the functional spec says. The scenarios reach it under `<conformance tests>` and `<acceptance tests>`, each under its label.
|
|
379
|
+
|
|
380
|
+
| | Labelled |
|
|
381
|
+
| --- | --- |
|
|
382
|
+
| A file of a functional spec's tests | a comment at its top: `conformance tests of todo:add-task` - one line for each functional spec the file tests |
|
|
383
|
+
| A test | a comment right above it: `conformance scenario rejects-empty-title of todo:add-task`, or `acceptance scenario adds-and-lists of todo:add-task` |
|
|
349
384
|
|
|
350
|
-
The labels are checked, not trusted: before a passing run counts, the harness reads the tests and sends the agent back for a
|
|
385
|
+
The labels are checked, not trusted: before a passing run counts, the harness reads the tests and sends the agent back for a functional spec with no labelled file, or for any scenario no test is labelled as carrying out - of every functional spec the tests are written for once the job lands, not only those it touches. A label that names nothing those are - a functional spec or a scenario taken out, a label mistyped, a test invented beside the scenarios - sends it back too, to remove the test or relabel it with the scenario it does carry out. A label is matched on its whole key, so `todo:log-in` is never found in `todo:log-in-2`. For a \*\*\*plain change that touches several functional specs, everything missing - every one's - is asked for in one request, the agent told to keep the labels there already, and the whole set checked again after each answer. Anyone reading the tests - or the next agent - sees at a glance which scenario a test carries out.
|
|
351
386
|
|
|
352
387
|
### Regenerated apart from the code
|
|
353
388
|
|
|
354
|
-
The code and its conformance tests are regenerated apart, each in its own folder (see [the sandbox](sandbox.md#what-an-agent-can-reach)). The test author writes only the tests folder; its file tools can read the code too, and it is told so - read access, never write access - and to take how the software is reached from the code, never what it should do. Its shell holds the tests folder only. The coding agent that fixes the code is told the same of the tests: it can read them, never change them. Before the test author starts, an explorer - an agent in the code's folder with the file tools alone: it reads the code, runs nothing and changes nothing - hands over everything the author needs, in parts: how to build and run it; how the conformance tests reach it as the project's conformance testing script runs them - the explorer is given the script, and the prepare script before it where there is one, and says what they build or installs and what the tests depend on or start (a package, a module, an entry point, by its exact name); how each functionality is reached from outside (the command, or the route, method and the request and response fields); what it needs around it
|
|
389
|
+
The code and its conformance tests are regenerated apart, each in its own folder (see [the sandbox](sandbox.md#what-an-agent-can-reach)). The test author writes only the tests folder; its file tools can read the code too, and it is told so - read access, never write access - and to take how the software is reached from the code, never what it should do. Its shell holds the tests folder only. The coding agent that fixes the code is told the same of the tests: it can read them, never change them. Before the test author starts, an explorer - an agent in the code's folder with the file tools alone: it reads the code, runs nothing and changes nothing - hands over everything the author needs, in parts: how to build and run it; how the conformance tests reach it as the project's conformance testing script runs them - the explorer is given the script, and the prepare script before it where there is one, and says what they build or installs and what the tests depend on or start (a package, a module, an entry point, by its exact name); how each functionality is reached from outside (the command, or the route, method and the request and response fields); and what it needs around it. What to test is not the explorer's to say: it is the scenarios. The account is checked before it is used: it has to say how the functionality under test is reached (for a \*\*\*plain diff, some of the module the change touches). One that does not is sent back saying what is missing. It is kept focused: the interface to what is under test, not a survey of the codebase, in words rather than code, under 12,000 characters. Each hand-over ends its turn, and it hands over three times at most. If it never completes it, what it wrote as it worked goes along with it, so nothing it found is lost. The tests are written from that account, the scenarios and \*\*\*plain, and every assertion comes from the scenarios and \*\*\*plain. `run_conformance_tests` puts the whole suite together with a copy of the build in a throwaway directory, so tests cannot accumulate state between attempts and nothing they write reaches the code.
|
|
355
390
|
|
|
356
391
|
While it writes the tests, the conformance agent can put a question to the explorer - `ask_explorer`, three times a run: how a functionality is reached, what a field is called. A fresh explorer, in the code's folder, given the account it handed over and the question, reads the code and answers in words; it runs and changes nothing. And `my_diff` shows it the tests folder's diff from where the run started, as its reviewer is shown it.
|
|
357
392
|
|
|
358
393
|
### When a conformance test fails
|
|
359
394
|
|
|
360
|
-
The harness runs the project's conformance testing script on the whole suite. When it passes, the unit testing script runs too - and then, with `review: true` in the config, the review gate: a reviewer reads the tests this run added or changed, and the code, and checks that they test black box - through the entry points the test reqs allow, never mocking or replacing any part of the software under test - that every test asserts what \*\*\*plain says, with no placeholder that cannot fail, and that each
|
|
395
|
+
The harness runs the project's conformance testing script on the whole suite. When it passes, the unit testing script runs too - and then, with `review: true` in the config, the review gate: a reviewer reads the tests this run added or changed, and the code, and checks that they test black box - through the entry points the test reqs allow, never mocking or replacing any part of the software under test - that every test asserts what \*\*\*plain says, with no placeholder that cannot fail, and that each scenario is carried out, every step it lists done and every expectation it states asserted. It must pass, as the suite and the unit tests must: when it does not, the conformance agent gets exactly what is missing and what is bad, file by file, and the round goes again. One reviewer does every review of the run, as the unit tests' does: the first time it is shown the diff of the tests folder from the module's last commit, each time after the diff since its last review, and every time the conformance agent's account through `submit_work` - checked against the diff, never taken instead of it. The first review is asked for every problem at once; each after it is given what the last one found, checks that first, and raises something new only when it is serious - a test that cannot fail, mocks the software, or leaves out what \*\*\*plain asks for. It asks only for what can be seen from outside: where \*\*\*plain says one part calls another, the outcome, never the call. The reviewer is the exacting developer, as the unit tests' is, and marks each problem blocking or not: blocking when the functionality is not yet tested black box - a scenario's test missing, cut down or skipping what it checks, the software mocked or not reached from outside, a test that cannot fail.
|
|
361
396
|
|
|
362
397
|
The tests are reviewed twice at most, as the unit tests are: the first review that sends them back goes to the conformance agent as it is, and the second the arbiter weighs first, as it does the unit tests' (see [the code and its unit tests are reviewed](#the-code-and-its-unit-tests-are-reviewed)): it upholds what leaves the functionality not tested black box, and dismisses what is out of scope or a nitpick. Only what it upholds goes back to the conformance agent; when it upholds nothing, the tests are approved as they are, and what it let go is kept in the result and the notes' pitfalls. The review optimises the tests, it does not stop the run: what the second review sends back is worked on once, and then the tests go on without another review - once the suite and the unit tests pass, which they still must. All three passing is done.
|
|
363
398
|
|
|
364
|
-
A \*\*\*plain diff's conformance run holds its tests to the same bar. The functionalities the change touches
|
|
399
|
+
A \*\*\*plain diff's conformance run holds its tests to the same bar. The functionalities the change touches are its job's cases - those it adds, changes or regenerates again - of those with scenarios. The conformance agent is shown their scenarios, each under its label; the run does not finish until each one is carried out by a labelled test; and the review checks each of them as it would a functionality's own.
|
|
365
400
|
|
|
366
401
|
A failing run's output goes to the judge and whoever fixes it whole when it is up to 60,000 characters, and otherwise its last 60,000 - where a test run says what failed and why - with the file the whole of it is kept in.
|
|
367
402
|
|
|
368
403
|
Why something failed is never lost. Every agent that writes or fixes code is told that where the code catches an error and turns it into a response, a status, a result or a retry, it logs the error with its whole trace, and what it hands on names the cause - never a bare "failed". When the output does not show why the software failed, the judge says the code is what is wrong, for hiding it, and the coding agent makes the cause show first, then fixes it. No agent may make the code behave differently when a test runs it. Both the conformance agent and the coding agent can run the conformance suite themselves, to reproduce a failure and check their fix - three times a turn: the third ends the turn, and the harness runs it and judges. The conformance agent is told that a failure of the software itself - it does not build or start, or does what \*\*\*plain says it must not - is not the tests' to work around. When it fails, a judge - an agent that reads the code and the tests, changes neither, and holds both to \*\*\*plain - decides which is wrong. It has the file tools and the web (`web_search`, `web_fetch`), to look up what a service the code calls answers - no shell: it judges from the code, the tests, \*\*\*plain, the conformance testing script word for word and the failing run's output, and its file tools write nothing. The explorer's account of how the code is invoked is in its prompt too, marked as written before the run and possibly wrong: the judge checks what it uses of it against the script and the files, and gives in `evidence` what it found itself. The script is fixed - neither agent can change it: what it does with the tests, the tests fit; what it needs of the build, the code provides. It is the culprit only when no code and no tests could pass it.
|
|
369
404
|
|
|
370
|
-
- **the code:** the coding agent - in the code's folder, reading the tests but never changing them - fixes it, and keeps its unit tests passing. The judge quotes \*\*\*plain's own words the code does not meet, or the testing script's for what it needs of the build (`script_needs`: a build output, an entry point, a module) - each checked by the harness against the text it quotes. The
|
|
405
|
+
- **the code:** the coding agent - in the code's folder, reading the tests but never changing them - fixes it, and keeps its unit tests passing. The judge quotes \*\*\*plain's own words the code does not meet, or the testing script's for what it needs of the build (`script_needs`: a build output, an entry point, a module) - each checked by the harness against the text it quotes. The scenarios are in that text, labelled as their tests are: for a \*\*\*plain change, those of every functional spec it touches, not only the last one's;
|
|
371
406
|
- **the tests:** the conformance agent corrects them to what \*\*\*plain says;
|
|
372
407
|
- **\*\*\*plain:** two functional specs cannot both hold, whatever the code does;
|
|
373
408
|
- **the environment:** neither the code nor the tests can fix it - only the person can, in what the run is given: a credential missing, empty or rejected (a 401 from a provider for a token no test made up), an account or quota a service refuses, a service \*\*\*plain names that cannot be reached, an interpreter or a toolchain this machine lacks. What a test sets up itself - a credential, a variable, a fixture - is the tests', and a package the code or the tests can declare is the agents';
|
|
@@ -375,7 +410,7 @@ Why something failed is never lost. Every agent that writes or fixes code is tol
|
|
|
375
410
|
|
|
376
411
|
The environment, or the testing script, is judged what is wrong twice in a row before it counts. The first time, the conformance agent checks that the tests do not cause it themselves and, when they do not, changes nothing; the second, the pulse stops, rolled back and not retried, and the person is told what to provide and where the run read it from - the testing scripts run in their own environment, so a credential comes from their shell's variables or a `.env` the script loads - or what to change in the script.
|
|
377
412
|
|
|
378
|
-
When the code and the tests could both be wrong, the judge is told to choose the tests. A \*\*\*plain conflict has to name the two functionalities, each by its module and id - they can be in different modules, since a module's codebase and its conformance suite hold the functionalities of the modules it requires too (
|
|
413
|
+
When the code and the tests could both be wrong, the judge is told to choose the tests. A \*\*\*plain conflict has to name the two functionalities, each by its module and id - they can be in different modules, since a module's codebase and its conformance suite hold the functionalities of the modules it requires too (`accounts:register` and `cognio:duplicate-email`). In a functionality's conformance run one of them must be the functionality under test - a conflict between two earlier ones would have come up when the later of them was tested (a \*\*\*plain diff's run may name any two). One that breaks these rules is sent back to the judge. A valid one is recorded, and the tests go back to the conformance agent, so the next judgement is of a new run. It counts only once the same two functionalities have been named three times. Then the run stops, and the person gets the conflict whole: both functional specs as they read, and each time what could not hold. The conversation's agent runs `analyze-2-func-specs` on the pair, then `resolve-spec-conflict` for the ways out, and puts the decision to the person - it changes nothing in \*\*\*plain before they have decided.
|
|
379
414
|
|
|
380
415
|
The judge holds only what \*\*\*plain says against the code: anything it leaves open - a name, coordinates, a version, a path, a package - is what the code already has, and the tests follow it. The coding agents keep the build's identity - name, coordinates, version, package, main class - as it is unless \*\*\*plain asks for another. And the conformance agent is given the code's build files (`pom.xml`, `package.json`, `pyproject.toml`, `go.mod`...) word for word, read by the harness: the one place to take what its tests' build points at from, never a guess from a folder name.
|
|
381
416
|
|
|
@@ -391,13 +426,13 @@ Then the suite runs again. A run that exits 80 goes back to the conformance agen
|
|
|
391
426
|
|
|
392
427
|
Before each run the harness checks for itself: both kinds of test are there and labelled, none of them is in the code folder, and no test went missing without being justified.
|
|
393
428
|
|
|
394
|
-
Conformance
|
|
429
|
+
Conformance tests live in the module's `tests` folder and nowhere else. One found in the code folder - by its label, or as a test file under a name or folder that says conformance or acceptance - is sent back: to the agent writing the tests, to move it; to an agent writing the code, to remove it, since those tests are not its to write. The conformance testing script refuses them too (see `implement-conformance-testing-script`), so a suite in the wrong place fails rather than passing unnoticed.
|
|
395
430
|
|
|
396
431
|
No agent runs the testing scripts itself. They are in its prompt so it knows what judges its work, but they are not in its workspace: it calls `run_unit_tests` and `run_conformance_tests`, which run them as the harness does. Its file tools refuse to write a copy of them, or a `.plain` file, into the codebase, and its working notes refuse a line telling the next agent to run them.
|
|
397
432
|
|
|
398
433
|
### Verified
|
|
399
434
|
|
|
400
|
-
After regenerating
|
|
435
|
+
After regenerating `hello:print-hello` of a hello-world Python \*\*\*plain, the conformance test runs the app as a subprocess and asserts on stdout, exit code and time - no import of internals:
|
|
401
436
|
|
|
402
437
|
```python
|
|
403
438
|
completed = subprocess.run([sys.executable, str(executable)], capture_output=True, text=True, timeout=1)
|
|
@@ -464,7 +499,7 @@ Two records per module, each committed with what it describes in the module's `.
|
|
|
464
499
|
| | |
|
|
465
500
|
| --- | --- |
|
|
466
501
|
| `code/.turri.json` | the code record: the \*\*\*plain description the code is built from - its whole requires chain's: the definitions and implementation reqs of the modules below, each tagged with its module, their functional specs among the ones it inherits, and its own - without the test reqs and the acceptance tests, which are for conformance only |
|
|
467
|
-
| `tests/.turri.json` | the tests record: the functional specs the conformance tests are written for - of the code record's, with their
|
|
502
|
+
| `tests/.turri.json` | the tests record: the functional specs the conformance tests are written for - of the code record's, those with scenarios, with their scenarios, the modules below's among them - the definitions and implementation reqs they were written against, and the test reqs they follow |
|
|
468
503
|
|
|
469
504
|
Nothing about how a build went: whether tests passed and which files a job touched are in the history, and how each pulse went is in the [ledger](using.md#the-ledger), which nothing reads to decide what to build. And nothing else is stored: what is left to build is worked out from the records whenever a job ends or \*\*\*plain changes - the code work from the code record to \*\*\*plain now (`src/regenerate/drift.ts`), the conformance work from the tests record to what the tests are to be written for. Only the running job is kept; what the panel shows as planned is worked out again. The tests record never goes ahead of the code's: a conformance test exercises functionality, and only what is in the code can be tested.
|
|
470
505
|
|
|
@@ -472,8 +507,8 @@ What goes into them:
|
|
|
472
507
|
|
|
473
508
|
- **A code job landed:** the code record becomes the \*\*\*plain description the job ends on.
|
|
474
509
|
- **A conformance job landed:** the tests record becomes what its tests are written for.
|
|
475
|
-
- **A module started from another's code:** that code's record, as a lower module's - see [where things go](#where-things-go) - and
|
|
476
|
-
- **A functional spec named to `regenerate`:** it is marked to be regenerated again in the code record, so the next job regenerates it again; that job's record drops the mark. Its conformance tests, when it has them, are marked in the tests record too, and the conformance job that runs them on the new code drops that mark once the whole suite passes.
|
|
510
|
+
- **A module started from another's code:** that code's record, as a lower module's - see [where things go](#where-things-go) - and that module's tests record the same way: the tests it inherits, and what they are written for.
|
|
511
|
+
- **A functional spec named to `regenerate`:** it is marked to be regenerated again in the code record, so the next job regenerates it again; that job's record drops the mark. Its conformance tests, when it has them, are marked in the same codebase's tests record too, and the conformance job that runs them on the new code drops that mark once the whole suite passes.
|
|
477
512
|
|
|
478
513
|
A unit of work - a code job, a conformance job - lands whole or is undone whole. It starts from the module's last commit, putting back whatever an interrupted run left; a module with no commit yet is given one first. When it does not pass, the module goes back to that commit: its changes, the files it added and any commit it made on the way are gone, with the record they came with. Installed dependencies and caches stay. So the code, its tests and the records of what they were built from never disagree.
|
|
479
514
|
|
package/docs/sentinel.md
CHANGED
|
@@ -47,7 +47,7 @@ Two functional specs that contradict each other stop a pulse in a way only you c
|
|
|
47
47
|
|
|
48
48
|
## What it may do
|
|
49
49
|
|
|
50
|
-
Nothing that changes the project. Its file tools - `read`, `ls`, `grep`, `find` - read the whole project, its \*\*\*plain among them, and write nothing; its shell runs [behind the walls](sandbox.md) every agent's does - the command check, the OS sandbox where one is up, the audit - with the project read only and the network open, its home and temporary folder its own. It has `ledger`, `pulses`, `diagnose`, `
|
|
50
|
+
Nothing that changes the project. Its file tools - `read`, `ls`, `grep`, `find` - read the whole project, its \*\*\*plain among them, and write nothing; its shell runs [behind the walls](sandbox.md) every agent's does - the command check, the OS sandbox where one is up, the audit - with the project read only and the network open, its home and temporary folder its own. It has `ledger`, `pulses`, `diagnose`, `parse`, `doctor` and the web, `notify_person` for its notices, `conclude` for when it is done with a pulse, `keep_guidance`, and what a host gives it. Whatever else it calls is refused: it never regenerates, steers, releases or changes \*\*\*plain, and never asks you a question - a notice is how it reaches you. What it found to do is yours to accept.
|
|
51
51
|
|
|
52
52
|
## Talking to it
|
|
53
53
|
|
package/docs/skills-and-gates.md
CHANGED
|
@@ -35,10 +35,12 @@ metadata:
|
|
|
35
35
|
...
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
A skill declares its steps with a `## Steps` section whose `###` headings are the steps; without it the whole skill is one step, which is what most skills are. Steps are never inferred from `###` headings elsewhere in the body - prose skills are full of those. Each gate becomes a conditional edge after its step; a single-step skill is gated by naming the skill itself.
|
|
38
|
+
A skill declares its steps with a `## Steps` section whose `###` headings are the steps; without it the whole skill is one step, which is what most skills are. Steps are never inferred from `###` headings elsewhere in the body - prose skills are full of those. Each gate becomes a conditional edge after its step; a single-step skill is gated by naming the skill itself. Of the skills turri ships, `convert-old-syntax` declares one - after its `rewrite`, two judges, reading the files themselves, check that moving a module to func-id headings and test plain files lost, changed and added nothing - and a project's own skill can declare its own.
|
|
39
39
|
|
|
40
40
|
`command-only: true` under `metadata:` keeps a skill from the model: it is started only by the person, with its slash command. None of turri's own is; turri registers the command for every such skill, the project's own too. Typed, the command puts what was typed in the chat as the person's message, and lets `cultivate` start the skill once - and so does an option starting with the command - a project's `/release-notes - for this release` - picked in the conversation's `ask_user` (`chosenCommand` in `src/skills.ts`). The answer tells the model to call `cultivate` for it at once, with the person's request word for word as its context (`startPicked`), so they never type the command after picking it; the run starting uses that up, so the model cannot start it again later on its own. Without either, `cultivate` refuses it and the model is told how the person starts it; the skill's line in `cultivate`'s list says so too.
|
|
41
41
|
|
|
42
|
+
`background: true` under `metadata:` runs a skill in the background, in the chat and a host: `cultivate` starts it and returns at once, and the chat's turn goes on. Nothing shows while it runs - no progress, no spinner - and nobody is asked anything: it has no `ask_user`, a gate it cannot pass stands, and its agent is told to decide what is left open and say what it decided. Its end comes back to the chat it was started from once that chat is idle - its agent done, nothing typed - batched, as the test advisor's verdicts are (`src/background-skills.ts`): a line drawn by turri when it did its work, naming the files it changed; a message that starts a turn when it stopped at a gate, failed, or changed no file, for the chat to tell the person and decide what next. One runs at a time a skill and project, whichever chat started it; quitting turri stops it. In pi's print, json and rpc modes, and from `turri cultivate`, it runs as any skill does, to its end. `model: coding` runs a skill on the coding model of the module it is for - `cultivate`'s `plainFile`: that module's stack's `coding-model` over the project's, and the one chosen with `engine` this session over both - the model a code pulse of that module runs on; without it, a skill runs on the chat's model (`harness-model` from the command line). turri's two that write the testing scripts, `implement-unit-testing-script` and `implement-conformance-testing-script`, are its only ones that set either, and they set both.
|
|
43
|
+
|
|
42
44
|
`paced: false` under `metadata:` lets a skill write \*\*\*plain changes one after another on its own: `change_plain` otherwise refuses a new change until the user has answered a question since the last one - one answer, one change, as an interview writes them. An unpaced skill is told so by the tool, and after each change to write the next at once, not to carry on with an interview it does not have.
|
|
43
45
|
|
|
44
46
|
`questioning:` under `metadata:` names the steps the questioning level caps (`src/questioning.ts`) - `[stack, product]`, say. When there are any and someone to ask, the harness itself asks the first question of the first step: how many questions those steps may ask - light (3), medium (5), thorough (10) or best judgement - and tells the agent the answer beside each step's instructions, with how broad each question is to be: broad at light, a whole area at once, narrow at thorough, an edge case at a time. Every level covers the same ground, in less or more depth. In a capped step `ask_user` refuses a question past the cap; the step's closing confirmation, asked with `confirms_phase: true`, is never counted. `end_questions` ends the step's questions sooner - best judgement's only end. What the questions leave open, the agent decides itself and says what it chose. The level, and how many questions each step has asked, are kept in the run's `run.json`, so a resumed run keeps them. A step it does not name, or a run with nobody to ask, is not capped.
|