@turri-dev/cli 0.1.4-next.318a98a → 0.1.4-next.5a8c6e5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/.pi/themes/turri-dark.json +67 -66
  2. package/.pi/themes/turri-light.json +71 -73
  3. package/README.md +40 -128
  4. package/assets/jellyfish/dark-00.png +0 -0
  5. package/assets/jellyfish/dark-01.png +0 -0
  6. package/assets/jellyfish/dark-02.png +0 -0
  7. package/assets/jellyfish/dark-03.png +0 -0
  8. package/assets/jellyfish/dark-04.png +0 -0
  9. package/assets/jellyfish/dark-05.png +0 -0
  10. package/assets/jellyfish/dark-06.png +0 -0
  11. package/assets/jellyfish/dark-07.png +0 -0
  12. package/assets/jellyfish/dark-08.png +0 -0
  13. package/assets/jellyfish/dark-09.png +0 -0
  14. package/assets/jellyfish/dark-10.png +0 -0
  15. package/assets/jellyfish/dark-11.png +0 -0
  16. package/assets/jellyfish/light-00.png +0 -0
  17. package/assets/jellyfish/light-01.png +0 -0
  18. package/assets/jellyfish/light-02.png +0 -0
  19. package/assets/jellyfish/light-03.png +0 -0
  20. package/assets/jellyfish/light-04.png +0 -0
  21. package/assets/jellyfish/light-05.png +0 -0
  22. package/assets/jellyfish/light-06.png +0 -0
  23. package/assets/jellyfish/light-07.png +0 -0
  24. package/assets/jellyfish/light-08.png +0 -0
  25. package/assets/jellyfish/light-09.png +0 -0
  26. package/assets/jellyfish/light-10.png +0 -0
  27. package/assets/jellyfish/light-11.png +0 -0
  28. package/dist/ask.js +34 -15
  29. package/dist/brand.js +7 -7
  30. package/dist/cli-options.js +12 -6
  31. package/dist/config-edit.js +1 -0
  32. package/dist/config.js +5 -2
  33. package/dist/cultivate-cli.js +16 -23
  34. package/dist/extension.js +59 -67
  35. package/dist/init-config.js +5 -0
  36. package/dist/jellyfish.js +130 -0
  37. package/dist/loop-cli.js +19 -7
  38. package/dist/loop-tools.js +11 -5
  39. package/dist/module-report.js +5 -4
  40. package/dist/pi.js +76 -19
  41. package/dist/question-dialog.js +1 -0
  42. package/dist/regenerate/activity.js +21 -0
  43. package/dist/regenerate/list-arguments.js +121 -0
  44. package/dist/regenerate/loop.js +21 -8
  45. package/dist/regenerate/plain-palette.js +52 -37
  46. package/dist/regenerate/regenerate.js +4 -2
  47. package/dist/regenerate/self-check.js +13 -6
  48. package/dist/regenerate/side-panel.js +1 -1
  49. package/dist/regenerate/spec-map-view.js +9 -5
  50. package/dist/regenerate/test-scripts.js +54 -10
  51. package/dist/regenerate/unit-review.js +1 -1
  52. package/dist/regenerate-cli.js +11 -5
  53. package/dist/release-cli.js +3 -8
  54. package/dist/review/live.js +2 -1
  55. package/dist/run-report.js +39 -1
  56. package/dist/validate-cli.js +3 -8
  57. package/docs/README.md +5 -12
  58. package/docs/authoring-plain.md +37 -119
  59. package/docs/config.md +53 -178
  60. package/docs/deploy.md +21 -80
  61. package/docs/development.md +13 -41
  62. package/docs/headless.md +45 -121
  63. package/docs/images/how-turri-works.svg +29 -31
  64. package/docs/images/turri-banner.png +0 -0
  65. package/docs/installation.md +13 -40
  66. package/docs/parser.md +15 -43
  67. package/docs/regenerating.md +229 -938
  68. package/docs/sandbox.md +38 -152
  69. package/docs/skills-and-gates.md +50 -171
  70. package/docs/theming.md +45 -46
  71. package/docs/using.md +69 -345
  72. package/genome/rules/bullet-continuation.md +5 -13
  73. package/genome/rules/concise-specs-examples.md +2 -4
  74. package/genome/rules/concise-specs-integration-examples.md +2 -6
  75. package/genome/rules/concise-specs.md +1 -2
  76. package/genome/rules/func-specs.md +1 -0
  77. package/genome/rules/integration-embedded-testing.md +1 -4
  78. package/genome/rules/integrations.md +1 -2
  79. package/genome/rules/project-model.md +14 -35
  80. package/genome/rules/stdlib.md +14 -49
  81. package/genome/rules/turri-regeneration.md +48 -0
  82. package/genome/skills/add-implementation-requirement/SKILL.md +1 -2
  83. package/genome/skills/analyze-if-func-spec-too-complex/SKILL.md +3 -8
  84. package/genome/skills/brood/SKILL.md +37 -127
  85. package/genome/skills/brood/references/intent.md +4 -12
  86. package/genome/skills/brood/references/product.md +24 -76
  87. package/genome/skills/brood/references/stack.md +7 -29
  88. package/genome/skills/brood/references/testing.md +11 -42
  89. package/genome/skills/bud/SKILL.md +32 -109
  90. package/genome/skills/bud/references/intent.md +4 -11
  91. package/genome/skills/implement-conformance-testing-script/SKILL.md +3 -6
  92. package/genome/skills/implement-unit-testing-script/SKILL.md +1 -2
  93. package/genome/skills/mature/SKILL.md +21 -69
  94. package/genome/skills/refactor-module/SKILL.md +24 -2
  95. package/genome/skills/spawn/SKILL.md +28 -113
  96. package/package.json +1 -1
  97. package/assets/jellyfish/dark-12.png +0 -0
  98. package/assets/jellyfish/dark-13.png +0 -0
  99. package/assets/jellyfish/dark-14.png +0 -0
  100. package/assets/jellyfish/fallback.txt +0 -252
  101. package/assets/jellyfish/light-12.png +0 -0
  102. package/assets/jellyfish/light-13.png +0 -0
  103. package/assets/jellyfish/light-14.png +0 -0
