@turri-dev/cli 0.1.11-next.3495500 → 0.1.11-next.450c74d

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 CHANGED
@@ -179,7 +179,7 @@ turri regenerate app.plain # regenerate the code from ***plain: planned int
179
179
  turri regenerate app.plain 3 # regenerate functionality 3, changed or not
180
180
  ```
181
181
 
182
- More: [using **turri**](docs/using.md); to regenerate \*\*\*plain overnight, see [running unattended](docs/headless.md).
182
+ More: [using **turri**](docs/using.md); to render \*\*\*plain overnight, see [running unattended](docs/headless.md).
183
183
 
184
184
  ## Documentation
185
185
 
@@ -192,7 +192,7 @@ Start at the [documentation index](docs/README.md), or go straight to a page:
192
192
  | [Using **turri**](docs/using.md) | the conversation, skills, tools, pulses and regen, choosing models, the command line |
193
193
  | [The project config](docs/config.md) | `config.turri.yaml` and each stack's `config.turri.<stack>.yaml`: every key, models and their inheritance, conformance, the testing scripts, stacks and choosing one, the old `config.yaml` |
194
194
  | [Deploy](docs/deploy.md) | trying what is built: the last commit in `dist/<module>`, started on your machine, nothing installed without asking |
195
- | [Running unattended](docs/headless.md) | regenerating \*\*\*plain overnight or in CI: the command, keeping it running, the results, resuming, rebuilding one functionality |
195
+ | [Running unattended](docs/headless.md) | rendering \*\*\*plain overnight or in CI: the command, keeping it running, the results, resuming, rebuilding one functionality |
196
196
  | [Authoring \*\*\*plain](docs/authoring-plain.md) | what \*\*\*plain is made of, the authoring rules, the skills that write and fix it, checking it |
197
197
  | [Regenerating](docs/regenerating.md) | what each build does and in which order: functionalities, modules, regeneration, changes to \*\*\*plain, conformance and acceptance tests, working notes, what the code is built from |
198
198
  | [The sandbox](docs/sandbox.md) | what agents can reach, the walls every command passes, time limits, the web tools |
package/dist/cli.js CHANGED
@@ -78,7 +78,7 @@ const COMMANDS = {
78
78
  glimpse: { module: "./regenerate-cli.ts", blurb: "plan the work and print the first job's prompt, starting nothing", args: ["--dry-run"] },
79
79
  drift: { module: "./drift-cli.ts", blurb: "what is left to regenerate: how far the code has drifted from its spec" },
80
80
  conform: { module: "./conform-cli.ts", blurb: "write and run a module's conformance tests" },
81
- "change-plain": { module: "./change-plain-cli.ts", blurb: "apply a change to ***plain, given as a git diff, and regenerate it" },
81
+ "spec-diff": { module: "./spec-diff-cli.ts", blurb: "apply a change to the specs, given as a git diff, and regenerate it" },
82
82
  validate: { module: "./validate-cli.ts", blurb: "validate a ***plain spec, regenerating nothing" },
83
83
  lineage: { module: "./lineage-cli.ts", blurb: "a module's lineage: what was regenerated into it, and when" },
84
84
  ledger: { module: "./ledger-cli.ts", blurb: "what turri did here: the last runs and their pulses, or one pulse, from the ledger" },
package/dist/extension.js CHANGED
@@ -669,11 +669,11 @@ function turriExtension(pi, host) {
669
669
  : "It changed no file in the project - whatever it said it wrote is not there. Say so to the user; do not report the work as done.";
670
670
  // A skill that edits the specs with the file tools builds nothing: the change is the conversation's to render.
671
671
  const specsChanged = changes.filter((path) => path.endsWith(".plain"));
672
- const unrendered = specsChanged.length > 0 && !skill.allowedTools.includes("change_plain")
672
+ const unrendered = specsChanged.length > 0 && !skill.allowedTools.includes("write_spec_diff")
673
673
  ? `${specsChanged.join(", ")} changed, and nothing is regenerated from that yet: call regenerate for it, and the code is brought up to the spec.`
674
674
  : "";
675
675
  const gated = skill.steps.some((step) => step.gate !== undefined);
676
- const first = skill.allowedTools.includes("change_plain") ? firstRegeneration(jobs.list(), began) : {};
676
+ const first = skill.allowedTools.includes("write_spec_diff") ? firstRegeneration(jobs.list(), began) : {};
677
677
  const ttfr = first.started === undefined
678
678
  ? ""
679
679
  : `Time to first regeneration: ${formatElapsed(first.started)} - its first pulse started that long after ${skill.name} began` +
@@ -1125,7 +1125,7 @@ export function projectConfigBlock(root) {
1125
1125
  return [
1126
1126
  ...settings(readProjectConfig(dir), withStack(undefined, () => findTestScripts(dir)), dir === root ? `${projectConfigFile(dir)}, for the specs here:` : `${relative(root, dir)}/${projectConfigFile(dir)}, for the specs in ${relative(root, dir)}/ - built in ${relative(root, dir)}/plain_modules:`, where, stacks.length > 0 ? "project of stacks" : "project"),
1127
1127
  ...(stacks.length > 0
1128
- ? ["", `Stacks: ${stacks.join(", ")} - chosen now: ${chosen ?? "none, so the project's file alone"}. Each module is built with the stack of its part, pinned to its pulses whatever is chosen after: a stack named after the module is its own - backend.plain is built with config.turri.backend.yaml - with nothing to choose. For a module whose stack has another name, pass it as stack to regenerate, conform, glimpse and change_plain. Choose one for the whole session with the stack tool only when the user asks.`]
1128
+ ? ["", `Stacks: ${stacks.join(", ")} - chosen now: ${chosen ?? "none, so the project's file alone"}. Each module is built with the stack of its part, pinned to its pulses whatever is chosen after: a stack named after the module is its own - backend.plain is built with config.turri.backend.yaml - with nothing to choose. For a module whose stack has another name, pass it as stack to regenerate, conform, glimpse and write_spec_diff. Choose one for the whole session with the stack tool only when the user asks.`]
1129
1129
  : []),
1130
1130
  // A stack: its file over the project's, for everything built while it is chosen.
1131
1131
  ...stacks.flatMap((stack) => [
@@ -1298,7 +1298,7 @@ function setRenderModelTool(pi, conversation) {
1298
1298
  label: "Engine",
1299
1299
  description: "The engine: which model the agents that regenerate the code run on. With no model, say which it is. With one, choose it " +
1300
1300
  "for the rest of this session: for spec changes " +
1301
- "(render spec diff pulses, and the ones change_plain queues), for functionalities (render, module, " +
1301
+ "(render spec diff pulses, and the ones write_spec_diff queues), for functionalities (render, module, " +
1302
1302
  "regenerate with functionalities named, conformance), or for everything. By default " +
1303
1303
  "each runs on the model the project's config.turri.yaml names, or else the conversation's model. The model may be given as provider/model-id or by name as " +
1304
1304
  "the user said it; a name that fits more than one model, or none with credentials, comes back as a " +
package/dist/genome.js CHANGED
@@ -12,7 +12,7 @@ import { DISMISSED } from "./ask.js";
12
12
  import { createQuestioning, levelOf, questioningQuestion } from "./questioning.js";
13
13
  import { createSpecDiffTools } from "./spec-tools.js";
14
14
  import { createMatureTools, MATURE_TOOLS } from "./mature-tools.js";
15
- const CHANGE_PLAIN = "change_plain";
15
+ const WRITE_SPEC_DIFF = "write_spec_diff";
16
16
  /** The conversation's tools a skill acts on the work loop with - never pi built-ins. */
17
17
  const LOOP_TOOLS = ["regenerate", "drift", "halt", "conform"];
18
18
  /** How much of what the agent said before a question is shown with it: its end, where the brief is. */
@@ -77,14 +77,14 @@ export async function runSkill(opts) {
77
77
  const questions = {
78
78
  refusal: (confirmsPhase) => diffPerAnswer() && diffs?.pace.owed() === true
79
79
  ? "This question was not asked: the last answer is not in the spec yet. Every answer in this phase is a spec " +
80
- "change, built at once - write it with change_plain first, then ask."
80
+ "change, built at once - write it with write_spec_diff first, then ask."
81
81
  : questioning?.refusal(confirmsPhase),
82
82
  answered: (confirmsPhase) => questioning?.answered(confirmsPhase),
83
83
  end: () => questioning?.end() ?? "No questioning level was chosen: ask what the phase needs.",
84
84
  };
85
- // A skill whose unit of work is a spec change gets change_plain: the change is applied
85
+ // A skill whose unit of work is a spec change gets write_spec_diff: the change is applied
86
86
  // and its build queued in one step.
87
- const diffs = opts.renderQueue !== undefined && skill.allowedTools.includes(CHANGE_PLAIN)
87
+ const diffs = opts.renderQueue !== undefined && skill.allowedTools.includes(WRITE_SPEC_DIFF)
88
88
  ? createSpecDiffTools({
89
89
  loop: opts.renderQueue,
90
90
  cwd: opts.cwd,
@@ -125,7 +125,7 @@ export async function runSkill(opts) {
125
125
  customTools.push(...(opts.sharedTools ?? []));
126
126
  const names = customTools.map((tool) => tool.name);
127
127
  // Tools this harness provides are never pi built-ins, even when it did not provide them.
128
- const builtins = skill.allowedTools.filter((t) => !names.includes(t) && t !== CHANGE_PLAIN && !MATURE_TOOLS.includes(t) && !LOOP_TOOLS.includes(t));
128
+ const builtins = skill.allowedTools.filter((t) => !names.includes(t) && t !== WRITE_SPEC_DIFF && !MATURE_TOOLS.includes(t) && !LOOP_TOOLS.includes(t));
129
129
  const executor = await createExecutor({
130
130
  cwd: opts.cwd,
131
131
  customTools,
package/dist/identity.js CHANGED
@@ -27,9 +27,8 @@ export function conversationIdentity(surface) {
27
27
  }
28
28
  const IDENTITY_BEFORE = [
29
29
  "<turri>",
30
- "You are turri - always lowercase - the first coding agent with the power of regenerative software. The software is",
31
- "its ***plain; the code is regenerated from it. You write the ***plain with the person - they say what the software",
32
- "should do, and you write it down as ***plain, shaping it with them - and you regenerate the code from it a",
30
+ "You are turri - always lowercase - a coding agent with the power of regenerative software. The software is its",
31
+ "***plain; the code is regenerated from it. You help the person write ***plain, and you regenerate the code from it a",
33
32
  "change at a time - with agents that write the code and tests, while you decide what runs next and when the work is",
34
33
  "done - record what each piece was regenerated from, and prove it against conformance tests written from the ***plain",
35
34
  "alone. When the code goes bad, you regenerate it from the ***plain. You are named after Turritopsis dohrnii, the",
@@ -38,10 +37,9 @@ const IDENTITY_BEFORE = [
38
37
  "gone bad is regenerated from it, whole, rather than patched. Say it as that likeness, not as a fact about a",
39
38
  "jellyfish.",
40
39
  "",
41
- "Asked who or what you are, say it in those words: you are turri, the first coding agent with the power of",
42
- "regenerative software - you write ***plain with them and regenerate the code from it. Never say they write the",
43
- "***plain and you help: you write it, together. Not an assistant, and not a helper with specifications: ***plain is",
44
- "the language the software is written in, and naming it is the point. Your replies are Markdown, where",
40
+ "Asked who or what you are, say it in those words: you are turri, a coding agent with the power of regenerative",
41
+ "software - you help them write ***plain and regenerate the code from it. Not an assistant, and not a helper with",
42
+ "specifications: ***plain is the language they write, and naming it is the point. Your replies are Markdown, where",
45
43
  "three asterisks start bold italics: write the name escaped, \\*\\*\\*plain, so it shows as ***plain.",
46
44
  "",
47
45
  "Speak as turri, in the first person - I, my pulses, my agents - to the person, in whole sentences. Never speak of",
@@ -55,7 +53,7 @@ const IDENTITY_BEFORE = [
55
53
  " allow-to-stop-jobs in config.turri.yaml are about pulses. \"Job\" in what you read is a pulse; say pulse.",
56
54
  ];
57
55
  const IDENTITY_AFTER = [
58
- "- mutate, in a skill's activity, is change_plain: a spec change written and regenerated in one step.",
56
+ "- mutate, in a skill's activity, is write_spec_diff: a spec change written and regenerated in one step.",
59
57
  "- Regenerate is the word for what you do to the code: never grow, grew or grown - older text, a tool's description",
60
58
  " or a report may still say it, and means regenerate.",
61
59
  ];
@@ -1,7 +1,7 @@
1
1
  import { type DriftReport, type ModuleStatus, type WorkLoop } from "./regenerate/loop.ts";
2
2
  import { type ModuleState } from "./run-report.ts";
3
3
  /**
4
- * What every command that builds - `turri regenerate`, `conform`, `change-plain` - does around its own
4
+ * What every command that builds - `turri regenerate`, `conform`, `spec-diff` - does around its own
5
5
  * request of the work loop, as the chat does it: the project's models, a job that fails run once more and, failing again,
6
6
  * diagnosed, a line as each job starts and ends; then the loop run until nothing more can start, how each job ended,
7
7
  * and exit 1 when any failed or a module is not complete. With `dryRun`, the work is planned and the prompt of the first job each codebase would
package/dist/loop-cli.js CHANGED
@@ -17,7 +17,7 @@ import { listFiles } from "./regenerate/testing.js";
17
17
  import { startRunReport } from "./run-report.js";
18
18
  import { configKeyOptions, optionValue } from "./cli-options.js";
19
19
  /**
20
- * What every command that builds - `turri regenerate`, `conform`, `change-plain` - does around its own
20
+ * What every command that builds - `turri regenerate`, `conform`, `spec-diff` - does around its own
21
21
  * request of the work loop, as the chat does it: the project's models, a job that fails run once more and, failing again,
22
22
  * diagnosed, a line as each job starts and ends; then the loop run until nothing more can start, how each job ended,
23
23
  * and exit 1 when any failed or a module is not complete. With `dryRun`, the work is planned and the prompt of the first job each codebase would
@@ -173,10 +173,10 @@ export function withinModules(text) {
173
173
  }
174
174
  /**
175
175
  * What the person is shown a tool as, where that is not the name its agent calls it by. The agent's name says
176
- * what the call takes - `change_plain` takes a diff of the spec - and the shown one speaks turri's language.
176
+ * what the call takes - `write_spec_diff` takes a diff of the spec - and the shown one speaks turri's language.
177
177
  */
178
178
  const SHOWN_AS = {
179
- change_plain: "mutate",
179
+ write_spec_diff: "mutate",
180
180
  };
181
181
  /** A tool's name as the person is shown it. */
182
182
  export function shownName(name) {
@@ -15,7 +15,7 @@ const TOOL_FOR = {
15
15
  conform: "conform",
16
16
  cultivate: "cultivate",
17
17
  release: "release",
18
- "change-plain": "regenerate",
18
+ "spec-diff": "regenerate",
19
19
  chat: "nothing - you are the conversation already",
20
20
  ask: "nothing - you are the conversation already",
21
21
  };
@@ -31,7 +31,7 @@ const NPM_SCRIPT = {
31
31
  const ENTRY = {
32
32
  "regenerate-cli": "regenerate",
33
33
  "conform-cli": "conform",
34
- "change-plain-cli": "change-plain",
34
+ "spec-diff-cli": "spec-diff",
35
35
  "cultivate-cli": "cultivate",
36
36
  "release-cli": "release",
37
37
  };
@@ -43,10 +43,10 @@ const AT_COMMAND = String.raw `(?:^|[\s;&|()\x60$])`;
43
43
  * agent - and neither are setup and doctor.
44
44
  */
45
45
  export function selfInvocation(command) {
46
- const cli = new RegExp(`${AT_COMMAND}(?:npx\\s+)?turri\\s+(regenerate|glimpse|conform|cultivate|release|change-plain)\\b`).exec(command);
46
+ const cli = new RegExp(`${AT_COMMAND}(?:npx\\s+)?turri\\s+(regenerate|glimpse|conform|cultivate|release|spec-diff)\\b`).exec(command);
47
47
  if (cli)
48
48
  return cli[1];
49
- const launcher = new RegExp(`(?:bin/turri\\.mjs|src/cli\\.ts)\\s+(regenerate|glimpse|conform|cultivate|release|change-plain)\\b`).exec(command);
49
+ const launcher = new RegExp(`(?:bin/turri\\.mjs|src/cli\\.ts)\\s+(regenerate|glimpse|conform|cultivate|release|spec-diff)\\b`).exec(command);
50
50
  if (launcher)
51
51
  return launcher[1];
52
52
  // turri alone, or with options, is the conversation - where a command starts, not a word an argument names (`which turri`).
@@ -83,7 +83,7 @@ const PI_CONFIGURES = new Set([
83
83
  export function askedForCommandLine(message) {
84
84
  const text = message.toLowerCase();
85
85
  return (/\b(headless|command[ -]line|cli|terminal|shell|in bash|via bash|through bash|npm run|nohup)\b/.test(text) ||
86
- /\bturri\s+(regenerate|glimpse|conform|change-plain|cultivate|release)\b/.test(text) ||
86
+ /\bturri\s+(regenerate|glimpse|conform|spec-diff|cultivate|release)\b/.test(text) ||
87
87
  /(^|\s)turri\s+-p\b/.test(text) ||
88
88
  /(^|\s)pi\s+-p\b/.test(text));
89
89
  }
@@ -102,7 +102,7 @@ export const TOOLS_NOT_CLI = [
102
102
  "<turri-tools>",
103
103
  "In this conversation, you do your work with your tools - regenerate, conform, cultivate and the rest - which run as",
104
104
  "background jobs the user can watch and halt. To try what is regenerated, release it - never by hand in plain_modules. Never",
105
- "run your own command line (turri regenerate, glimpse, conform, change-plain, cultivate, release, turri itself; npm run",
105
+ "run your own command line (turri regenerate, glimpse, conform, spec-diff, cultivate, release, turri itself; npm run",
106
106
  "regenerate and the like) or start another pi through bash:",
107
107
  "that is a separate headless run the user cannot see or stop. Only when the user explicitly asks for the",
108
108
  "command line, run it. Configuring pi itself - pi install, update, list, config, auth, or its settings files -",
package/dist/skill.d.ts CHANGED
@@ -70,7 +70,7 @@ export interface Skill {
70
70
  allowedTools: string[];
71
71
  steps: StepSpec[];
72
72
  /**
73
- * Whether `change_plain` needs an answer from the user between two new changes - one answer,
73
+ * Whether `write_spec_diff` needs an answer from the user between two new changes - one answer,
74
74
  * one change, as an interview writes them. `metadata.paced: false` turns it off, for a skill that
75
75
  * writes the specs on its own.
76
76
  */
@@ -81,8 +81,8 @@ export interface Skill {
81
81
  */
82
82
  questioning: string[];
83
83
  /**
84
- * The steps where each answer is a spec change (`metadata.change-plain-per-answer`): the next question waits until the
85
- * last answer is written with `change_plain`, and changes the agent decides itself need no answer before them.
84
+ * The steps where each answer is a spec change (`metadata.spec-diff-per-answer`): the next question waits until the
85
+ * last answer is written with `write_spec_diff`, and changes the agent decides itself need no answer before them.
86
86
  */
87
87
  diffPerAnswer: string[];
88
88
  /**
package/dist/skill.js CHANGED
@@ -109,11 +109,11 @@ export function loadSkill(skillDir) {
109
109
  throw new Error(`${name}: 'metadata.questioning' names unknown step '${stepName}'`);
110
110
  }
111
111
  }
112
- const perAnswer = data.metadata?.["change-plain-per-answer"];
112
+ const perAnswer = data.metadata?.["spec-diff-per-answer"];
113
113
  const diffPerAnswer = Array.isArray(perAnswer) ? perAnswer.map(String) : [];
114
114
  for (const stepName of diffPerAnswer) {
115
115
  if (!steps.some((s) => s.name === stepName)) {
116
- throw new Error(`${name}: 'metadata.change-plain-per-answer' names unknown step '${stepName}'`);
116
+ throw new Error(`${name}: 'metadata.spec-diff-per-answer' names unknown step '${stepName}'`);
117
117
  }
118
118
  }
119
119
  for (const stepName of gatesByStep.keys()) {
@@ -4,9 +4,9 @@ import { checkPlainFile } from "./plain/check.js";
4
4
  import { applySpecDiff, revertSpecDiff } from "./regenerate/regenerate.js";
5
5
  import { parseArgs } from "./cli-options.js";
6
6
  import { headlessOptions, runLoop } from "./loop-cli.js";
7
- const USAGE = `usage: turri change-plain <file.plain> <diff-file> [options]
7
+ const USAGE = `usage: turri spec-diff <file.plain> <diff-file> [options]
8
8
 
9
- Applies a change to ***plain, given as a git diff of the .plain files, and builds it: the headless
9
+ Applies a change to the specs, given as a git diff of the .plain files, and builds it: the headless
10
10
  counterpart of regenerate, given a diff. The diff is applied first, unless it is already in; then, as
11
11
  turri regenerate does, what is left to build is planned into jobs and built.
12
12
 
@@ -40,7 +40,7 @@ runLoop({
40
40
  startOver: options["start-over"] !== undefined,
41
41
  ...(buildDir !== undefined ? { buildDir } : {}),
42
42
  ...(report !== undefined ? { report } : {}),
43
- command: ["change-plain", ...process.argv.slice(2)],
43
+ command: ["spec-diff", ...process.argv.slice(2)],
44
44
  ask: (loop) => loop.bringUp(plainFile),
45
45
  }).catch((error) => {
46
46
  console.error(error instanceof Error ? error.message : error);
@@ -28,7 +28,7 @@ export function createSpecDiffTools(options) {
28
28
  let owed = false;
29
29
  let answeredSinceLastDiff = true;
30
30
  const writeDiff = defineTool({
31
- name: "change_plain",
31
+ name: "write_spec_diff",
32
32
  label: "Write spec diff",
33
33
  description: "Apply a change to the ***plain specs, given as a git diff of the .plain files, and start building it in " +
34
34
  "the background. The diff is applied with git; if the specs no longer parse, it is undone and nothing is " +
@@ -36,7 +36,7 @@ export function createSpecDiffTools(options) {
36
36
  "every change is built, whatever it touches.",
37
37
  promptSnippet: "apply a git diff of the .plain specs and start building it",
38
38
  promptGuidelines: [
39
- "Every change to a .plain file in the product phase goes through change_plain, as a git diff with paths relative to the project root. It writes the change and starts its build in one step.",
39
+ "Every change to a .plain file in the product phase goes through write_spec_diff, as a git diff with paths relative to the project root. It writes the change and starts its build in one step.",
40
40
  skillPaced
41
41
  ? "One change per answer, and a new one only after the user has answered a question about it. Set fixes_earlier to correct something already written."
42
42
  : "Write the changes one after another, on your own: no answer is needed between them, and none is asked for. Set fixes_earlier to correct something already written.",
package/dist/stacks.js CHANGED
@@ -77,7 +77,7 @@ export function registerStacks(pi, cwd) {
77
77
  "For the session; a pulse already running keeps the stack it started with. Without a name, says the stacks and the one chosen.",
78
78
  promptSnippet: "choose the stack - its testing scripts and settings - that everything is built with",
79
79
  promptGuidelines: [
80
- "Switch the stack only when the user asks for it, and say which you chose. A module is built with the stack named after it by itself; to build one whose stack has another name, pass that stack as stack to regenerate, conform, glimpse or change_plain instead: it is pinned to that module's pulses, and the session's choice stays as it is.",
80
+ "Switch the stack only when the user asks for it, and say which you chose. A module is built with the stack named after it by itself; to build one whose stack has another name, pass that stack as stack to regenerate, conform, glimpse or write_spec_diff instead: it is pinned to that module's pulses, and the session's choice stays as it is.",
81
81
  ],
82
82
  parameters: Type.Object({
83
83
  name: Type.Optional(Type.String({ description: "The stack to choose, or none. Omitted: the stacks there are, and the one chosen" })),
package/dist/tools.js CHANGED
@@ -164,7 +164,7 @@ export function createEndQuestionsTool(questioning) {
164
164
  label: "End questions",
165
165
  description: "End this phase's questions: you have asked what the person must decide, and you decide what is left " +
166
166
  "yourself, saying what you chose. Afterwards ask_user asks only the phase's closing confirmation, and " +
167
- "change_plain needs no answer between changes.",
167
+ "write_spec_diff needs no answer between changes.",
168
168
  promptSnippet: "end this phase's questions and decide what is left yourself",
169
169
  parameters: Type.Object({}),
170
170
  async execute() {
package/docs/README.md CHANGED
@@ -1,31 +1,31 @@
1
1
  # turri documentation
2
2
 
3
- turri is the first coding agent with the power of regenerative software: [\*\*\*plain](https://plainlang.org/docs/) captures the durable definition of what a system does, and the code is regenerated from it and validated against. The [project README](../README.md) says why, and how to install and start; these pages go into each part.
3
+ turri implements regenerative software: [\*\*\*plain](https://plainlang.org/docs/) captures the durable definition of what a system does, and the code is regenerated from it and validated against. The [project README](../README.md) says why, and how to install and start; these pages go into each part.
4
4
 
5
5
  ## Start here
6
6
 
7
7
  1. [Installation](installation.md) - get a machine ready: `turri doctor`, and what turri needs of this machine.
8
- 2. [Using turri](using.md) - the conversation, the skills and tools, background jobs and their logs, choosing the model that codes, the command line.
9
- 3. [Authoring \*\*\*plain](authoring-plain.md) - writing \*\*\*plain: what is it made out of, the authoring rules, the skills that write and fix it.
10
- 4. [Regenerating](regenerating.md) - turning \*\*\*plain into code: what each build does, in which order, and what has to pass before it moves on.
8
+ 2. [Using turri](using.md) - the conversation, the skills and tools, background jobs and their logs, choosing the model that regenerates, the command line.
9
+ 3. [Authoring \*\*\*plain](authoring-plain.md) - writing the specs: what a spec is made of, the authoring rules, the skills that write and fix specs.
10
+ 4. [Regenerating](regenerating.md) - turning the specs into code: what each build does, in which order, and what has to pass before it moves on.
11
11
 
12
12
  ## By question
13
13
 
14
14
  | to find out… | read |
15
15
  | --- | --- |
16
16
  | what my machine needs, and why a check failed | [installation](installation.md) |
17
- | what turri needs of this machine, and what `turri doctor` checks | [installation](installation.md#what-turri-doctor-checks) |
17
+ | what turri needs of this machine, and what `turri doctor` checks | [installation](installation.md#what-turri-setup-checks) |
18
18
  | how to start a project, or add a feature, in a conversation | [using](using.md#in-a-conversation) |
19
- | which model codes, and how to change it | [using](using.md#choosing-a-model), [the project config](config.md#models) |
19
+ | which model regenerates, and how to change it | [using](using.md#choosing-a-model), [the project config](config.md#models) |
20
20
  | what `config.turri.yaml` can set, and what happens without it | [the project config](config.md) |
21
21
  | how a backend and a frontend on different stacks share one project | [the project config](config.md#stacks) |
22
- | which ready-made stacks \*\*\*plain can import - a FastAPI backend, a React frontend | [the standard library](authoring-plain.md#the-standard-library) |
22
+ | which ready-made stacks a spec can import - a FastAPI backend, a React frontend | [the standard library](authoring-plain.md#the-standard-library) |
23
23
  | everything an agent was sent and did, to debug it | [using](using.md#agent-logs) |
24
- | how to regenerate \*\*\*plain overnight, and resume it | [running unattended](headless.md) |
24
+ | how to regenerate a spec overnight, and resume it | [running unattended](headless.md) |
25
25
  | how to rebuild one functionality | [running unattended](headless.md#rebuilding-one-functionality) |
26
- | what goes in which section of \*\*\*plain | [authoring \*\*\*plain](authoring-plain.md#what-plain-is-made-of) |
26
+ | what goes in which section of a spec | [authoring \*\*\*plain](authoring-plain.md#what-a-spec-is-made-of) |
27
27
  | which skill does what | [authoring \*\*\*plain](authoring-plain.md#the-skills) |
28
- | what happens when \*\*\*plain changes | [regenerating the code](regenerating.md#when-plain-changes) |
28
+ | what happens when a spec changes | [regenerating the code](regenerating.md#when-the-spec-changes) |
29
29
  | why a test was not allowed to be deleted | [regenerating the code](regenerating.md#the-tests-must-actually-pass) |
30
30
  | how to try what is built, and what deploy may install | [deploy](deploy.md) |
31
31
  | what the agents can and cannot reach | [the sandbox](sandbox.md) |
@@ -43,8 +43,8 @@ turri is the first coding agent with the power of regenerative software: [\*\*\*
43
43
  | [The project config](config.md) | `config.turri.yaml` and each stack's `config.turri.<stack>.yaml`: where they are read from, every key, models and their inheritance, conformance, the testing scripts, stacks and choosing one, the old `config.yaml` |
44
44
  | [Deploy](deploy.md) | trying what is built: dist/<module>, the last commit, starting it on your machine, `turri release` |
45
45
  | [Running unattended](headless.md) | regenerating overnight or in CI: before you leave it, the command, the results, resuming, rebuilding one functionality |
46
- | [Authoring \*\*\*plain](authoring-plain.md) | a \*\*\*plain project, what \*\*\*plain is made of, the rules, writing \*\*\*plain with the agent, the skills, checking \*\*\*plain |
47
- | [Regenerating](regenerating.md) | where things go, one job, a whole module and how its work is cut into jobs, each job's cases, \*\*\*plain changes, conformance tests, the two records of what is built |
46
+ | [Authoring \*\*\*plain](authoring-plain.md) | a \*\*\*plain project, what a spec is made of, the rules, writing specs with the agent, the skills, checking a spec |
47
+ | [Regenerating](regenerating.md) | where things go, one job, a whole module and how its work is cut into jobs, each job's cases, spec changes, conformance tests, the two records of what is built |
48
48
  | [The sandbox](sandbox.md) | what an agent can reach, the file-tool fence, the command check, the OS sandbox, the audit |
49
49
  | [Skills and gates](skills-and-gates.md) | the gate syntax, what the harness enforces, what a step can do, the rules, trying the gates |
50
50
  | [The \*\*\*plain parser](parser.md) | the TypeScript port, `turri validate`, inheritance, the iterator, fidelity |
@@ -1,8 +1,8 @@
1
1
  # Authoring \*\*\*plain
2
2
 
3
- turri builds code from [\*\*\*plain](https://plainlang.org/docs/) - its documentation is the language's whole reference. Regenerating turns \*\*\*plain into code; authoring is the half that decides what gets built. The code is only ever as good as the \*\*\*plain description - a fact in the wrong section is silently ignored, a functional spec that is too big comes out half-built, two functional specs that contradict each other break each other's tests. So this repo carries as much for writing \*\*\*plain as for regenerating it: the authoring rules, a library of skills that apply them, and independent review of what they write.
3
+ A spec is written in [\*\*\*plain](https://plainlang.org/docs/) - its documentation is the language's whole reference. Rendering turns a spec into code; authoring is the half that decides what gets built. The code is only ever as good as the spec - a fact in the wrong section is silently ignored, a functional spec that is too big comes out half-built, two specs that contradict each other break each other's tests. So this repo carries as much for writing specs as for rendering them: the authoring rules, a library of skills that apply them, and independent review of what they write.
4
4
 
5
- The rule underneath all of it: **\*\*\*plain is the source of truth**. The generated code in `plain_modules/` is never edited by hand. A bug is fixed in \*\*\*plain, and a change that is wanted goes into \*\*\*plain - that is what persists and what the next regeneration builds from.
5
+ The rule underneath all of it: **the specs are the source of truth**. The generated code in `plain_modules/` is never edited by hand. A bug is fixed in the spec, and a change that is wanted goes into the spec - that is what persists and what the next render builds from.
6
6
 
7
7
  ## A \*\*\*plain project
8
8
 
@@ -16,7 +16,7 @@ my-project/
16
16
  plain_modules/ # generated - code, tests, history; never edited by hand
17
17
  ```
