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

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 (100) hide show
  1. package/.pi/themes/turri-dark.json +67 -66
  2. package/.pi/themes/turri-light.json +71 -73
  3. package/README.md +39 -127
  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/dark-12.png +0 -0
  17. package/assets/jellyfish/dark-13.png +0 -0
  18. package/assets/jellyfish/dark-14.png +0 -0
  19. package/assets/jellyfish/light-00.png +0 -0
  20. package/assets/jellyfish/light-01.png +0 -0
  21. package/assets/jellyfish/light-02.png +0 -0
  22. package/assets/jellyfish/light-03.png +0 -0
  23. package/assets/jellyfish/light-04.png +0 -0
  24. package/assets/jellyfish/light-05.png +0 -0
  25. package/assets/jellyfish/light-06.png +0 -0
  26. package/assets/jellyfish/light-07.png +0 -0
  27. package/assets/jellyfish/light-08.png +0 -0
  28. package/assets/jellyfish/light-09.png +0 -0
  29. package/assets/jellyfish/light-10.png +0 -0
  30. package/assets/jellyfish/light-11.png +0 -0
  31. package/assets/jellyfish/light-12.png +0 -0
  32. package/assets/jellyfish/light-13.png +0 -0
  33. package/assets/jellyfish/light-14.png +0 -0
  34. package/dist/ask.js +34 -15
  35. package/dist/brand.js +7 -7
  36. package/dist/cli-options.js +12 -6
  37. package/dist/config-edit.js +1 -0
  38. package/dist/config.js +5 -2
  39. package/dist/cultivate-cli.js +16 -23
  40. package/dist/extension.js +41 -29
  41. package/dist/init-config.js +5 -0
  42. package/dist/loop-cli.js +19 -7
  43. package/dist/loop-tools.js +11 -5
  44. package/dist/module-report.js +5 -4
  45. package/dist/pi.js +76 -19
  46. package/dist/question-dialog.js +1 -0
  47. package/dist/regenerate/activity.js +21 -0
  48. package/dist/regenerate/list-arguments.js +121 -0
  49. package/dist/regenerate/loop.js +21 -8
  50. package/dist/regenerate/plain-palette.js +51 -36
  51. package/dist/regenerate/regenerate.js +4 -2
  52. package/dist/regenerate/self-check.js +13 -6
  53. package/dist/regenerate/side-panel.js +1 -1
  54. package/dist/regenerate/spec-map-view.js +9 -5
  55. package/dist/regenerate/test-scripts.js +54 -10
  56. package/dist/regenerate/unit-review.js +1 -1
  57. package/dist/regenerate-cli.js +11 -5
  58. package/dist/release-cli.js +3 -8
  59. package/dist/review/live.js +2 -1
  60. package/dist/run-report.js +39 -1
  61. package/dist/validate-cli.js +3 -8
  62. package/docs/README.md +5 -12
  63. package/docs/authoring-plain.md +37 -119
  64. package/docs/config.md +53 -178
  65. package/docs/deploy.md +21 -80
  66. package/docs/development.md +13 -41
  67. package/docs/headless.md +45 -121
  68. package/docs/images/how-turri-works.svg +29 -31
  69. package/docs/installation.md +13 -40
  70. package/docs/parser.md +15 -43
  71. package/docs/regenerating.md +229 -938
  72. package/docs/sandbox.md +38 -152
  73. package/docs/skills-and-gates.md +50 -171
  74. package/docs/theming.md +45 -46
  75. package/docs/using.md +69 -345
  76. package/genome/rules/bullet-continuation.md +5 -13
  77. package/genome/rules/concise-specs-examples.md +2 -4
  78. package/genome/rules/concise-specs-integration-examples.md +2 -6
  79. package/genome/rules/concise-specs.md +1 -2
  80. package/genome/rules/func-specs.md +1 -0
  81. package/genome/rules/integration-embedded-testing.md +1 -4
  82. package/genome/rules/integrations.md +1 -2
  83. package/genome/rules/project-model.md +14 -35
  84. package/genome/rules/stdlib.md +14 -49
  85. package/genome/rules/turri-regeneration.md +48 -0
  86. package/genome/skills/add-implementation-requirement/SKILL.md +1 -2
  87. package/genome/skills/analyze-if-func-spec-too-complex/SKILL.md +3 -8
  88. package/genome/skills/brood/SKILL.md +37 -127
  89. package/genome/skills/brood/references/intent.md +4 -12
  90. package/genome/skills/brood/references/product.md +24 -76
  91. package/genome/skills/brood/references/stack.md +7 -29
  92. package/genome/skills/brood/references/testing.md +11 -42
  93. package/genome/skills/bud/SKILL.md +32 -109
  94. package/genome/skills/bud/references/intent.md +4 -11
  95. package/genome/skills/implement-conformance-testing-script/SKILL.md +3 -6
  96. package/genome/skills/implement-unit-testing-script/SKILL.md +1 -2
  97. package/genome/skills/mature/SKILL.md +21 -69
  98. package/genome/skills/refactor-module/SKILL.md +24 -2
  99. package/genome/skills/spawn/SKILL.md +28 -113
  100. package/package.json +1 -1