@@ -2,79 +2,80 @@
2
2
  "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
3
  "name": "turri-dark",
4
4
  "vars": {
5
- "yellow": "#e0ff6e",
6
- "yellowMuted": "#b9cb69",
7
- "green": "#79fc96",
8
- "greenLight": "#c5dcd9",
9
- "greenDark": "#223936",
10
- "black": "#0f0f0f",
11
- "white": "#ffffff",
12
- "gray": "#808080",
13
- "grayLight": "#666666",
14
- "statusError": "#dd5353",
15
- "statusWarning": "#dc6803"
5
+ "abyss": "#0a0f1a",
6
+ "blueWhale": "#1e3442",
7
+ "lines": "#22344a",
8
+ "path": "#3e5a6b",
9
+ "grauzone": "#85a3b2",
10
+ "white": "#f4f7f9",
11
+ "siestaTan": "#e9d8c8",
12
+ "pink": "#ff5c8d",
13
+ "pinkHover": "#ff7fa6",
14
+ "neon": "#5ce1e6",
15
+ "neonHover": "#8eebee",
16
+ "orange": "#ff7a3d"
16
17
  },
17
18
  "colors": {
18
- "accent": "yellow",
19
- "border": "green",
20
- "borderAccent": "green",
21
- "borderMuted": "greenDark",
22
- "success": "green",
23
- "error": "statusError",
24
- "warning": "statusWarning",
25
- "muted": "gray",
26
- "dim": "grayLight",
27
- "text": "greenLight",
28
- "thinkingText": "gray",
29
- "selectedBg": "greenDark",
30
- "scrollbarTrack": "greenDark",
31
- "scrollbarThumb": "green",
32
- "searchMatchBg": "yellow",
33
- "searchMatchText": "black",
19
+ "accent": "neon",
20
+ "border": "path",
21
+ "borderAccent": "neon",
22
+ "borderMuted": "lines",
23
+ "success": "pink",
24
+ "error": "orange",
25
+ "warning": "orange",
26
+ "muted": "grauzone",
27
+ "dim": "path",
28
+ "text": "grauzone",
29
+ "thinkingText": "grauzone",
30
+ "selectedBg": "blueWhale",
31
+ "scrollbarTrack": "lines",
32
+ "scrollbarThumb": "path",
33
+ "searchMatchBg": "neon",
34
+ "searchMatchText": "abyss",
34
35
  "userMessageBg": "",
35
- "userMessageText": "yellow",
36
+ "userMessageText": "white",
36
37
  "customMessageBg": "",
37
- "customMessageText": "greenLight",
38
- "customMessageLabel": "yellow",
38
+ "customMessageText": "grauzone",
39
+ "customMessageLabel": "neon",
39
40
  "toolPendingBg": "",
40
41
  "toolSuccessBg": "",
41
42
  "toolErrorBg": "",
42
- "toolTitle": "yellow",
43
- "toolOutput": "gray",
44
- "mdHeading": "yellow",
45
- "mdLink": "green",
46
- "mdLinkUrl": "grayLight",
47
- "mdCode": "yellowMuted",
48
- "mdCodeBlock": "greenLight",
49
- "mdCodeBlockBorder": "greenDark",
50
- "mdQuote": "gray",
51
- "mdQuoteBorder": "greenDark",
52
- "mdHr": "grayLight",
53
- "mdListBullet": "green",
54
- "toolDiffAdded": "green",
55
- "toolDiffRemoved": "statusError",
56
- "toolDiffContext": "gray",
57
- "syntaxComment": "grayLight",
58
- "syntaxKeyword": "yellow",
59
- "syntaxFunction": "green",
60
- "syntaxVariable": "greenLight",
61
- "syntaxString": "yellowMuted",
62
- "syntaxNumber": "statusWarning",
63
- "syntaxType": "white",
64
- "syntaxOperator": "gray",
65
- "syntaxPunctuation": "grayLight",
66
- "thinkingOff": "grayLight",
67
- "thinkingMinimal": "gray",
68
- "thinkingLow": "greenLight",
69
- "thinkingMedium": "green",
70
- "thinkingHigh": "yellowMuted",
71
- "thinkingXhigh": "yellow",
72
- "thinkingMax": "statusWarning",
73
- "bashMode": "yellow"
43
+ "toolTitle": "white",
44
+ "toolOutput": "grauzone",
45
+ "mdHeading": "white",
46
+ "mdLink": "neon",
47
+ "mdLinkUrl": "path",
48
+ "mdCode": "siestaTan",
49
+ "mdCodeBlock": "white",
50
+ "mdCodeBlockBorder": "lines",
51
+ "mdQuote": "grauzone",
52
+ "mdQuoteBorder": "path",
53
+ "mdHr": "lines",
54
+ "mdListBullet": "neon",
55
+ "toolDiffAdded": "neon",
56
+ "toolDiffRemoved": "pink",
57
+ "toolDiffContext": "grauzone",
58
+ "syntaxComment": "path",
59
+ "syntaxKeyword": "pinkHover",
60
+ "syntaxFunction": "neon",
61
+ "syntaxVariable": "white",
62
+ "syntaxString": "siestaTan",
63
+ "syntaxNumber": "pinkHover",
64
+ "syntaxType": "neonHover",
65
+ "syntaxOperator": "grauzone",
66
+ "syntaxPunctuation": "path",
67
+ "thinkingOff": "path",
68
+ "thinkingMinimal": "grauzone",
69
+ "thinkingLow": "siestaTan",
70
+ "thinkingMedium": "neonHover",
71
+ "thinkingHigh": "neon",
72
+ "thinkingXhigh": "pinkHover",
73
+ "thinkingMax": "pink",
74
+ "bashMode": "orange"
74
75
  },