18
18
 
19
- ## What \*\*\*plain is made of
19
+ ## What a spec is made of
20
20
 
21
21
  A `.plain` file is one module: optional YAML frontmatter, then up to four sections, in this order.
22
22
 
@@ -39,13 +39,13 @@ The frontmatter connects modules:
39
39
  | `exported_concepts` | which concepts a module that `requires` this one may use |
40
40
  | `required_concepts` | concepts an import module expects the importing module to define |
41
41
 
42
- Beyond that: \*\*\*plain links to files under `resources/` with markdown link syntax, and the file's contents go to the coding agents with the \*\*\*plain description; lines starting with `>` are comments for people; and files are processed with Liquid first, so a template can be included with parameters.
42
+ Beyond that: a spec links to files under `resources/` with markdown link syntax, and the file's contents go to the renderer with the spec; lines starting with `>` are comments for people; and files are processed with Liquid first, so a template can be included with parameters.
43
43
 
44
- **Section ownership is the rule that bites.** turri reads each kind of fact only from the section that owns it. A tech choice written into a functional spec, or a behaviour written into the implementation reqs, is not flagged - it is simply not read.
44
+ **Section ownership is the rule that bites.** The renderer reads each kind of fact only from the section that owns it. A tech choice written into a functional spec, or a behaviour written into the implementation reqs, is not flagged - it is simply not read.
45
45
 