@@ -1,12 +1,8 @@
1
1
  # Installation
2
2
 
3
- **turri** runs wherever pi runs - macOS, Linux, WSL - with git, bash and Node 22.19 or newer (a Linux
4
- distribution's own `nodejs` package is often older: take it from nodejs.org, nvm or NodeSource). Native Windows is
5
- best effort: it needs bash on the PATH (Git for Windows' Git Bash), and has no OS sandbox under the agents' commands.
3
+ **turri** runs wherever pi runs - macOS, Linux, WSL - with git, bash and Node 22.19 or newer (a Linux distribution's own `nodejs` package is often older: take it from nodejs.org, nvm or NodeSource). Native Windows is best effort: it needs bash on the PATH (Git for Windows' Git Bash), and has no OS sandbox under the agents' commands.
6
4
 
7
- The agents' commands run on this machine, with its toolchains - see [the sandbox](sandbox.md). Each is checked before
8
- it runs and audited after, on every platform; under them an OS sandbox fences it where the OS has one: Seatbelt on
9
- macOS, always there, and bubblewrap on Linux and WSL 2 - `apt install bubblewrap`, or your distribution's package.
5
+ The agents' commands run on this machine, with its toolchains - see [the sandbox](sandbox.md). Each is checked before it runs and audited after, on every platform; under them an OS sandbox fences it where the OS has one: Seatbelt on macOS, always there, and bubblewrap on Linux and WSL 2 - `apt install bubblewrap`, or your distribution's package.
10
6
 
11
7
  ```bash
12
8
  npm install -g @turri-dev/cli # puts `turri` on your PATH
@@ -21,9 +17,7 @@ turri init-config # a config.turri.yaml with the model you talk to and the one
21
17
  turri # pi, with turri's tools, skills and themes loaded
22
18
  ```
23
19
 
24
- The package is `@turri-dev/cli` - npm keeps the name `turri` back, as too like another
25
- package's - and the command it puts on your PATH is `turri`. `npm install -g @turri-dev/cli@next` gets the latest
26
- prerelease instead, built from the last commit on `main`.
20
+ The package is `@turri-dev/cli` - npm keeps the name `turri` back, as too like another package's - and the command it puts on your PATH is `turri`. `npm install -g @turri-dev/cli@next` gets the latest prerelease instead, built from the last commit on `main`.
27
21
 
28
22
  ## From a clone
29
23
 
@@ -35,22 +29,13 @@ npm install
35
29
  npm link # puts `turri` on your PATH, pointing at this clone
36
30
  ```
37
31
 
38
- A clone runs its TypeScript sources directly - Node strips the types - so edits take effect immediately. The package
39
- on npm runs JavaScript compiled from them instead (`npm run build`, into `dist/`, run by `npm pack` and `npm publish`
40
- before they pack), as Node runs no `.ts` file inside a `node_modules`. `bin/turri.mjs` runs `src/` where there is one,
41
- and `dist/` otherwise.
32
+ A clone runs its TypeScript sources directly - Node strips the types - so edits take effect immediately. The package on npm runs JavaScript compiled from them instead (`npm run build`, into `dist/`, run by `npm pack` and `npm publish` before they pack), as Node runs no `.ts` file inside a `node_modules`. `bin/turri.mjs` runs `src/` where there is one, and `dist/` otherwise.
42
33
 
43
- To update, `git pull` and `npm install` - the second picks up a dependency that changed, pi's say. `npm link` needs
44
- running only once. A **turri** already running keeps the code it started with: start it again to run what you pulled.
34
+ To update, `git pull` and `npm install` - the second picks up a dependency that changed, pi's say. `npm link` needs running only once. A **turri** already running keeps the code it started with: start it again to run what you pulled.
45
35
 
46
36
  ## In Docker
47
37
 
48
- `docker/Dockerfile` builds an image with Node, git, bash, bubblewrap and **turri** linked; the agents' commands and the
49
- testing scripts run inside it, so add the toolchains your projects need first. It runs **turri** as the user who owns
50
- the project folder mounted at `/work`, never as root - bubblewrap as root in a container lacks the capability to make
51
- its namespaces - and with seccomp and AppArmor unconfined the OS sandbox starts. `systempaths=unconfined` lets it mount
52
- a `/proc` of its own; without it, it binds the container's. The build, the run, Windows and the keys:
53
- [turri in Docker](../docker/README.md).
38
+ `docker/Dockerfile` builds an image with Node, git, bash, bubblewrap and **turri** linked; the agents' commands and the testing scripts run inside it, so add the toolchains your projects need first. It runs **turri** as the user who owns the project folder mounted at `/work`, never as root - bubblewrap as root in a container lacks the capability to make its namespaces - and with seccomp and AppArmor unconfined the OS sandbox starts. `systempaths=unconfined` lets it mount a `/proc` of its own; without it, it binds the container's. The build, the run, Windows and the keys: [turri in Docker](../docker/README.md).
54
39
 
55
40
  ## What `turri doctor` checks
56
41
 
@@ -73,23 +58,17 @@ In a project - a folder with `config.turri.yaml` (or the old `config.yaml`) or `
73
58
  | the testing scripts | what in them this machine does not have: a program named by its whole path that is not here (a macOS-only `/usr/libexec/java_home` on Linux), a toolchain they run that is not on the PATH |
74
59
  | the models | each model `config.turri.yaml` names - `harness-model`, `coding-model`, `judge-model`, every role under `models:` - sent one short request through pi, with the credentials turri's agents will use, for any provider pi supports. One that answers is ready; for one that does not, it says what the provider said and what to do: the credentials pi reads for that provider (`AWS_PROFILE` and `AWS_REGION` for Amazon Bedrock, `OPENAI_API_KEY`, `/login`, ...), model access in the Bedrock console, the closest model ids pi knows for one it does not. `--harness-model`, `--coding-model` (`--model`) and `--judge-model` name models as the config's keys, as `turri regenerate` reads them - checked in a project or not. `--no-models` skips it |
75
60
 
76
- Removing that file is the one thing `doctor` changes, and it asks first; `turri doctor --yes` says yes. Run without a
77
- terminal - piped, or in CI - it asks nothing and changes nothing. Run it again whenever something breaks;
78
- `turri doctor --no-models` leaves out the models' requests.
61
+ Removing that file is the one thing `doctor` changes, and it asks first; `turri doctor --yes` says yes. Run without a terminal - piped, or in CI - it asks nothing and changes nothing. Run it again whenever something breaks; `turri doctor --no-models` leaves out the models' requests.
79
62
 
80
63
  The chat is told every turn which wall is up and what the project's modules need of this machine that it lacks. What they need is worked out from every spec of the project - seconds, on a project of long requires chains - so it is worked out once the chat is up and again after a turn in which a spec changed, never while your message waits: a turn is told what was known last.
81
64
 
82
65
  ## turri and `pi`
83
66
 
84
- `turri` runs pi from this project's `node_modules`, with turri loaded, so no global pi install is needed. A plain
85
- `pi` is left as it is: starting pi does not start turri, and turri puts nothing into pi's own folders.
67
+ `turri` runs pi from this project's `node_modules`, with turri loaded, so no global pi install is needed. A plain `pi` is left as it is: starting pi does not start turri, and turri puts nothing into pi's own folders.
86
68
 
87
- An older `turri setup` could load turri into every `pi`, with a one-line file in `~/.pi/agent/extensions/` pointing at
88
- this clone. `turri doctor` says when it is there, and offers to remove it. Until it is gone, `turri`
89
- leaves out its own `-e`: pi treats a tool registered twice as an error.
69
+ An older `turri setup` could load turri into every `pi`, with a one-line file in `~/.pi/agent/extensions/` pointing at this clone. `turri doctor` says when it is there, and offers to remove it. Until it is gone, `turri` leaves out its own `-e`: pi treats a tool registered twice as an error.
90
70
 
91
- `turri` starts in the `turri-dark` theme. A plain `pi` keeps its own theme; to give it
92
- `turri-dark` too, in `~/.pi/agent/settings.json`:
71
+ `turri` starts in the `turri-dark` theme. A plain `pi` keeps its own theme; to give it `turri-dark` too, in `~/.pi/agent/settings.json`:
93
72
 
94
73
  ```json
95
74
  { "theme": "turri-dark" }
@@ -97,24 +76,18 @@ leaves out its own `-e`: pi treats a tool registered twice as an error.
97
76
 
98
77
  ### Project trust
99
78
 
100
- pi will not auto-discover a project-local extension until you trust the project, and `-p` has no
101
- way to ask - so `npm run chat` and `npm run ask` pass `-e` explicitly. Once you have run `pi`
102
- interactively in this directory and accepted the trust prompt, plain `pi` picks the extension up
103
- on its own. A `defaultProjectTrust` key in `.pi/settings.json` does *not* work - a project cannot
104
- vouch for itself; that setting only counts in `~/.pi/agent/settings.json`.
79
+ pi will not auto-discover a project-local extension until you trust the project, and `-p` has no way to ask - so `npm run chat` and `npm run ask` pass `-e` explicitly. Once you have run `pi` interactively in this directory and accepted the trust prompt, plain `pi` picks the extension up on its own. A `defaultProjectTrust` key in `.pi/settings.json` does *not* work - a project cannot vouch for itself; that setting only counts in `~/.pi/agent/settings.json`.
105
80
 
106
81
  ## Environment
107
82
 
108
- Models and credentials come from your pi configuration (`~/.pi/agent`) or provider environment
109
- variables - the same resolution `pi` itself uses. Put the rest in your shell profile:
83
+ Models and credentials come from your pi configuration (`~/.pi/agent`) or provider environment variables - the same resolution `pi` itself uses. Put the rest in your shell profile:
110
84
 
111
85
  ```bash
112
86
  export PLAIN_TEMPLATE_DIRS=~/path/to/standard_template_library # shared templates
113
87
  export GEMINI_API_KEY=... # and leave GOOGLE_API_KEY unset
114
88
  ```
115
89
 
116
- For Gemini, `GEMINI_API_KEY` is what makes pi *offer* the google provider, but when
117
- `GOOGLE_API_KEY` is also set pi uses that one for the calls and says so.
90
+ For Gemini, `GEMINI_API_KEY` is what makes pi *offer* the google provider, but when `GOOGLE_API_KEY` is also set pi uses that one for the calls and says so.
118
91
 
119
92
  | variable | |
120
93
  | --- | --- |
package/docs/parser.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # The \*\*\*plain parser
2
2
 
3
- `src/plain/` is a TypeScript port of the reference \*\*\*plain parser - `plain_file.py`,
4
- `plain_spec.py`, `concept_utils.py`, and the `file_utils.py` helpers they depend on.
3
+ `src/plain/` is a TypeScript port of the reference \*\*\*plain parser - `plain_file.py`, `plain_spec.py`, `concept_utils.py`, and the `file_utils.py` helpers they depend on.
5
4
 
6
5
  | module | ports |
7
6
  |---|---|
@@ -21,9 +20,7 @@ turri validate . # every .plain file in a directory
21
20
  turri validate <file.plain> --json
22
21
  ```
23
22
 
24
- It uses this repo's own parser, so it needs no external tool, no API key and no credits: it parses
25
- the file, resolves its imports and required modules, and reports every syntax, concept and
26
- structure error with the line it is on.
23
+ It uses this repo's own parser, so it needs no external tool, no API key and no credits: it parses the file, resolves its imports and required modules, and reports every syntax, concept and structure error with the line it is on.
27
24
 
28
25
  ```
29
26
  PASS d365_export.plain 6 functionalities (1, 2, 3, 4, 5, 6), requires d365_restore_api
@@ -37,14 +34,12 @@ The exit code is 0 only when every file passed. In a conversation the same check
37
34
 
38
35
  ## Two rules of inheritance
39
36
 
40
- - A module that **`requires`** another inherits its functional specs, transitively: it is built on
41
- top of that module's code.
37
+ - A module that **`requires`** another inherits its functional specs, transitively: it is built on top of that module's code.
42
38
  - A module that **`import`s** another inherits its definitions, implementation reqs and test reqs.
43
39
 
44
40
  ## The functional-spec iterator
45
41
 
46
- `getFrids` walks functionalities depth-first through nested sections; `getSpecificationsForFrid`
47
- builds what a single functionality is rendered with. `iterateFunctionalSpecs` pairs them:
42
+ `getFrids` walks functionalities depth-first through nested sections; `getSpecificationsForFrid` builds what a single functionality is rendered with. `iterateFunctionalSpecs` pairs them:
48
43
 
49
44
  ```ts
50
45
  import { plainFileParser, iterateFunctionalSpecs } from "./src/plain/index.ts";
@@ -60,49 +55,26 @@ for (const { frid, specifications, codeVariables } of iterateFunctionalSpecs(tre
60
55
 
61
56
  ## Parsing once
62
57
 
63
- A module's parse reads its imports and the whole of its `requires` chain, so a long chain asks for the same
64
- files over and over: bringing an 18-module chain up to its spec parsed for minutes. Two caches keep it to once.
65
- Inside `withParseCache`, one question about the specs, each file is parsed once. Between calls, a parse is kept
66
- with a fingerprint of every file directly in its template folders and the current one - name, size,
67
- modification time, and a `.plain` file's text - and handed out again, as a copy, while the fingerprint is the
68
- same; a spec that does not parse is kept as that too. What a parse returns is unchanged: the cache only decides
69
- whether to parse again.
58
+ A module's parse reads its imports and the whole of its `requires` chain, so a long chain asks for the same files over and over: bringing an 18-module chain up to its spec parsed for minutes. Two caches keep it to once. Inside `withParseCache`, one question about the specs, each file is parsed once. Between calls, a parse is kept with a fingerprint of every file directly in its template folders and the current one - name, size, modification time, and a `.plain` file's text - and handed out again, as a copy, while the fingerprint is the same; a spec that does not parse is kept as that too. What a parse returns is unchanged: the cache only decides whether to parse again.
70
59
 
71
60
  ## Fidelity
72
61
 
73
- The port is checked against the Python implementation directly, not only against the ported
74
- assertions. Both parsers are run over a corpus and their module name, marshalled tree, required
75
- modules, functionality ids and per-functionality specifications compared:
62
+ The port is checked against the Python implementation directly, not only against the ported assertions. Both parsers are run over a corpus and their module name, marshalled tree, required modules, functionality ids and per-functionality specifications compared:
76
63
 
77
64
  | corpus | files | identical | differences |
78
65
  |---|---|---|---|
79
66
  | `tests/data/` fixtures | 84 | 80 | 4 error strings (below) |
80
67
  | `hycu-dynamics-365-modules` | 47 | 47 | none |
81
68
 
82
- The 4 differences are all the same thing: template partials (`implement.plain`,
83
- `implement_2.plain`, `header.plain`, `pr_implement.plain`) are meant to be included with
84
- arguments, not parsed alone. Both implementations reject them for the same reason - an undefined
85
- Liquid variable - but the message text comes from the template engine, and liquidjs phrases it
86
- differently from liquid2.
87
-
88
- Real specs exposed three places where mdast and mistletoe disagree, each covered by
89
- `tests/plain/renderer.test.ts`:
90
-
91
- - **Inline decoding.** mdast resolves `\"` to `"` and forgets whether emphasis was written with `_`
92
- or `*`; mistletoe round-trips the source. Inline leaf nodes are pinned back to their original
93
- source slice at parse time.
94
- - **List geometry.** mistletoe indents an item's continuation lines by its `prepend`, measured in
95
- coordinates with the enclosing item's indentation stripped - not by the column gap between parent
96
- and child. An acceptance test rendered detached from its functionality keeps 6 and 10 spaces where
97
- the naive reading gives 4 and 8.
98
- - **Lazy continuation lines.** A paragraph's continuation lines carry leading whitespace that is not
99
- part of the text; keeping it in the raw slice indents the line twice.
69
+ The 4 differences are all the same thing: template partials (`implement.plain`, `implement_2.plain`, `header.plain`, `pr_implement.plain`) are meant to be included with arguments, not parsed alone. Both implementations reject them for the same reason - an undefined Liquid variable - but the message text comes from the template engine, and liquidjs phrases it differently from liquid2.
70
+
71
+ Real specs exposed three places where mdast and mistletoe disagree, each covered by `tests/plain/renderer.test.ts`:
72
+
73
+ - **Inline decoding.** mdast resolves `\"` to `"` and forgets whether emphasis was written with `_` or `*`; mistletoe round-trips the source. Inline leaf nodes are pinned back to their original source slice at parse time.
74
+ - **List geometry.** mistletoe indents an item's continuation lines by its `prepend`, measured in coordinates with the enclosing item's indentation stripped - not by the column gap between parent and child. An acceptance test rendered detached from its functionality keeps 6 and 10 spaces where the naive reading gives 4 and 8.
75
+ - **Lazy continuation lines.** A paragraph's continuation lines carry leading whitespace that is not part of the text; keeping it in the raw slice indents the line twice.
100
76
 
101
77
  Two deliberate differences from the Python source:
102
78
 
103
- - The `test_plainfile.py` tests drive the acceptance-test helpers with `MagicMock` tokens and patch
104
- the inner helper to count calls. ESM has no equivalent, so those tests build real ASTs from
105
- markdown and assert the same observable outcome.
106
- - `networkx`'s `topological_sort` is reimplemented rather than replaced with a generic one: it
107
- flattens `topological_generations`, so the ordering of independent concepts follows graph
108
- insertion order, and the Python tests assert that exact sequence.
79
+ - The `test_plainfile.py` tests drive the acceptance-test helpers with `MagicMock` tokens and patch the inner helper to count calls. ESM has no equivalent, so those tests build real ASTs from markdown and assert the same observable outcome.
80
+ - `networkx`'s `topological_sort` is reimplemented rather than replaced with a generic one: it flattens `topological_generations`, so the ordering of independent concepts follows graph insertion order, and the Python tests assert that exact sequence.