75
76
  "export": {
76
- "pageBg": "#0f0f0f",
77
- "cardBg": "#121212",
78
- "infoBg": "#223936"
77
+ "pageBg": "#0a0f1a",
78
+ "cardBg": "#0d1420",
79
+ "infoBg": "#142030"
79
80
  }
80
- }
81
+ }
@@ -2,81 +2,79 @@
2
2
  "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
3
  "name": "turri-light",
4
4
  "vars": {
5
- "blue": "#0a1fd4",
6
- "greenLight": "#c5dcd9",
7
- "greenDark": "#223936",
8
- "diffGreen": "#1a7f37",
9
- "black": "#0f0f0f",
10
- "gray": "#808080",
11
- "grayLight": "#666666",
12
- "red": "#d00505",
13
- "statusErrorLight": "#fee4e2",
14
- "statusWarningLight": "#fef0c7",
15
- "statusWarning": "#dc6803",
16
- "paleGreen": "#eef7f5",
17
- "paleGray": "#f4f4f2"
5
+ "abyss": "#0a0f1a",
6
+ "blueWhale": "#1e3442",
7
+ "lines": "#22344a",
8
+ "path": "#3e5a6b",
9
+ "grauzone": "#85a3b2",
10
+ "white": "#f4f7f9",
11
+ "siestaTan": "#e9d8c8",
12
+ "eggplant": "#732553",
13
+ "pink": "#ff5c8d",
14
+ "neon": "#5ce1e6",
15
+ "orange": "#ff7a3d"
18
16
  },
19
17
  "colors": {
20
- "accent": "blue",
21
- "border": "gray",
22
- "borderAccent": "blue",
23
- "borderMuted": "greenLight",
24
- "success": "greenDark",
25
- "error": "red",
26
- "warning": "statusWarning",
27
- "muted": "grayLight",
28
- "dim": "gray",
29
- "text": "black",
30
- "thinkingText": "grayLight",
31
- "selectedBg": "greenLight",
32
- "scrollbarTrack": "greenLight",
33
- "scrollbarThumb": "grayLight",
34
- "searchMatchBg": "statusWarningLight",
35
- "searchMatchText": "black",
36
- "userMessageBg": "paleGray",
37
- "userMessageText": "black",
38
- "customMessageBg": "paleGreen",
39
- "customMessageText": "black",
40
- "customMessageLabel": "blue",
41
- "toolPendingBg": "paleGray",
42
- "toolSuccessBg": "paleGreen",
43
- "toolErrorBg": "statusErrorLight",
44
- "toolTitle": "blue",
45
- "toolOutput": "grayLight",
46
- "mdHeading": "blue",
47
- "mdLink": "blue",
48
- "mdLinkUrl": "grayLight",
49
- "mdCode": "greenDark",
50
- "mdCodeBlock": "black",
51
- "mdCodeBlockBorder": "greenLight",
52
- "mdQuote": "grayLight",
53
- "mdQuoteBorder": "greenLight",
54
- "mdHr": "gray",
55
- "mdListBullet": "blue",
56
- "toolDiffAdded": "diffGreen",
57
- "toolDiffRemoved": "red",
58
- "toolDiffContext": "grayLight",
59
- "syntaxComment": "grayLight",
60
- "syntaxKeyword": "blue",
61
- "syntaxFunction": "greenDark",
62
- "syntaxVariable": "black",
63
- "syntaxString": "greenDark",
64
- "syntaxNumber": "statusWarning",
65
- "syntaxType": "blue",
66
- "syntaxOperator": "gray",
67
- "syntaxPunctuation": "grayLight",
68
- "thinkingOff": "gray",
69
- "thinkingMinimal": "grayLight",
70
- "thinkingLow": "greenDark",
71
- "thinkingMedium": "blue",
72
- "thinkingHigh": "blue",
73
- "thinkingXhigh": "statusWarning",
74
- "thinkingMax": "red",
75
- "bashMode": "blue"
18
+ "accent": "eggplant",
19
+ "border": "path",
20
+ "borderAccent": "eggplant",
21
+ "borderMuted": "grauzone",
22
+ "success": "eggplant",
23
+ "error": "orange",
24
+ "warning": "orange",
25
+ "muted": "path",
26
+ "dim": "grauzone",
27
+ "text": "abyss",
28
+ "thinkingText": "path",
29
+ "selectedBg": "siestaTan",
30
+ "scrollbarTrack": "siestaTan",
31
+ "scrollbarThumb": "path",
32
+ "searchMatchBg": "neon",
33
+ "searchMatchText": "abyss",
34
+ "userMessageBg": "white",
35
+ "userMessageText": "abyss",
36
+ "customMessageBg": "",
37
+ "customMessageText": "abyss",
38
+ "customMessageLabel": "eggplant",
39
+ "toolPendingBg": "",
40
+ "toolSuccessBg": "",
41
+ "toolErrorBg": "",
42
+ "toolTitle": "abyss",
43
+ "toolOutput": "path",
44
+ "mdHeading": "eggplant",
45
+ "mdLink": "blueWhale",
46
+ "mdLinkUrl": "path",
47
+ "mdCode": "eggplant",
48
+ "mdCodeBlock": "abyss",
49
+ "mdCodeBlockBorder": "grauzone",
50
+ "mdQuote": "path",
51
+ "mdQuoteBorder": "grauzone",
52
+ "mdHr": "grauzone",
53
+ "mdListBullet": "eggplant",
54
+ "toolDiffAdded": "blueWhale",
55
+ "toolDiffRemoved": "eggplant",
56
+ "toolDiffContext": "path",
57
+ "syntaxComment": "path",
58
+ "syntaxKeyword": "eggplant",
59
+ "syntaxFunction": "blueWhale",
60
+ "syntaxVariable": "abyss",
61
+ "syntaxString": "lines",
62
+ "syntaxNumber": "eggplant",
63
+ "syntaxType": "blueWhale",
64
+ "syntaxOperator": "path",
65
+ "syntaxPunctuation": "path",
66
+ "thinkingOff": "grauzone",
67
+ "thinkingMinimal": "path",
68
+ "thinkingLow": "lines",
69
+ "thinkingMedium": "blueWhale",
70
+ "thinkingHigh": "eggplant",
71
+ "thinkingXhigh": "pink",
72
+ "thinkingMax": "orange",
73
+ "bashMode": "orange"
76
74
  },