46
46
  ## The standard library
47
47
 
48
- turri ships a standard library of import modules in `stdlib/` that settle everything about a generic piece of software on one stack except what it does: its language and framework, layout, configuration, error handling, logging, shutdown, and how it is unit and conformance tested. A module's \*\*\*plain imports one and writes only its own concepts and functional specs:
48
+ turri ships a standard library of import modules in `stdlib/` that settle everything about a generic piece of software on one stack except what it does: its language and framework, layout, configuration, error handling, logging, shutdown, and how it is unit and conformance tested. A spec imports one and writes only its own concepts and functional specs:
49
49
 
50
50
  ```plain
51
51
  ---
@@ -82,19 +82,19 @@ It is built in three layers, and a stack imports the other two:
82
82
 
83
83
  Each conformance template imports its kind's `conformance/common`: a backend's tests start the built service on a free port and reach it over HTTP only, checking a failure by status and `error.code`; a frontend's run the served build in Chromium through Playwright with the backend stood in; a command-line tool's run the built tool as a process; a library's go through its public entry point.
84
84
 
85
- - **Conformance tests apart.** \*\*\*plain without the conformance template has no test reqs, so no conformance tests are written or run for it. Turning them on later is adding that one import.
86
- - **A reserved name.** An import that starts with `stdlib/` is always turri's template, never a file of the project's. A project with a module at such a path - `stdlib/backend/python-fastapi.plain` beside the project's \*\*\*plain, in its `template/` folder or in `PLAIN_TEMPLATE_DIRS` - gets an error saying the name is reserved, so which one the project's \*\*\*plain builds on never depends on what is on disk beside it.
87
- - **No concepts.** Its requirements are on the predefined `:Implementation:`, `:UnitTests:` and `:ConformanceTests:` only, so it never collides with \*\*\*plain's own definitions.
85
+ - **Conformance tests apart.** A spec without the conformance template has no test reqs, so no conformance tests are written or run for it. Turning them on later is adding that one import.
86
+ - **A reserved name.** An import that starts with `stdlib/` is always turri's template, never a file of the project's. A project with a module at such a path - `stdlib/backend/python-fastapi.plain` beside the spec, in its `template/` folder or in `PLAIN_TEMPLATE_DIRS` - gets an error saying the name is reserved, so which one a spec builds on never depends on what is on disk beside it.
87
+ - **No concepts.** Its requirements are on the predefined `:Implementation:`, `:UnitTests:` and `:ConformanceTests:` only, so it never collides with a spec's own definitions.
88
88
  - **Pinned to a toolchain.** It names its stack's toolchain - Python 3.12, Node.js 24, Java 21, Go 1.25, Rust - which the agents use from this machine; `turri doctor` says when the machine lacks it.
89
89
  - **Not storage, not the testing scripts.** A module with a database says which on top of its stack. It still needs its unit testing script, and a conformance testing script when it has conformance tests.
90
- - **Known to the agents.** The `stdlib` rule, in the system prompt of every agent that writes \*\*\*plain, says when to import which, and lists every template with what it is and the folder it is in, read from `stdlib/` when the rules load. `spawn` and `brood` import a stack when the one chosen is in it, and its conformance template when conformance tests are on.
91
- - **Only what this machine can build.** The agents use this machine's toolchains and install none, so a Go stack on a laptop without Go stops at its first build. Every agent that writes \*\*\*plain, and the conversation, are told which of the standard library's languages the machine can build now - Python needs `uv`, TypeScript and every frontend `node` and `npm`, Go `go`, Rust `cargo`, Java a JDK (`src/stack.ts`, `toolchainsBlock`) - and `spawn` and `brood` offer, and choose, only stacks in those. A stack the person names in a language the machine lacks is not refused: they are told what to install first, and that `turri doctor` checks it.
90
+ - **Known to the agents.** The `stdlib` rule, in every spec-writing agent's system prompt, says when to import which, and lists every template with what it is and the folder it is in, read from `stdlib/` when the rules load. `spawn` and `brood` import a stack when the one chosen is in it, and its conformance template when conformance tests are on.
91
+ - **Only what this machine can build.** The agents use this machine's toolchains and install none, so a Go stack on a laptop without Go stops at its first build. Every spec-writing agent and the conversation are told which of the standard library's languages the machine can build now - Python needs `uv`, TypeScript and every frontend `node` and `npm`, Go `go`, Rust `cargo`, Java a JDK (`src/stack.ts`, `toolchainsBlock`) - and `spawn` and `brood` offer, and choose, only stacks in those. A stack the person names in a language the machine lacks is not refused: they are told what to install first, and that `turri doctor` checks it.
92
92
 
93
93
  A requirement beyond the stack - storage, an outside service - is added on top of it. A module that differs from its stack on something the stack settles - another framework, another layout - writes its own instead: an import cannot be taken back in part.
94
94
 
95
95
  ## The rules
96
96
 
97
- `genome/rules/` holds the authoring rules. They are in the system prompt of every agent that writes \*\*\*plain - the conversation, the interview skills, the reviewers - so they are not something an agent has to decide to go and read.
97
+ `genome/rules/` holds the authoring rules. They are in the system prompt of every agent that writes specs - the conversation, the interview skills, the reviewers - so they are not something an agent has to decide to go and read.
98
98
 
99
99
  | rule | covers |
100
100
  | --- | --- |
@@ -103,40 +103,40 @@ A requirement beyond the stack - storage, an outside service - is added on top o
103
103
  | `func-specs.md` | voice, the complexity limit, chronological order, no conflicts, language agnosticism, testability, acceptance tests |
104
104
  | `impl-reqs.md` | HOW not WHAT, unit tests live here, what belongs and what does not |
105
105
  | `test-reqs.md` | conformance tests only, what belongs, test types |
106
- | `concise-specs.md` (+ two example banks) | keeping \*\*\*plain short enough for a person to review: no obvious lines, plain words, no uncheckable adjectives, no hedging |
106
+ | `concise-specs.md` (+ two example banks) | keeping specs short enough for a person to review: no obvious lines, plain words, no uncheckable adjectives, no hedging |
107
107
  | `bullet-continuation.md` | bullets and continuation lines in every section |
108
108
  | `linked-resources.md` | a linked resource is one text file on disk, or a PNG or JPEG image for a model that reads images; protocol artifacts are linked, never transcribed |
109
109
  | `import-modules.md`, `requires-modules.md` | the two ways modules build on each other |
110
110
  | `exported-concepts.md`, `required-concepts.md` | which concepts cross module boundaries |
111
- | `integrations.md` (+ standalone, embedded, embedded testing) | \*\*\*plain for REST API integrations, deployed standalone or embedded in an existing codebase |
112
- | `turri-regeneration.md` | turri's model of itself: a \*\*\*plain change regenerated as a \*\*\*plain diff, wherever it sits, in the chain's tip; what each kind of change sets off; what a coding agent sees; how bad code is fixed; where the cost is - so \*\*\*plain is placed by what it means, never to spare regeneration |
111
+ | `integrations.md` (+ standalone, embedded, embedded testing) | specs for REST API integrations, deployed standalone or embedded in an existing codebase |
112
+ | `turri-regeneration.md` | turri's model of itself: a spec change regenerated as a spec diff, wherever it sits, in the chain's tip; what each kind of change sets off; what a coding agent sees; how bad code is fixed; where the cost is - so a spec is placed by what it means, never to spare regeneration |
113
113
  | `stdlib.md` | the standard library: when to import which template, and every template with what it is and where it is, read from `stdlib/` |
114
114
 
115
- The ones that shape \*\*\*plain most:
115
+ The ones that shape a spec most:
116
116
 
117
117
  - **One functionality is at most ~200 lines of code.** A bigger one is split before it is written (`analyze-if-func-spec-too-complex`, `break-down-func-spec`).
118
- - **Functional specs are in build order.** Each is regenerated on top of the ones before it - which is what a functional spec may assume, not what a change costs: a functional spec inserted anywhere is regenerated alone.
118
+ - **Functional specs are in build order.** Each is rendered on top of the ones before it - which is what a spec may assume, not what a change costs: a spec inserted anywhere is regenerated alone.
119
119
  - **They state facts, with a concrete subject.** "A :User: can add a :Task:" - not "Implement adding tasks", not "The system should…".
120
120
  - **Nothing a test cannot check.** No `robust`, `seamless`, `as appropriate`; state the checkable fact or cut the word.
121
- - **No two functional specs contradict each other.** A conflict is found and resolved when a functional spec is added, not when its tests fail.
121
+ - **No two specs contradict each other.** A conflict is found and resolved when a spec is added, not when its tests fail.
122
122
 
123
- ## Writing \*\*\*plain with turri
123
+ ## Writing specs with turri
124
124
 
125
- In a conversation (`turri`), say what you want and the matching skill runs - but the three that start a project or a feature you start yourself, by their commands: `/brood`, `/spawn` or `/bud`, with what you want after it. Two build a project from scratch, and write each \*\*\*plain change as a git diff that is built in the background the moment it is written. `brood` interviews you one question at a time and writes \*\*\*plain as you answer; `spawn`, its quick twin, gets something running as soon as it can - the smallest thing that runs first, then the product a slice at a time - asking only what your message leaves open:
125
+ In a conversation (`turri`), say what you want and the matching skill runs - but the three that start a project or a feature you start yourself, by their commands: `/brood`, `/spawn` or `/bud`, with what you want after it. Two build a project from scratch, and write each spec change as a git diff that is built in the background the moment it is written. `brood` interviews you one question at a time and writes the specs as you answer; `spawn`, its quick twin, gets something running as soon as it can - the smallest thing that runs first, then the product a slice at a time - asking only what your message leaves open:
126
126
 
127
- | skill | phases | how a \*\*\*plain change is written |
127
+ | skill | phases | how a spec change is written |
128
128
  | --- | --- | --- |
129
- | `brood` | intent → stack → testing → product, feature by feature | first, how many questions the stack and product phases may ask - light 3, medium 5, thorough 10 or best judgement, broader with fewer, covering the same ground - and what they leave open turri decides itself, each decision a \*\*\*plain change of its own; every product answer is still a \*\*\*plain change, built before the next question; in testing, whether there are conformance tests, their `***test reqs***` and script - written as files, building nothing; then one \*\*\*plain change per answer, across whatever sections it needs, as a git diff with `change_plain`, regenerated as a \*\*\*plain diff pulse and conformance tested as it is built |
130
- | `spawn` | start → skeleton → regenerate | built for the time to first regeneration: what to build is asked only when the message does not say, and the stack only when the user named one this machine cannot build - otherwise turri chooses one; the stack and the unit tests are written as files, with conformance tests off unless the user asks for them; then a \*\*\*plain change for the smallest thing that runs starts the first build - a module's first pulse of one functional spec is not reviewed - and the main slice of what the user described and at most one more follow - none when they described no feature, and never one of turri's own - each a functional spec on its happy path, as git diffs with `change_plain`, one after another with no answer between them. The rest - the next slices, then validation and edge cases as changes to those functional specs - is asked for in the conversation once the user has tried what landed: `go on` for the next slice it proposed |
129
+ | `brood` | intent → stack → testing → product, feature by feature | first, how many questions the stack and product phases may ask - light 3, medium 5, thorough 10 or best judgement, broader with fewer, covering the same ground - and what they leave open turri decides itself, each decision a spec change of its own; every product answer is still a spec change, built before the next question; in testing, whether there are conformance tests, their `***test reqs***` and script - written as files, building nothing; then one spec change per answer, across whatever sections it needs, as a git diff with `write_spec_diff`, rendered as a render spec diff job and conformance tested as it is built |
130
+ | `spawn` | start → skeleton → regenerate | built for the time to first regeneration: what to build is asked only when the message does not say, and the stack only when the user named one this machine cannot build - otherwise turri chooses one; the stack and the unit tests are written as files, with conformance tests off unless the user asks for them; then a spec change for the smallest thing that runs starts the first build - a module's first pulse of one functional spec is not reviewed - and the main slice of what the user described and at most one more follow - none when they described no feature, and never one of turri's own - each a functional spec on its happy path, as git diffs with `write_spec_diff`, one after another with no answer between them. The rest - the next slices, then validation and edge cases as changes to those specs - is asked for in the conversation once the user has tried what landed: `go on` for the next slice it proposed |
131
131
 
132
- `mature` starts from \*\*\*plain you already have, rough or hand-written, and runs on its own until it is fully regenerated - every functionality built from \*\*\*plain as it stands, its tests passing. It regenerates what is not built and watches the agents building it; when one struggles on something \*\*\*plain leaves open or unclear - sent back again and again, the judge going back and forth, a \*\*\*plain conflict - it writes what \*\*\*plain should say as a \*\*\*plain diff, stops that build, and regenerates it again. What the builds had to decide themselves - their assumptions, pitfalls, a failed build's diagnosis - goes into \*\*\*plain the same way, when a user, a caller or a test can see it. It never asks: it takes the reading that fits the rest of the \*\*\*plain description, and marks each such decision in its report. It leaves code, environment and turri problems to the builds, and stops when a functionality keeps struggling after its \*\*\*plain was clarified, when two cycles change nothing, or after twenty.
132
+ `mature` starts from a spec you already have, rough or hand-written, and runs on its own until it is fully rendered - every functionality built from the spec as it stands, its tests passing. It renders what is not built and watches the agents building it; when one struggles on something the spec leaves open or unclear - sent back again and again, the judge going back and forth, a spec conflict - it writes what the spec should say as a spec diff, stops that build, and renders it again. What the builds had to decide themselves - their assumptions, pitfalls, a failed build's diagnosis - goes into the spec the same way, when a user, a caller or a test can see it. It never asks: it takes the reading that fits the rest of the spec, and marks each such decision in its report. It leaves code, environment and turri problems to the builds, and stops when a functionality keeps struggling after the spec was clarified, when two cycles change nothing, or after twenty.
133
133
 
134
- For an existing project, `bud` works the same way, scoped to one feature: intent → scope → product. It first asks how many questions the product phase may ask - light, medium, thorough or best judgement, as `brood` does - then a short feature-intent interview, then product questions - a trigger and its outcome, an edge case, a rule - and every answer is a \*\*\*plain change, a git diff written with `change_plain` and built the moment it is written, before the next question. What the questions leave open it decides itself, a \*\*\*plain change each. A change to something already specified, built or still to build, is put to the user first and is a \*\*\*plain diff too: what is left to build is worked out again from \*\*\*plain. It ends on the person's confirmation of a short summary of the feature's changes.
134
+ For an existing project, `bud` works the same way, scoped to one feature: intent → scope → product. It first asks how many questions the product phase may ask - light, medium, thorough or best judgement, as `brood` does - then a short feature-intent interview, then product questions - a trigger and its outcome, an edge case, a rule - and every answer is a spec change, a git diff written with `write_spec_diff` and built the moment it is written, before the next question. What the questions leave open it decides itself, a spec change each. A change to something already specified, built or still to build, is put to the user first and is a spec diff too: what is left to build is worked out again from the spec. It ends on the person's confirmation of a short summary of the feature's changes.
135
135
 
136
136
  What keeps the interview honest is the harness, not the interviewer:
137
137
 
138
- - **Every question offers choices** (`ask_user` refuses a question without them), and each answer maps to one \*\*\*plain change.
139
- - **Every answer is written before the next question.** In the product phase of `brood` and `bud`, `ask_user` refuses a new question until the last answer is a \*\*\*plain change - see [skills and gates](skills-and-gates.md).
138
+ - **Every question offers choices** (`ask_user` refuses a question without them), and each answer maps to one spec change.
139
+ - **Every answer is written before the next question.** In the product phase of `brood` and `bud`, `ask_user` refuses a new question until the last answer is a spec change - see [skills and gates](skills-and-gates.md).
140
140
  - **Each phase ends on the person's confirmation** of a short summary, not on the interviewer's word.
141
141
 
142
142
  ## The skills
@@ -146,21 +146,21 @@ Every skill in `genome/skills/` can be run from a conversation; most are also us
146
146
  | to… | skills |
147
147
  | --- | --- |
148
148
  | start a project | `brood`, `spawn`, `init-plain-project` |
149
- | make rough \*\*\*plain build | `mature` |
150
- | add to \*\*\*plain | `bud`, `add-functional-spec`, `add-functional-specs`, `add-concept`, `add-implementation-requirement`, `add-test-requirement`, `add-acceptance-test`, `add-resource`, `add-template` |
149
+ | make a rough spec build | `mature` |
150
+ | add to a spec | `bud`, `add-functional-spec`, `add-functional-specs`, `add-concept`, `add-implementation-requirement`, `add-test-requirement`, `add-acceptance-test`, `add-resource`, `add-template` |
151
151
  | check what is written | `analyze-if-func-spec-too-complex`, `analyze-2-func-specs`, `analyze-func-specs`, `resolve-section-ownership` |
152
152
  | fix what is written | `break-down-func-spec`, `resolve-spec-conflict`, `debug-specs` |
153
153
  | restructure modules | `create-import-module`, `create-requires-module`, `refactor-module`, `consolidate-concepts` |
154
154
  | set up the project to build | `implement-unit-testing-script`, `implement-conformance-testing-script`, `check-plain-env` |
155
155
 
156
- `debug-specs` is the one for a running application that misbehaves: it reads the generated code to find the cause, traces it back to \*\*\*plain, and fixes only the `.plain` files.
156
+ `debug-specs` is the one for a running application that misbehaves: it reads the generated code to find the cause, traces it back to the spec, and fixes only the `.plain` files.
157
157
 
158
- ## Checking \*\*\*plain
158
+ ## Checking a spec
159
159
 
160
160
  ```bash
161
161
  turri validate app.plain # or validate in a conversation
162
162
  ```
163
163
 
164
- It parses \*\*\*plain with this repo's own parser, resolves its imports and required modules, and reports every syntax, concept and structure error with its line - no model, no API key. The interview skills run it before a phase ends, and `change_plain` refuses a change that leaves a file that does not parse. Pass the project directory to check every module at once.
164
+ It parses the spec with this repo's own parser, resolves its imports and required modules, and reports every syntax, concept and structure error with its line - no model, no API key. The interview skills run it before a phase ends, and `write_spec_diff` refuses a change that leaves a file that does not parse. Pass the project directory to check every module at once.
165
165
 
166
- What `check` cannot see - a fact in the wrong section, a functional spec that is too big, two that conflict, wording no test can check - is what the rules, the skills and the reviewers are for.
166
+ What `check` cannot see - a fact in the wrong section, a spec that is too big, two that conflict, wording no test can check - is what the rules, the skills and the reviewers are for.