77
75
  "export": {
78
- "pageBg": "#ffffff",
79
- "cardBg": "#f4f4f2",
80
- "infoBg": "#eef7f5"
76
+ "pageBg": "#f4f7f9",
77
+ "cardBg": "#f4f7f9",
78
+ "infoBg": "#e9d8c8"
81
79
  }
82
- }
80
+ }
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- <p align="center"><img src="docs/images/turri-banner.png" alt="turri - coding agent with the power of regenerative software: regenerate, drift, lineage"></p>
1
+ <p align="center"><img src="docs/images/turri-banner.png" alt="turri - the first coding agent with the power of regenerative software, beside a pixel jellyfish: npm install -g @turri-dev/cli"></p>
2
2
 
3
3
  <h1 align="center">turri<br>the first coding agent with the power of<br>regenerative software<br>&nbsp;</h1>
4
4
 
@@ -8,19 +8,13 @@
8
8
  <a href="https://nodejs.org/en/download"><img src="https://img.shields.io/node/v/@turri-dev/cli" alt="Node version"></a>
9
9
  </p>
10
10
 
11
- You tell **turri** what the system should do, and **turri** writes it down as [\*\*\*plain](https://plainlang.org/).
12
- **turri** builds the code from it. From then on \*\*\*plain is the durable source of truth: the code can always be
13
- regenerated from it, and healed against it, as it changes.
11
+ **turri** builds regenerative software: what lasts is the system's intent, and the code is derived from it - cheap to throw away and build again. You tell **turri** what the system should do; **turri** writes that down as durable intent, with the tests that say when it is met, and builds the code from it. From then on the durable intent is the source of truth: as it changes, the code is regenerated from it rather than patched in place, and never left to drift from it.
14
12
 
15
- **turri** is named after *Turritopsis dohrnii*, the immortal jellyfish that regenerates itself from its young
16
- form, again and again - as **turri** regenerates the code from \*\*\*plain - see [the name](#the-name).
13
+ **turri** is named after *Turritopsis dohrnii*, the immortal jellyfish that regenerates itself from its young form, again and again - as **turri** regenerates the code from the durable intent - see [the name](#the-name).
17
14
 
18
15
  ## Quick start
19
16
 
20
- **turri** is built on [pi](https://pi.dev), the coding agent, and runs wherever pi runs: macOS, Linux, WSL; native
21
- Windows best effort, with Git Bash. You need git, bash and [Node](https://nodejs.org/en/download) 22.19 or newer - a
22
- Linux distribution's own `nodejs` package is often older. The agents use this machine's toolchains, fenced by a command check and an audit everywhere, and an OS sandbox where the
23
- OS has one - Seatbelt on macOS, bubblewrap on Linux (`apt install bubblewrap`) - see [installation](docs/installation.md#installation).
17
+ **turri** is built on [pi](https://pi.dev), the coding agent, and runs wherever pi runs: macOS, Linux, WSL; native Windows best effort, with Git Bash. You need git, bash and [Node](https://nodejs.org/en/download) 22.19 or newer - a Linux distribution's own `nodejs` package is often older. The agents use this machine's toolchains, fenced by a command check and an audit everywhere, and an OS sandbox where the OS has one - Seatbelt on macOS, bubblewrap on Linux (`apt install bubblewrap`) - see [installation](docs/installation.md#installation).
24
18
 
25
19
  ```bash
26
20
  npm install -g @turri-dev/cli # puts `turri` on your PATH
@@ -29,11 +23,7 @@ turri doctor # checks the machine
29
23
 
30
24
  To follow `main` as it moves, or work on turri itself, run it [from a clone](#from-a-clone) instead.
31
25
 
32
- `doctor` checks for Node 22.19+, bash, the OS sandbox and a model provider for pi; in a project, the toolchains its
33
- modules need, what its testing scripts run against this machine, and that each model `config.turri.yaml` names
34
- answers with your credentials. It changes nothing without asking: when a check fails - the OS sandbox does not start,
35
- say - it says why, and the command for you to run. Run it again whenever something breaks. What each check means:
36
- [installation](docs/installation.md).
26
+ `doctor` checks for Node 22.19+, bash, the OS sandbox and a model provider for pi; in a project, the toolchains its modules need, what its testing scripts run against this machine, and that each model `config.turri.yaml` names answers with your credentials. It changes nothing without asking: when a check fails - the OS sandbox does not start, say - it says why, and the command for you to run. Run it again whenever something breaks. What each check means: [installation](docs/installation.md).
37
27
 
38
28
  Then start it in your project, signed in to your model providers:
39
29
 
@@ -44,26 +34,20 @@ export ANTHROPIC_API_KEY=... # the key it names - or skip it, and type /login
44
34
  turri
45
35
  ```
46
36
 
47
- `turri init-config` asks which vendor's models you use and writes the project's `config.turri.yaml` with two of theirs - a
48
- capable one you talk to, which writes \*\*\*plain and plans the work, and a smaller, cheaper one that writes the code.
49
- For Anthropic:
37
+ `turri init-config` asks which vendor's models you use and writes the project's `config.turri.yaml` with two of theirs - a capable one you talk to, which writes the durable intent and plans the work, and a smaller, cheaper one that writes the code. For Anthropic:
50
38
 
51
39
  ```yaml
52
- harness-model: anthropic/claude-opus-5-5:medium # you talk to it: it writes ***plain and plans the work
40
+ harness-model: anthropic/claude-opus-5-5:medium # you talk to it
53
41
  coding-model: anthropic/claude-haiku-5-5:low # it writes the code
54
42
  ```
55
43
 
56
- To skip the question, name the vendor - `anthropic`, `openai`, `google`, `amazon-bedrock` (with `--maker` and
57
- `--region`) or `other`:
44
+ To skip the question, name the vendor - `anthropic`, `openai`, `google`, `amazon-bedrock` (with `--maker` and `--region`) or `other`:
58
45
 
59
46
  ```bash
60
47
  turri init-config --vendor anthropic
61
48
  ```
62
49
 
63
- It then tells you which API key to set - or to type `/login` once **turri** is running instead. **turri** loads the
64
- `config.turri.yaml` in the folder you start it from.
65
- Below the two models, the file sets every other setting to its default - change any of them in the file, or from the
66
- chat with `/turri-config`. Any other model works too: [models](#models).
50
+ It then tells you which API key to set - or to type `/login` once **turri** is running instead. **turri** loads the `config.turri.yaml` in the folder you start it from. Below the two models, the file sets every other setting to its default - change any of them in the file, or from the chat with `/turri-config`. Any other model works too: [models](#models).
67
51
 
68
52
  Once `turri` is running, say: *Let's start a new project: a small API where people can register and sign in.*
69
53
 
@@ -91,91 +75,44 @@ git pull
91
75
  npm install # picks up any dependency that changed
92
76
  ```
93
77
 
94
- A **turri** already running keeps the code it started with - start it again to run what you pulled. More in
95
- [installation](docs/installation.md#from-a-clone).
78
+ A **turri** already running keeps the code it started with - start it again to run what you pulled. More in [installation](docs/installation.md#from-a-clone).
96
79
 
97
80
  ## Why
98
81
 
99
- In the age of coding agents, writing code is getting easy. The hard and important part is
100
- defining what the system should do. Agents can fix bugs, ask questions and keep getting more
101
- capable - but they still cannot read your mind. The question is not only whether an agent can
102
- write the code, but whether it understands what it is building.
82
+ Software has always been maintained: written once, then patched for as long as it lives and everything learnt while building it lived only in the code. Coding agents code in minutes what took a team weeks, and they get better at it with every model, so code is now cheap and a disposable asset. It no longer has to be maintained - it can be regenerated. What has to last instead is the intent: what the system should do, and the tests that say whether it does. Get that right and the code is replaceable. Get it wrong and no agent, however capable, can guess what you meant.
103
83
 
104
- Code that is patched, prompt after prompt, drifts: every misunderstanding stays in it, and the
105
- next change is made on top. When the software can always be regenerated from durable information
106
- instead, that understanding is written down - explicit, reviewable and tested - and it evolves with
107
- the software rather than against it.
84
+ Code that is patched, prompt after prompt, drifts: every misunderstanding stays in it, and the next change is made on top. When the software can always be regenerated from durable information instead, that understanding is written down - explicit, reviewable and tested - and it evolves with the software rather than against it.
108
85
 
109
86
  ## How it differs from ye old coding agent
110
87
 
111
- With a coding agent you work on code: you ask for a change, it edits the code, and you review the
112
- code it wrote.
88
+ With a coding agent you work on code: you ask for a change, it edits the code, and you review the code it wrote.
113
89
 
114
- With **turri** you work on \*\*\*plain. You say what the software must do, and **turri** updates \*\*\*plain
115
- and can always regenerate the code from that. You don't review the code or keep it - you review and
116
- keep the intent: what the software must do, and what must hold as it changes. \*\*\*plain is the
117
- durable part. The code is a disposable artefact, rebuilt from it whenever it changes.
90
+ With **turri** you work on the durable intent. You say what the software must do, and **turri** updates durable intent and can always regenerate the code from that. You don't review the code or keep it - you review and keep the intent: what the software must do, and what must hold as it changes. The code is a disposable artefact, rebuilt from it whenever it changes.
118
91
 
119
92
  | | ye old coding agent | **turri** |
120
93
  | --- | --- | --- |
121
- | **What you maintain** | the code, patched prompt after prompt | \*\*\*plain; the code is generated from it and never edited by hand |
122
- | **Who drives** | the agent picks what to do next | the harness, in a fixed order: one functionality or one change to \*\*\*plain at a time, or a whole module functionality by functionality, in \*\*\*plain's order, each on top of the ones before it |
123
- | **What counts as done** | the agent writes the code, runs the tests, and decides for itself that it is done | ye old coding agent writes the code; **turri** runs the whole test suite itself, with the project's own testing scripts, and decides deterministically when it is done - every test passes in its own run, or the work goes back |
124
- | **Tests** | written and changed by whoever writes the code | conformance tests written from \*\*\*plain, black box, and kept apart from your acceptance tests; an agent fixing the code cannot change them |
125
- | **What the agent sees** | your whole machine | only the prompt the harness writes, its module's folders, and the public web through its search and fetch tools; every command it runs is checked, fenced and audited |
126
- | **Memory** | one conversation that fills up | a fresh agent for every step, starting from working notes the agents before it left - dated, attributed, and never allowed to override \*\*\*plain |
127
- | **When it gets stuck** | it keeps trying, or quietly works around the problem | after 20 attempts it stops and tells you what to change in \*\*\*plain - never in the code |
128
- | **A change** | another patch on top | a change to \*\*\*plain: what it touches is rebuilt, everything built before is tested again, and code that disagrees with \*\*\*plain is healed to match |
129
- | **History** | whatever you commit | every build, regeneration and repair is a commit; a build interrupted halfway starts again from the last one |
94
+ | **What you maintain** | the code, patched prompt after prompt | the durable intent |
95
+ | **What gets built, in what order** | whatever the agent decides, as it goes | the code is built from the durable intent step by step, in a fixed order, so no intent is skipped |
96
+ | **Who writes the code** | the agent, and it decides everything else too | the agent - **turri** decides what it builds, the agent only how, line by line |
97
+ | **How it works** | improvised, differently every time | a developer workflow baked in - build, unit test, review, conformance test, regression test, commit - the same every time |
98
+ | **What counts as done** | the agent says so | every unit of intent is tested and validated by **turri** itself: all its tests pass, or the work goes back |
99
+ | **Tests** | written and changed by the agent that writes the code | written from the durable intent, apart from the code; the agent writing the code cannot change them |
100
+ | **When it gets stuck** | it keeps going, or quietly works around the problem | it stops and tells you which intent to clarify |
130
101
 
131
102
  ## How it works
132
103
 
133
- <p align="center"><img src="docs/images/how-turri-works.svg" width="900" alt="How turri works: you describe changes to turri, and turri asks and reports back. turri writes ***plain and reads it; you review it with turri in a review loop. turri regenerates the code from ***plain and tests it against ***plain - an endless loop."></p>
104
+ **turri** captures the durable intent in [\*\*\*plain](https://plainlang.org/), a language for saying what software should do. \*\*\*plain breaks the intent down into functionalities - small units, each a single thing the software does - and **turri** regenerates the code from them piece by piece.
134
105
 
135
- 1. **Define.** Write \*\*\*plain with **turri**: it interviews you one question at a time and
136
- writes the `.plain` files, held to the \*\*\*plain authoring rules and reviewed by independent
137
- judges.
138
- 2. **Generate.** **turri** builds the code one functionality at a time, each on top of the ones
139
- before it, into `plain_modules/` - and builds each answer in the background while the interview
140
- goes on.
141
- 3. **Validate.** The harness runs the unit tests, then conformance tests written from \*\*\*plain,
142
- then everything built so far, and moves on only when all of it passes.
143
- 4. **Regenerate.** To change the system, change its definition. The functionalities whose \*\*\*plain
144
- changed are rebuilt, and everything built before is tested again.
106
+ 1. **Define.** Write \*\*\*plain with **turri**
107
+ 2. **Review and refine.** You review \*\*\*plain and change it with **turri** until it says what you mean.
108
+ 3. **Regenerate.** Agents write the code; **turri** decides what they write and when, step by step, the same way every time.
109
+ 4. **Validate.** Agents write conformance tests from \*\*\*plain; **turri** runs them, and keeps the code only when it does what \*\*\*plain says.
145
110
 
146
- A bug is fixed in \*\*\*plain; a new behaviour goes into \*\*\*plain; and the next regeneration carries
147
- it. When a build is done, ask to try it: **turri** puts what is built in `dist/<module>` and
148
- starts it on your machine - an app, and it tells you where to open your browser.
149
-
150
- \*\*\*plain looks like this.
151
-
152
- ```plain
153
- ***definitions***
154
-
155
- - :User: is a person with an account: an email address and a password.
156
-
157
- ***implementation reqs***
158
-
159
- - :Implementation: is written in Python 3.12 with FastAPI.
160
-
161
- ***functional specs***
162
-
163
- - A new :User: can register with an email address and a password.
164
- - Registering with an email address already in use fails with status 400.
165
-
166
- - A registered :User: can sign in and receives a bearer token.
167
- ```
168
-
169
- Each item under `***functional specs***` is one functionality, built on top of the ones before it.
170
-
171
- **turri** runs as an extension to [pi](https://github.com/earendil-works/pi), so you work with it
172
- in a conversation, and as a command line for unattended runs.
111
+ These are not phases, one after the other: you don't spend hours writing \*\*\*plain and then hours waiting for the code. You go round the loop in small steps, in conversation with **turri** - while you refine the next functionality, the one before it is already being regenerated and validated. A bug is fixed in \*\*\*plain; a new behaviour goes into \*\*\*plain; and the next regeneration carries it. Ask to try it at any time: **turri** puts what is built in `dist` and starts it on your machine - an app, and it tells you where to open your browser.
173
112
 
174
113
  ## The name
175
114
 
176
- **turri** is short for [*Turritopsis dohrnii*](https://en.wikipedia.org/wiki/Turritopsis_dohrnii), the immortal
177
- jellyfish, which, when injured or old, turns back into its young self and regenerates - the same jellyfish, from the
178
- same genes, again and again.
115
+ **turri** is short for [*Turritopsis dohrnii*](https://en.wikipedia.org/wiki/Turritopsis_dohrnii), the immortal jellyfish, which, when injured or old, turns back into its young self and regenerates - the same jellyfish, from the same genes, again and again.
179
116
 
180
117
  That is what regenerative software asks of software, and what **turri** does:
181
118
 
@@ -186,23 +123,11 @@ That is what regenerative software asks of software, and what **turri** does:
186
123
  | Every cell can become another, and it is still the same jellyfish. | Every line of code can be replaced, and it is still the same software - because what it is never lived in the code. |
187
124
  | It can do it again and again, for as long as it lives. | The code can be regenerated whenever \*\*\*plain changes or a model gets better, for as long as \*\*\*plain is kept. |
188
125
 
189
- So the tools speak its language: **`regenerate`** regenerates the code from \*\*\*plain as it is now - or the functionalities
190
- you name, though nothing changed, or all of it from scratch - **`drift`** says how far the code has moved from it, and
191
- **`lineage`** shows every generation of a module and what each was regenerated from.
126
+ So the tools speak its language: **`regenerate`** regenerates the code from \*\*\*plain as it is now - or the functionalities you name, though nothing changed, or all of it from scratch - **`drift`** says how far the code has moved from it, and **`lineage`** shows every generation of a module and what each was regenerated from.
192
127
 
193
128
  ## Models
194
129
 
195
- `init-config`'s models are only a starting point. **turri** is built on [pi](https://github.com/earendil-works/pi),
196
- so any model pi supports works - Anthropic, OpenAI, Google, Amazon Bedrock, OpenRouter, a local one. A model is reached
197
- as pi reaches it - `/login`, in `turri` as in `pi`, the provider's API key in the environment (`ANTHROPIC_API_KEY`,
198
- `OPENAI_API_KEY`, `GEMINI_API_KEY`, ...), or a cloud account - and named as pi names it, `provider/model-id`, with
199
- `:high`, `:low` and so on for how hard it thinks. It uses three: the **harness** model you talk
200
- to, which writes \*\*\*plain and plans the work - worth a capable one - and the **coding** and
201
- **judge** models its agents build and judge with, which can be smaller and cheaper, such as GPT-6
202
- Luna or Gemini 3.1 Flash Lite. `turri --harness-model` and `--coding-model` choose them for a
203
- session, and pi's `/model` switches the one you talk to as you go; to keep them for the project,
204
- set them with `/turri-config harness-model`, `/turri-config coding-model` and so on - each role's too, as
205
- `models.<role>` - or write them in its `config.turri.yaml`:
130
+ `init-config`'s models are only a starting point. **turri** is built on [pi](https://github.com/earendil-works/pi), so any model pi supports works - Anthropic, OpenAI, Google, Amazon Bedrock, OpenRouter, a local one. A model is reached as pi reaches it - `/login`, in `turri` as in `pi`, the provider's API key in the environment (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, ...), or a cloud account - and named as pi names it, `provider/model-id`, with `:high`, `:low` and so on for how hard it thinks. It uses three: the **harness** model you talk to, which writes \*\*\*plain and plans the work - worth a capable one - and the **coding** and **judge** models its agents build and judge with, which can be smaller and cheaper, such as GPT-6 Luna or Gemini 3.1 Flash Lite. `turri --harness-model` and `--coding-model` choose them for a session, and pi's `/model` switches the one you talk to as you go; to keep them for the project, set them with `/turri-config harness-model`, `/turri-config coding-model` and so on - each role's too, as `models.<role>` - or write them in its `config.turri.yaml`:
206
131
 
207
132
  ```yaml
208
133
  harness-model: anthropic/claude-opus-5-5 # the model you talk to: a capable one
@@ -210,8 +135,7 @@ coding-model: openai/gpt-6-luna # writes the code and the tests: a s
210
135
  judge-model: google/gemini-3.1-flash-lite # judges the conformance runs
211
136
  ```
212
137
 
213
- One left out is the one before it: judge from coding, coding from harness. Every way to set them:
214
- [models](docs/config.md#models).
138
+ One left out is the one before it: judge from coding, coding from harness. Every way to set them: [models](docs/config.md#models).
215
139
 
216
140
  ## Use
217
141
 
@@ -226,24 +150,15 @@ Then talk to it:
226
150
 
227
151
  > Let's start a new project: a small API where people can register and sign in.
228
152
 
229
- It runs the interview skill, asks you about the problem, the stack and the product, writes
230
- \*\*\*plain, and builds each functionality as it is written. While it works:
153
+ It runs the interview skill, asks you about the problem, the stack and the product, writes \*\*\*plain, and builds each functionality as it is written. While it works:
231
154
 
232
- - the **panel** above the input shows every build - its stage, what its agents are doing, its
233
- model and cost - and the queue behind it;
234
- - ask to try it at any time - "let me try it" - and **`release`** puts what is built so far in
235
- `dist/<module>` and **`activate`** starts it, installing what it needs - nothing to approve;
155
+ - the **panel** above the input shows every build - its stage, what its agents are doing, its model and cost - and the queue behind it;
156
+ - ask to try it at any time - "let me try it" - and **`release`** puts what is built so far in `dist/<module>` and **`activate`** starts it, installing what it needs - nothing to approve;
236
157
  - the **side panel** (`ctrl+h`) takes the screen and opens on **regen** - \*\*\*plain, every item marked planned, working, regenerated, validating, conform or needs you - and `p` turns it to the **pulses** (`/pulses`) - every pulse, running, queued and finished, and what each regenerates; what its agents did is in each pulse's log in `.turri/jobs/`;
237
- - **`/halt`** halts a pulse, **`/lineage`** shows every generation of a
238
- module, and the **`drift`** tool says what is left to regenerate;
239
- - **`/btw <question>`** asks turri something on the side - answered at once, even in the middle of a skill's interview
240
- (typed as the answer, under "Something else…"), and left out of the conversation;
241
- - **`/turri-config`** changes any setting of the project's `config.turri.yaml` - the models, review, conformance tests,
242
- how many pulses at once - and says when it takes effect: now, at your next message, or at the next pulse. No
243
- restart: `/turri-config review false`, or `/turri-config` alone to pick from the list;
244
- - **`/stack`** chooses the stack to build with, in a project whose backend and frontend each have their own testing
245
- scripts in `config.turri.<stack>.yaml` - `/stack backend`, `/stack none` - for the session (`--stack <name>` on the
246
- command line).
158
+ - **`/halt`** halts a pulse, **`/lineage`** shows every generation of a module, and the **`drift`** tool says what is left to regenerate;
159
+ - **`/btw <question>`** asks turri something on the side - answered at once, even in the middle of a skill's interview (typed as the answer, under "Something else…"), and left out of the conversation;
160
+ - **`/turri-config`** changes any setting of the project's `config.turri.yaml` - the models, review, conformance tests, how many pulses at once - and says when it takes effect: now, at your next message, or at the next pulse. No restart: `/turri-config review false`, or `/turri-config` alone to pick from the list;
161
+ - **`/stack`** chooses the stack to build with, in a project whose backend and frontend each have their own testing scripts in `config.turri.<stack>.yaml` - `/stack backend`, `/stack none` - for the session (`--stack <name>` on the command line).
247
162
 
248
163
  Other things to ask for:
249
164
 
@@ -253,9 +168,7 @@ Other things to ask for:
253
168
  >
254
169
  > Regenerate changes to \*\*\*plain with a faster model.
255
170
 
256
- The last one holds for the rest of the session; the model can be chosen separately for changes to
257
- \*\*\*plain and for functionalities, and a name that fits more than one model is asked about rather
258
- than guessed.
171
+ The last one holds for the rest of the session; the model can be chosen separately for changes to \*\*\*plain and for functionalities, and a name that fits more than one model is asked about rather than guessed.
259
172
 
260
173
  Without a conversation, the same work is on the command line:
261
174
 
@@ -266,8 +179,7 @@ turri regenerate app.plain # regenerate the code from ***plain: planned int
266
179
  turri regenerate app.plain 3 # regenerate functionality 3, changed or not
267
180
  ```
268
181
 
269
- More: [using **turri**](docs/using.md); to render \*\*\*plain overnight, see
270
- [running unattended](docs/headless.md).
182
+ More: [using **turri**](docs/using.md); to render \*\*\*plain overnight, see [running unattended](docs/headless.md).
271
183
 
272
184
  ## Documentation
273
185
 
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file