@turri-dev/cli 0.1.27 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/advisor-chat.d.ts +63 -0
- package/dist/advisor-chat.js +290 -0
- package/dist/background-skills.d.ts +53 -0
- package/dist/background-skills.js +121 -0
- package/dist/bedrock-region.d.ts +66 -0
- package/dist/bedrock-region.js +144 -0
- package/dist/btw.d.ts +1 -1
- package/dist/btw.js +1 -1
- package/dist/change-plain-cli.js +20 -13
- package/dist/chat-idle.d.ts +7 -0
- package/dist/chat-idle.js +20 -0
- package/dist/chats.d.ts +10 -0
- package/dist/chats.js +23 -0
- package/dist/cli-options.d.ts +1 -2
- package/dist/cli-options.js +2 -7
- package/dist/cli.js +11 -3
- package/dist/config-command.d.ts +14 -0
- package/dist/config-command.js +35 -15
- package/dist/config-edit.d.ts +3 -3
- package/dist/config-edit.js +16 -12
- package/dist/config.d.ts +54 -34
- package/dist/config.js +40 -44
- package/dist/conform-cli.js +12 -10
- package/dist/conformance-switch.d.ts +34 -0
- package/dist/conformance-switch.js +108 -0
- package/dist/cultivate-cli.js +15 -5
- package/dist/drift-cli.js +2 -0
- package/dist/extension.d.ts +15 -0
- package/dist/extension.js +260 -83
- package/dist/host-session.d.ts +26 -0
- package/dist/host-session.js +30 -2
- package/dist/host.d.ts +5 -2
- package/dist/host.js +7 -1
- package/dist/init-config.d.ts +1 -1
- package/dist/init-config.js +20 -11
- package/dist/loop-cli.d.ts +3 -3
- package/dist/loop-cli.js +13 -16
- package/dist/loop-tools.js +18 -10
- package/dist/model-check.d.ts +8 -3
- package/dist/model-check.js +13 -8
- package/dist/new-project.js +12 -8
- package/dist/{validate-cli.js → parse-cli.js} +11 -5
- package/dist/parse-tool.d.ts +9 -0
- package/dist/parse-tool.js +33 -0
- package/dist/pi-launch.js +1 -1
- package/dist/plain/check.d.ts +53 -6
- package/dist/plain/check.js +217 -24
- package/dist/plain/concepts.d.ts +8 -0
- package/dist/plain/concepts.js +66 -23
- package/dist/plain/cycles.d.ts +21 -0
- package/dist/plain/cycles.js +190 -0
- package/dist/plain/errors.d.ts +4 -0
- package/dist/plain/errors.js +7 -0
- package/dist/plain/files.d.ts +18 -1
- package/dist/plain/files.js +39 -2
- package/dist/plain/graph.d.ts +33 -4
- package/dist/plain/graph.js +60 -12
- package/dist/plain/highlight.d.ts +3 -2
- package/dist/plain/highlight.js +4 -3
- package/dist/plain/index.d.ts +8 -5
- package/dist/plain/index.js +8 -5
- package/dist/plain/liquid.js +1 -6
- package/dist/plain/markdown.d.ts +32 -3
- package/dist/plain/markdown.js +146 -24
- package/dist/plain/module-concepts.js +2 -2
- package/dist/plain/parser.d.ts +83 -28
- package/dist/plain/parser.js +381 -260
- package/dist/plain/plain.tmLanguage.json +29 -3
- package/dist/plain/project.d.ts +48 -0
- package/dist/plain/project.js +155 -0
- package/dist/plain/spec.d.ts +90 -28
- package/dist/plain/spec.js +107 -133
- package/dist/plain/test-plain-file.d.ts +59 -0
- package/dist/plain/test-plain-file.js +232 -0
- package/dist/regenerate/activity.d.ts +20 -9
- package/dist/regenerate/activity.js +11 -4
- package/dist/regenerate/advisor-records.d.ts +93 -0
- package/dist/regenerate/advisor-records.js +110 -0
- package/dist/regenerate/advisor-runs.d.ts +87 -0
- package/dist/regenerate/advisor-runs.js +327 -0
- package/dist/regenerate/base-folder.d.ts +68 -0
- package/dist/regenerate/base-folder.js +168 -0
- package/dist/regenerate/cases.d.ts +9 -6
- package/dist/regenerate/cases.js +70 -14
- package/dist/regenerate/change-view.d.ts +8 -3
- package/dist/regenerate/change-view.js +71 -22
- package/dist/regenerate/chunk-plan.d.ts +36 -15
- package/dist/regenerate/chunk-plan.js +165 -59
- package/dist/regenerate/conform.d.ts +3 -0
- package/dist/regenerate/conform.js +6 -5
- package/dist/regenerate/conformance-agents.d.ts +18 -39
- package/dist/regenerate/conformance-agents.js +60 -88
- package/dist/regenerate/conformance.d.ts +23 -13
- package/dist/regenerate/conformance.js +119 -82
- package/dist/regenerate/diff-view.d.ts +1 -1
- package/dist/regenerate/diff-view.js +20 -4
- package/dist/regenerate/drift.d.ts +47 -15
- package/dist/regenerate/drift.js +101 -30
- package/dist/regenerate/jobs.d.ts +2 -2
- package/dist/regenerate/jobs.js +1 -1
- package/dist/regenerate/ledger.d.ts +19 -0
- package/dist/regenerate/loop.d.ts +62 -43
- package/dist/regenerate/loop.js +472 -341
- package/dist/regenerate/paths.d.ts +4 -0
- package/dist/regenerate/paths.js +7 -1
- package/dist/regenerate/plain-palette.js +2 -0
- package/dist/regenerate/prompt.d.ts +57 -19
- package/dist/regenerate/prompt.js +157 -122
- package/dist/regenerate/records.d.ts +43 -12
- package/dist/regenerate/records.js +102 -88
- package/dist/regenerate/regenerate.js +29 -11
- package/dist/regenerate/regression.d.ts +4 -4
- package/dist/regenerate/regression.js +14 -10
- package/dist/regenerate/renames.d.ts +42 -0
- package/dist/regenerate/renames.js +185 -0
- package/dist/regenerate/requires.d.ts +1 -1
- package/dist/regenerate/requires.js +10 -3
- package/dist/regenerate/resources.d.ts +5 -3
- package/dist/regenerate/resources.js +4 -4
- package/dist/regenerate/scripts-being-written.d.ts +19 -0
- package/dist/regenerate/scripts-being-written.js +30 -0
- package/dist/regenerate/spec-map-view.d.ts +2 -2
- package/dist/regenerate/spec-map-view.js +46 -15
- package/dist/regenerate/spec-map.d.ts +27 -5
- package/dist/regenerate/spec-map.js +92 -60
- package/dist/regenerate/spec-steps.d.ts +48 -5
- package/dist/regenerate/spec-steps.js +213 -28
- package/dist/regenerate/state.d.ts +4 -3
- package/dist/regenerate/stop-report.d.ts +1 -1
- package/dist/regenerate/stop-report.js +10 -10
- package/dist/regenerate/test-advisor.d.ts +101 -0
- package/dist/regenerate/test-advisor.js +379 -0
- package/dist/regenerate/test-kinds.d.ts +71 -28
- package/dist/regenerate/test-kinds.js +110 -63
- package/dist/regenerate/test-scripts.d.ts +2 -0
- package/dist/regenerate/test-scripts.js +4 -0
- package/dist/regenerate/testing-steps.d.ts +41 -0
- package/dist/regenerate/testing-steps.js +110 -0
- package/dist/regenerate/testing.d.ts +1 -1
- package/dist/regenerate/testing.js +5 -4
- package/dist/regenerate/unit-review.d.ts +1 -1
- package/dist/regenerate/unit-review.js +3 -3
- package/dist/regenerate-cli.js +11 -12
- package/dist/release-agent.js +4 -0
- package/dist/release-cli.js +2 -0
- package/dist/release-tools.js +2 -0
- package/dist/run-report.d.ts +2 -2
- package/dist/run-report.js +4 -3
- package/dist/self-invocation.d.ts +1 -1
- package/dist/self-invocation.js +1 -1
- package/dist/sentinel.js +1 -1
- package/dist/setup.d.ts +10 -0
- package/dist/setup.js +52 -4
- package/dist/skill.d.ts +10 -0
- package/dist/skill.js +6 -0
- package/dist/skills.js +3 -1
- package/dist/spec-tools.js +21 -31
- package/dist/test-plain-files.d.ts +41 -0
- package/dist/test-plain-files.js +177 -0
- package/docs/README.md +3 -1
- package/docs/authoring-plain.md +46 -13
- package/docs/chats.md +3 -1
- package/docs/config.md +20 -15
- package/docs/deploy.md +1 -1
- package/docs/development.md +2 -1
- package/docs/headless.md +15 -18
- package/docs/hosting.md +28 -12
- package/docs/installation.md +1 -0
- package/docs/parser.md +88 -27
- package/docs/regenerating.md +87 -52
- package/docs/sentinel.md +1 -1
- package/docs/skills-and-gates.md +3 -1
- package/docs/test-advisor.md +110 -0
- package/docs/theming.md +1 -1
- package/docs/using.md +17 -15
- package/genome/rules/bullet-continuation.md +8 -8
- package/genome/rules/concise-specs-examples.md +111 -80
- package/genome/rules/concise-specs-integration-examples.md +56 -41
- package/genome/rules/concise-specs.md +17 -16
- package/genome/rules/definitions.md +5 -5
- package/genome/rules/examples/integration-embedded-testing/run_conformance_tests_java.sh +1 -1
- package/genome/rules/func-specs.md +69 -74
- package/genome/rules/impl-reqs.md +4 -4
- package/genome/rules/integration-embedded-testing.md +20 -20
- package/genome/rules/integration-embedded.md +31 -31
- package/genome/rules/integration-standalone.md +9 -9
- package/genome/rules/integrations.md +18 -18
- package/genome/rules/linked-resources.md +19 -16
- package/genome/rules/module-structure.md +21 -14
- package/genome/rules/project-model.md +18 -17
- package/genome/rules/required-concepts.md +1 -1
- package/genome/rules/requires-modules.md +6 -5
- package/genome/rules/semantic-ids.md +49 -0
- package/genome/rules/stdlib.md +4 -5
- package/genome/rules/test-plain-files.md +130 -0
- package/genome/rules/test-reqs.md +8 -8
- package/genome/rules/turri-regeneration.md +23 -8
- package/genome/skills/analyze-2-func-specs/SKILL.md +36 -21
- package/genome/skills/analyze-func-specs/SKILL.md +46 -32
- package/genome/skills/break-down-func-spec/SKILL.md +91 -67
- package/genome/skills/consolidate-concepts/SKILL.md +10 -10
- package/genome/skills/convert-old-syntax/SKILL.md +68 -0
- package/genome/skills/convert-old-syntax/references/rubric.md +11 -0
- package/genome/skills/debug-specs/SKILL.md +62 -56
- package/genome/skills/implement-conformance-testing-script/SKILL.md +19 -15
- package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +2 -2
- package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +2 -2
- package/genome/skills/implement-unit-testing-script/SKILL.md +14 -10
- package/genome/skills/refactor-module/SKILL.md +35 -35
- package/genome/skills/resolve-section-ownership/SKILL.md +9 -9
- package/genome/skills/resolve-spec-conflict/SKILL.md +35 -29
- package/package.json +7 -6
- package/dist/regenerate/choose-conformance.d.ts +0 -32
- package/dist/regenerate/choose-conformance.js +0 -117
- /package/dist/{validate-cli.d.ts → parse-cli.d.ts} +0 -0
package/dist/config-edit.js
CHANGED
|
@@ -21,7 +21,6 @@ const ROLE_ABOUT = {
|
|
|
21
21
|
default: "every role not named",
|
|
22
22
|
chat: "the conversation - as harness-model, which it wins over",
|
|
23
23
|
sentinel: "the sentinel: checks every finished pulse and tests the release",
|
|
24
|
-
chooser: "chooses what gets conformance tests under turri regenerate",
|
|
25
24
|
planner: "cuts the work into pulses",
|
|
26
25
|
diagnosis: "looks into a pulse that failed for good",
|
|
27
26
|
release: "the release agent",
|
|
@@ -33,6 +32,7 @@ const ROLE_ABOUT = {
|
|
|
33
32
|
judge: "judges a failing conformance run - as judge-model, which it wins over",
|
|
34
33
|
arbiter: "weighs a second review",
|
|
35
34
|
debugger: "a fresh look at unit tests that keep failing the same way",
|
|
35
|
+
advisor: "the test advisor: whether a new or changed functional spec needs scenarios",
|
|
36
36
|
};
|
|
37
37
|
/** Every setting, in the order the list shows them. */
|
|
38
38
|
export function settings(rules = []) {
|
|
@@ -60,13 +60,15 @@ export function settings(rules = []) {
|
|
|
60
60
|
{ key: "coding-model", about: "the model that writes the code", kind: "model", unset: "harness-model", effect: "next-pulse" },
|
|
61
61
|
{ key: "judge-model", about: "the judge and the test review of a conformance run", kind: "model", unset: "coding-model", effect: "next-pulse" },
|
|
62
62
|
{ key: "module", about: "the .plain file turri regenerate builds when none is named", kind: "path", unset: "the folder's .plain files", effect: "next-regenerate", projectOnly: true },
|
|
63
|
-
{ key: "conformance-tests", about: "which functional specs get conformance tests", kind: "choice", options: ["all", "chosen", "module", "false"], unset: "all, where a module has test reqs", effect: "next-plan" },
|
|
64
|
-
{ key: "conformance-budget", about: "under conformance-tests: chosen or module, how many may be chosen - a count or a share", kind: "budget", options: ["10%", "30%", "50%", "5", "10"], unset: "no limit", effect: "next-plan" },
|
|
65
63
|
{ key: "review", about: "whether the code and its tests are reviewed once they pass", kind: "boolean", unset: "true", effect: "next-pulse" },
|
|
66
64
|
{ key: "mutation-testing", about: "whether the coding agent and the reviewer can put a bug in the code for one test run (can_it_fail)", kind: "boolean", unset: "true", effect: "next-pulse" },
|
|
67
65
|
{ key: "allow-to-stop-jobs", about: "whether turri stops a running pulse the ***plain has moved on from", kind: "boolean", unset: "true", effect: "now" },
|
|
68
66
|
{ key: "release-after-pulse", about: "whether every pulse that lands code releases it", kind: "boolean", unset: "false", effect: "next-landing" },
|
|
69
67
|
{ key: "sentinel", about: "whether a chat of its own checks every finished pulse, tests the release, and tells you what is wrong - ask: you are asked before it first opens", kind: "choice", options: ["ask", "true", "false"], unset: "ask", effect: "next-landing" },
|
|
68
|
+
{ key: "test-advisor", about: "whether turri checks each new or changed functional spec with no scenarios in the background, to see whether it needs scenarios - on a yes, the chat writes them", kind: "boolean", unset: "true", effect: "now" },
|
|
69
|
+
{ key: "conformance-tests", about: "whether functional specs' scenarios are written and conformance tested - false: none, the test advisor and conform off", kind: "boolean", unset: "false", effect: "now" },
|
|
70
|
+
{ key: "test-dir", about: "the folder of the test plain files, a folder per module in it, by path from the project root", kind: "path", unset: "tests", effect: "now" },
|
|
71
|
+
{ key: "base-folder", about: "a folder a codebase that requires no other module starts from, by path from the project root - code to build on, files to use, copied in once", kind: "path", unset: "none: it starts empty", effect: "next-pulse" },
|
|
70
72
|
{ key: "unittests-script", about: "the unit testing script, by path from the project root", kind: "path", unset: "the one run_unittests*.sh found", effect: "next-test-run" },
|
|
71
73
|
{ key: "conformance-tests-script", about: "the conformance testing script, by path from the project root", kind: "path", unset: "the one run_conformance_tests*.sh found", effect: "next-test-run" },
|
|
72
74
|
{ key: "prepare-environment-script", about: "run on the build before every conformance testing script run, by path from the project root - optional", kind: "path", unset: "the one prepare_environment*.sh found, else none", effect: "next-test-run" },
|
|
@@ -128,14 +130,6 @@ export function parseValue(setting, typed, known) {
|
|
|
128
130
|
return { error: `${setting.key} is a whole number of at least ${setting.min ?? 0}.` };
|
|
129
131
|
return { value: number };
|
|
130
132
|
}
|
|
131
|
-
case "budget": {
|
|
132
|
-
if (/^\d+$/.test(text))
|
|
133
|
-
return { value: Number(text) };
|
|
134
|
-
const share = /^(\d+(?:\.\d+)?)\s*%$/.exec(text);
|
|
135
|
-
if (share !== null && Number(share[1]) <= 100)
|
|
136
|
-
return { value: `${share[1]}%` };
|
|
137
|
-
return { error: `${setting.key} is a count, such as 5, or a share, such as 30%.` };
|
|
138
|
-
}
|
|
139
133
|
case "model": {
|
|
140
134
|
const { model, thinking } = splitModelSpec(text);
|
|
141
135
|
const colon = text.lastIndexOf(":");
|
|
@@ -351,7 +345,7 @@ export function writeSetting(dir, key, value) {
|
|
|
351
345
|
writeFileSync(join(dir, CONFIG_FILE), text);
|
|
352
346
|
return text;
|
|
353
347
|
}
|
|
354
|
-
/** The files a path setting is offered: the testing scripts in the root and test_scripts/,
|
|
348
|
+
/** The files a path setting is offered: the testing scripts in the root and test_scripts/, the .plain files of the folder, or - the test folder - its folders. */
|
|
355
349
|
export function pathOptions(dir, key) {
|
|
356
350
|
const list = (folder, test) => {
|
|
357
351
|
try {
|
|
@@ -365,6 +359,16 @@ export function pathOptions(dir, key) {
|
|
|
365
359
|
};
|
|
366
360
|
if (key === "module")
|
|
367
361
|
return list("", (name) => name.endsWith(".plain")).sort();
|
|
362
|
+
if (key === "test-dir" || key === "base-folder") {
|
|
363
|
+
const own = key === "test-dir" ? ["tests"] : [];
|
|
364
|
+
try {
|
|
365
|
+
const folders = readdirSync(dir).filter((name) => !name.startsWith(".") && name !== "plain_modules" && name !== "node_modules" && statSync(join(dir, name)).isDirectory());
|
|
366
|
+
return [...new Set([...own, ...folders])].sort();
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
return own;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
368
372
|
const prefix = key === "unittests-script" ? "run_unittests" : key === "conformance-tests-script" ? "run_conformance_tests" : "prepare_environment";
|
|
369
373
|
const script = (name) => name.startsWith(prefix) && /\.(sh|ps1)$/.test(name);
|
|
370
374
|
return [...list("", script), ...list("test_scripts", script)].sort();
|
package/dist/config.d.ts
CHANGED
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
*
|
|
6
6
|
* ```yaml
|
|
7
7
|
* module: prism_cli.plain # what `turri regenerate` builds by default
|
|
8
|
+
* conformance-tests: false # whether scenarios are written and conformance tested - false: none, the test advisor off (default: false)
|
|
9
|
+
* test-dir: tests # where the test plain files are, a folder per module: tests/<module>/ (default: tests)
|
|
10
|
+
* base-folder: existing-app # a codebase that requires none starts as a copy of it - code to build on, assets to use
|
|
8
11
|
* harness-model: # the model you chat with in `turri`
|
|
9
12
|
* model: anthropic/claude-opus-5-5
|
|
10
13
|
* thinking: high
|
|
@@ -13,12 +16,11 @@
|
|
|
13
16
|
* thinking: medium
|
|
14
17
|
* judge-model: # the judge and the test review (default: coding-model)
|
|
15
18
|
* model: google/gemini-3.1-pro
|
|
16
|
-
* conformance-tests: chosen # all, chosen (those with acceptance tests, and those the chooser picks after each pulse), module (the chooser picks, and plans, once the module is regenerated) or false (default: false)
|
|
17
|
-
* conformance-budget: 30% # under chosen or module: how many functional specs a module may have chosen, beside those with acceptance tests - a count or a share (default: no limit)
|
|
18
19
|
* review: false # review the code and its tests once they pass (default: true)
|
|
19
20
|
* mutation-testing: false # give the coding agent and the reviewer can_it_fail (default: true)
|
|
20
21
|
* allow-to-stop-jobs: false # stop a running job the spec moved on from (default: true)
|
|
21
22
|
* release-after-pulse: true # release what each pulse lands, as its last stage, before the next pulse (default: false)
|
|
23
|
+
* test-advisor: false # check each new or changed functional spec with no scenarios for whether it needs them - on a yes, the chat writes them (default: true)
|
|
22
24
|
* sentinel: true # a chat of its own every finished pulse goes to, which tests the release and tells you what is wrong: true, false, or ask - the person asked before it first opens in a session (default: ask)
|
|
23
25
|
* rules-off: [integrations] # ***plain rules to leave out of the prompts, by name (default: none)
|
|
24
26
|
* unittests-script: test_scripts/run_unittests.sh # the testing scripts - see test-scripts.ts
|
|
@@ -126,9 +128,10 @@ export interface ModelChoice {
|
|
|
126
128
|
/**
|
|
127
129
|
* The agents turri starts, by what they do - each can be given its own model, thinking and turn limit (`models:`).
|
|
128
130
|
* The code fixer of a conformance run and the repair agent are coding agents; the unit-test and conformance arbiters
|
|
129
|
-
* are both `arbiter`.
|
|
131
|
+
* are both `arbiter`. The test advisor's calls - classifying a functional spec, its probes, its readers, its verifier -
|
|
132
|
+
* are `advisor`.
|
|
130
133
|
*/
|
|
131
|
-
export declare const AGENT_ROLES: readonly ["chat", "sentinel", "
|
|
134
|
+
export declare const AGENT_ROLES: readonly ["chat", "sentinel", "planner", "diagnosis", "release", "coding", "conformance", "explorer", "reviewer", "test-reviewer", "judge", "arbiter", "debugger", "advisor"];
|
|
132
135
|
export type AgentRole = (typeof AGENT_ROLES)[number];
|
|
133
136
|
/**
|
|
134
137
|
* How hard each role thinks when nothing names a level - not the config's `models:`, nor a `:level` on the model it is
|
|
@@ -165,6 +168,12 @@ export declare function projectModels(config: Pick<ProjectConfig, "harnessModel"
|
|
|
165
168
|
coding?: ModelChoice;
|
|
166
169
|
judge?: ModelChoice;
|
|
167
170
|
};
|
|
171
|
+
/**
|
|
172
|
+
* What a skill run from the command line runs on: the project's harness model, as a skill in the chat runs on the
|
|
173
|
+
* chat's - or its coding model, for a skill that names it (`metadata.model: coding`) - undefined, and pi's default,
|
|
174
|
+
* when the project names none.
|
|
175
|
+
*/
|
|
176
|
+
export declare function skillModel(root: string, role?: "harness" | "coding"): string | undefined;
|
|
168
177
|
/**
|
|
169
178
|
* What the config itself says a role runs on - its own entry, the legacy key that names it (judge-model for the judge
|
|
170
179
|
* and the test review), then `default` (the chat's side: the chat's model instead) - or nothing when it says nothing
|
|
@@ -172,6 +181,11 @@ export declare function projectModels(config: Pick<ProjectConfig, "harnessModel"
|
|
|
172
181
|
* The coding role always runs on what it is given: its config is already in it (projectModels).
|
|
173
182
|
*/
|
|
174
183
|
export declare function roleModel(config: Pick<ProjectConfig, "harnessModel" | "judgeModel" | "models">, role: AgentRole): ModelChoice | undefined;
|
|
184
|
+
/**
|
|
185
|
+
* What the test advisor's calls run on: `models.advisor` - else `default` - and without either the coding
|
|
186
|
+
* model alone, thinking as the role has it (ROLE_THINKING). Undefined when the config names no model at all.
|
|
187
|
+
*/
|
|
188
|
+
export declare function advisorModel(config: ProjectConfig): string | undefined;
|
|
175
189
|
/** How long each turn of a role's agents may take, in milliseconds: its own, `default`'s, `turn-limit:`'s - or undefined, the harness's default. */
|
|
176
190
|
export declare function roleTurnLimitMs(config: Pick<ProjectConfig, "models" | "turnLimit">, role: AgentRole | undefined): number | undefined;
|
|
177
191
|
/** `sentinel:` - on, off, or `ask`: on once the person says so, asked before it first opens in a session. */
|
|
@@ -188,24 +202,6 @@ export interface ProjectConfig {
|
|
|
188
202
|
* the code, the tests or the spec is wrong, and the test review. Unset: the coding model.
|
|
189
203
|
*/
|
|
190
204
|
judgeModel?: ModelChoice;
|
|
191
|
-
/**
|
|
192
|
-
* Whether conformance tests are written and run, and for what. true (`all`): every functional spec the code is built
|
|
193
|
-
* from. "chosen": the ones with acceptance tests, and those the chooser picks from what each code pulse regenerated, as
|
|
194
|
-
* the pulse ends. "module": the same, but the chooser is asked once, when the whole module is regenerated - what to test,
|
|
195
|
-
* and in which pulses. Under both, those the person asks for with conform too, and a choice is kept once its tests land.
|
|
196
|
-
* false: none, unless the person asks. Unset: none, as with false.
|
|
197
|
-
*/
|
|
198
|
-
conformanceTests?: boolean | "chosen" | "module";
|
|
199
|
-
/**
|
|
200
|
-
* Under `conformance-tests: chosen`: how many of a module's functional specs may be chosen for conformance tests, beside
|
|
201
|
-
* those with acceptance tests - a count, or a share of the module's functional specs (rounded up, at least one).
|
|
202
|
-
* Every choice for the module counts, whenever it was made; the person's own conform is not limited. Unset: no limit.
|
|
203
|
-
*/
|
|
204
|
-
conformanceBudget?: {
|
|
205
|
-
count: number;
|
|
206
|
-
} | {
|
|
207
|
-
share: number;
|
|
208
|
-
};
|
|
209
205
|
/**
|
|
210
206
|
* Whether the code and its unit tests - and the conformance tests - are reviewed once they pass: two reviews at
|
|
211
207
|
* most, the second weighed by the arbiter. false: the work goes on once its tests pass. Unset: false.
|
|
@@ -234,6 +230,30 @@ export interface ProjectConfig {
|
|
|
234
230
|
* asked, before it first opens in a session, whether to start it. Unset: ask.
|
|
235
231
|
*/
|
|
236
232
|
sentinel?: SentinelSetting;
|
|
233
|
+
/**
|
|
234
|
+
* Whether the test advisor starts by itself: in the chat and a host, each new or changed functional spec with no
|
|
235
|
+
* scenarios is classified in the background, and on a yes the chat writes its scenarios (docs/test-advisor.md). false
|
|
236
|
+
* turns off only that: the chat's evaluate_tests still works, and asked for scenarios, the chat writes them as before.
|
|
237
|
+
* Unset: true.
|
|
238
|
+
*/
|
|
239
|
+
testAdvisor?: boolean;
|
|
240
|
+
/**
|
|
241
|
+
* The folder of the test plain files, from the project's folder: a functional spec's scenarios are in its test plain
|
|
242
|
+
* file in `<test-dir>/<module>/`. Unset: `tests`.
|
|
243
|
+
*/
|
|
244
|
+
testDir?: string;
|
|
245
|
+
/**
|
|
246
|
+
* Whether functional specs' scenarios are written and conformance tested (conformance-switch.ts). False: none - no
|
|
247
|
+
* conformance pulse, no conformance testing script, the test advisor and the chat's conform and evaluate_tests off; the
|
|
248
|
+
* test plain files there are kept, and not tested. The person asking for tests, or agreeing to the chat's offer, turns it
|
|
249
|
+
* on. Unset: false.
|
|
250
|
+
*/
|
|
251
|
+
conformanceTests?: boolean;
|
|
252
|
+
/**
|
|
253
|
+
* A folder, from the project's folder, that a codebase requiring no other module starts from - a copy of it, once,
|
|
254
|
+
* before its first pulse: code to build on, files to use (src/regenerate/base-folder.ts). Unset: it starts empty.
|
|
255
|
+
*/
|
|
256
|
+
baseFolder?: string;
|
|
237
257
|
/** Path from the root to the unit testing script. */
|
|
238
258
|
unittestsScript?: string;
|
|
239
259
|
/** Path from the root to the conformance testing script. */
|
|
@@ -303,13 +323,15 @@ export declare const CONFIG_KEYS: {
|
|
|
303
323
|
readonly harnessModel: "harness-model";
|
|
304
324
|
readonly codingModel: "coding-model";
|
|
305
325
|
readonly judgeModel: "judge-model";
|
|
306
|
-
readonly conformanceTests: "conformance-tests";
|
|
307
|
-
readonly conformanceBudget: "conformance-budget";
|
|
308
326
|
readonly review: "review";
|
|
309
327
|
readonly mutationTesting: "mutation-testing";
|
|
310
328
|
readonly allowToStopJobs: "allow-to-stop-jobs";
|
|
311
329
|
readonly releaseAfterPulse: "release-after-pulse";
|
|
312
330
|
readonly sentinel: "sentinel";
|
|
331
|
+
readonly testAdvisor: "test-advisor";
|
|
332
|
+
readonly testDir: "test-dir";
|
|
333
|
+
readonly conformanceTests: "conformance-tests";
|
|
334
|
+
readonly baseFolder: "base-folder";
|
|
313
335
|
readonly unittestsScript: "unittests-script";
|
|
314
336
|
readonly conformanceTestsScript: "conformance-tests-script";
|
|
315
337
|
readonly prepareEnvironmentScript: "prepare-environment-script";
|
|
@@ -327,12 +349,6 @@ export declare const CONFIG_KEYS: {
|
|
|
327
349
|
readonly models: "models";
|
|
328
350
|
readonly turnLimit: "turn-limit";
|
|
329
351
|
};
|
|
330
|
-
/** Whether `conformance-tests:` turns the conformance tests on: all (true), chosen or module. Not set, they are off, as with false. */
|
|
331
|
-
export declare function conformanceSwitchedOn(setting: ProjectConfig["conformanceTests"]): boolean;
|
|
332
|
-
/** When the chooser decides which functional specs get conformance tests: after each code pulse, once the module is regenerated, or never - every one, or none. */
|
|
333
|
-
export declare function choosingWhen(setting: ProjectConfig["conformanceTests"]): "pulse" | "module" | undefined;
|
|
334
|
-
/** How many functional specs a module of `count` may have chosen under a budget: the count, or the share rounded up - at least one. */
|
|
335
|
-
export declare function budgetFor(budget: NonNullable<ProjectConfig["conformanceBudget"]>, count: number): number;
|
|
336
352
|
/**
|
|
337
353
|
* The project's config - with a stack's over it, when one is named - or nothing of it when there is no file or it does
|
|
338
354
|
* not parse.
|
|
@@ -340,12 +356,12 @@ export declare function budgetFor(budget: NonNullable<ProjectConfig["conformance
|
|
|
340
356
|
export declare function readProjectConfig(root: string, stack?: string): ProjectConfig;
|
|
341
357
|
/**
|
|
342
358
|
* What a command's own options say of the config's keys - `turri regenerate --harness-model`, `--coding-model`,
|
|
343
|
-
* `--judge-model`, `--
|
|
359
|
+
* `--judge-model`, `--review`, `--mutation-testing` - read as if the file had them: each takes its key's value, and
|
|
344
360
|
* every key keeps its place in the order, so a run is the same as one with them in config.turri.yaml - a `models:`
|
|
345
361
|
* entry still winning over `harness-model`, `coding-model` or `judge-model`. A headless run needs no config file
|
|
346
362
|
* edited. Never set in the conversation.
|
|
347
363
|
*/
|
|
348
|
-
type RunOverrides = Partial<Pick<ProjectConfig, "harnessModel" | "codingModel" | "judgeModel" | "
|
|
364
|
+
type RunOverrides = Partial<Pick<ProjectConfig, "harnessModel" | "codingModel" | "judgeModel" | "review" | "mutationTesting">>;
|
|
349
365
|
/** Megabytes of package caches a project keeps when `cache-keep:` does not say. */
|
|
350
366
|
export declare const DEFAULT_CACHE_KEEP_MB = 4096;
|
|
351
367
|
/**
|
|
@@ -355,10 +371,14 @@ export declare const DEFAULT_CACHE_KEEP_MB = 4096;
|
|
|
355
371
|
export declare function debugMode(project: string): boolean;
|
|
356
372
|
/** Read a command's options as the config's keys for the rest of this process. */
|
|
357
373
|
export declare function overrideConfig(overrides: RunOverrides): void;
|
|
358
|
-
/** `--conformance-tests <value>`: the config's own values - all (or true), chosen, module, false. Undefined for anything else. */
|
|
359
|
-
export declare function conformanceOption(value: string): ProjectConfig["conformanceTests"] | undefined;
|
|
360
374
|
/** `--review <value>`, `--mutation-testing <value>`: the config's own, true or false. Undefined for anything else. */
|
|
361
375
|
export declare function booleanOption(value: string): boolean | undefined;
|
|
376
|
+
/** Where the test plain files are when `test-dir:` does not say. */
|
|
377
|
+
export declare const DEFAULT_TEST_DIR = "tests";
|
|
378
|
+
/** The folder of a module's project's test plain files: `test-dir:` - its stack's over the project's - from the project's folder. */
|
|
379
|
+
export declare function testDirOf(plainFile: string): string;
|
|
362
380
|
/** The config a spec is built with: its project's, with its module's stack over it (`stackForModule`). */
|
|
363
381
|
export declare function configForSpec(plainFile: string): ProjectConfig;
|
|
382
|
+
/** One config file, read, or nothing of it when it is not there or does not parse. */
|
|
383
|
+
export declare function readConfigFile(path: string): ProjectConfig;
|
|
364
384
|
export {};
|
package/dist/config.js
CHANGED
|
@@ -11,6 +11,9 @@ import { projectDirOf } from "./regenerate/paths.js";
|
|
|
11
11
|
*
|
|
12
12
|
* ```yaml
|
|
13
13
|
* module: prism_cli.plain # what `turri regenerate` builds by default
|
|
14
|
+
* conformance-tests: false # whether scenarios are written and conformance tested - false: none, the test advisor off (default: false)
|
|
15
|
+
* test-dir: tests # where the test plain files are, a folder per module: tests/<module>/ (default: tests)
|
|
16
|
+
* base-folder: existing-app # a codebase that requires none starts as a copy of it - code to build on, assets to use
|
|
14
17
|
* harness-model: # the model you chat with in `turri`
|
|
15
18
|
* model: anthropic/claude-opus-5-5
|
|
16
19
|
* thinking: high
|
|
@@ -19,12 +22,11 @@ import { projectDirOf } from "./regenerate/paths.js";
|
|
|
19
22
|
* thinking: medium
|
|
20
23
|
* judge-model: # the judge and the test review (default: coding-model)
|
|
21
24
|
* model: google/gemini-3.1-pro
|
|
22
|
-
* conformance-tests: chosen # all, chosen (those with acceptance tests, and those the chooser picks after each pulse), module (the chooser picks, and plans, once the module is regenerated) or false (default: false)
|
|
23
|
-
* conformance-budget: 30% # under chosen or module: how many functional specs a module may have chosen, beside those with acceptance tests - a count or a share (default: no limit)
|
|
24
25
|
* review: false # review the code and its tests once they pass (default: true)
|
|
25
26
|
* mutation-testing: false # give the coding agent and the reviewer can_it_fail (default: true)
|
|
26
27
|
* allow-to-stop-jobs: false # stop a running job the spec moved on from (default: true)
|
|
27
28
|
* release-after-pulse: true # release what each pulse lands, as its last stage, before the next pulse (default: false)
|
|
29
|
+
* test-advisor: false # check each new or changed functional spec with no scenarios for whether it needs them - on a yes, the chat writes them (default: true)
|
|
28
30
|
* sentinel: true # a chat of its own every finished pulse goes to, which tests the release and tells you what is wrong: true, false, or ask - the person asked before it first opens in a session (default: ask)
|
|
29
31
|
* rules-off: [integrations] # ***plain rules to leave out of the prompts, by name (default: none)
|
|
30
32
|
* unittests-script: test_scripts/run_unittests.sh # the testing scripts - see test-scripts.ts
|
|
@@ -214,9 +216,10 @@ export const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhig
|
|
|
214
216
|
/**
|
|
215
217
|
* The agents turri starts, by what they do - each can be given its own model, thinking and turn limit (`models:`).
|
|
216
218
|
* The code fixer of a conformance run and the repair agent are coding agents; the unit-test and conformance arbiters
|
|
217
|
-
* are both `arbiter`.
|
|
219
|
+
* are both `arbiter`. The test advisor's calls - classifying a functional spec, its probes, its readers, its verifier -
|
|
220
|
+
* are `advisor`.
|
|
218
221
|
*/
|
|
219
|
-
export const AGENT_ROLES = ["chat", "sentinel", "
|
|
222
|
+
export const AGENT_ROLES = ["chat", "sentinel", "planner", "diagnosis", "release", "coding", "conformance", "explorer", "reviewer", "test-reviewer", "judge", "arbiter", "debugger", "advisor"];
|
|
220
223
|
/**
|
|
221
224
|
* How hard each role thinks when nothing names a level - not the config's `models:`, nor a `:level` on the model it is
|
|
222
225
|
* given. The agents that do the work - write the code and the tests, explore, release - think little: they work from a
|
|
@@ -228,19 +231,19 @@ export const ROLE_THINKING = {
|
|
|
228
231
|
conformance: "low",
|
|
229
232
|
explorer: "low",
|
|
230
233
|
release: "low",
|
|
234
|
+
advisor: "low",
|
|
231
235
|
reviewer: "medium",
|
|
232
236
|
"test-reviewer": "medium",
|
|
233
237
|
judge: "medium",
|
|
234
238
|
arbiter: "medium",
|
|
235
239
|
debugger: "medium",
|
|
236
240
|
planner: "medium",
|
|
237
|
-
chooser: "medium",
|
|
238
241
|
diagnosis: "medium",
|
|
239
242
|
};
|
|
240
243
|
/** The roles on the conversation's side: without their own entry they take the chat's model, not `default`. */
|
|
241
244
|
// The release is not: it follows steps - a script, a start command - and runs on the coding model, thinking low. Nor
|
|
242
245
|
// is the diagnosis: a post-mortem of a job that failed, read by the person - it runs on the coding model, thinking medium.
|
|
243
|
-
const CHAT_SIDE = ["chat", "sentinel", "
|
|
246
|
+
const CHAT_SIDE = ["chat", "sentinel", "planner"];
|
|
244
247
|
function isThinkingLevel(value) {
|
|
245
248
|
return typeof value === "string" && THINKING_LEVELS.includes(value);
|
|
246
249
|
}
|
|
@@ -295,6 +298,14 @@ export function projectModels(config) {
|
|
|
295
298
|
const codingModel = coding?.model !== undefined ? { model: coding.model } : undefined;
|
|
296
299
|
return { harness, coding, judge: inheritModel(choiceOf(models.judge), inheritModel(config.judgeModel, inheritModel(choiceOf(models.default), codingModel))) };
|
|
297
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* What a skill run from the command line runs on: the project's harness model, as a skill in the chat runs on the
|
|
303
|
+
* chat's - or its coding model, for a skill that names it (`metadata.model: coding`) - undefined, and pi's default,
|
|
304
|
+
* when the project names none.
|
|
305
|
+
*/
|
|
306
|
+
export function skillModel(root, role = "harness") {
|
|
307
|
+
return modelSpec(projectModels(readProjectConfig(root, stackOf(root)))[role]);
|
|
308
|
+
}
|
|
298
309
|
/** A role entry's model and thinking alone. */
|
|
299
310
|
function choiceOf(entry) {
|
|
300
311
|
if (entry === undefined || (entry.model === undefined && entry.thinking === undefined))
|
|
@@ -320,6 +331,14 @@ export function roleModel(config, role) {
|
|
|
320
331
|
const legacy = role === "judge" || role === "test-reviewer" ? config.judgeModel : undefined;
|
|
321
332
|
return inheritModel(own, inheritModel(legacy, choiceOf(models.default)));
|
|
322
333
|
}
|
|
334
|
+
/**
|
|
335
|
+
* What the test advisor's calls run on: `models.advisor` - else `default` - and without either the coding
|
|
336
|
+
* model alone, thinking as the role has it (ROLE_THINKING). Undefined when the config names no model at all.
|
|
337
|
+
*/
|
|
338
|
+
export function advisorModel(config) {
|
|
339
|
+
const coding = projectModels(config).coding?.model;
|
|
340
|
+
return modelSpec(inheritModel(roleModel(config, "advisor"), coding !== undefined ? { model: coding } : undefined));
|
|
341
|
+
}
|
|
323
342
|
/** How long each turn of a role's agents may take, in milliseconds: its own, `default`'s, `turn-limit:`'s - or undefined, the harness's default. */
|
|
324
343
|
export function roleTurnLimitMs(config, role) {
|
|
325
344
|
const models = config.models ?? {};
|
|
@@ -377,13 +396,15 @@ export const CONFIG_KEYS = {
|
|
|
377
396
|
harnessModel: "harness-model",
|
|
378
397
|
codingModel: "coding-model",
|
|
379
398
|
judgeModel: "judge-model",
|
|
380
|
-
conformanceTests: "conformance-tests",
|
|
381
|
-
conformanceBudget: "conformance-budget",
|
|
382
399
|
review: "review",
|
|
383
400
|
mutationTesting: "mutation-testing",
|
|
384
401
|
allowToStopJobs: "allow-to-stop-jobs",
|
|
385
402
|
releaseAfterPulse: "release-after-pulse",
|
|
386
403
|
sentinel: "sentinel",
|
|
404
|
+
testAdvisor: "test-advisor",
|
|
405
|
+
testDir: "test-dir",
|
|
406
|
+
conformanceTests: "conformance-tests",
|
|
407
|
+
baseFolder: "base-folder",
|
|
387
408
|
unittestsScript: "unittests-script",
|
|
388
409
|
conformanceTestsScript: "conformance-tests-script",
|
|
389
410
|
prepareEnvironmentScript: "prepare-environment-script",
|
|
@@ -404,34 +425,6 @@ export const CONFIG_KEYS = {
|
|
|
404
425
|
function whatScriptsRunOn(value) {
|
|
405
426
|
return value === "copy" || value === "in-place" ? value : undefined;
|
|
406
427
|
}
|
|
407
|
-
/** `conformance-tests:` - true or all, chosen, module, false. Anything else is not read. */
|
|
408
|
-
function conformanceSetting(value) {
|
|
409
|
-
if (typeof value === "boolean")
|
|
410
|
-
return value;
|
|
411
|
-
const word = typeof value === "string" ? value.trim().toLowerCase() : undefined;
|
|
412
|
-
return word === "all" ? true : word === "chosen" ? "chosen" : word === "module" ? "module" : word === "false" ? false : word === "true" ? true : undefined;
|
|
413
|
-
}
|
|
414
|
-
/** Whether `conformance-tests:` turns the conformance tests on: all (true), chosen or module. Not set, they are off, as with false. */
|
|
415
|
-
export function conformanceSwitchedOn(setting) {
|
|
416
|
-
return setting === true || setting === "chosen" || setting === "module";
|
|
417
|
-
}
|
|
418
|
-
/** When the chooser decides which functional specs get conformance tests: after each code pulse, once the module is regenerated, or never - every one, or none. */
|
|
419
|
-
export function choosingWhen(setting) {
|
|
420
|
-
return setting === "chosen" ? "pulse" : setting === "module" ? "module" : undefined;
|
|
421
|
-
}
|
|
422
|
-
/** `conformance-budget:` - a whole number, or a share such as `30%`. Anything else is not read. */
|
|
423
|
-
function budgetSetting(value) {
|
|
424
|
-
if (typeof value === "number" && Number.isInteger(value) && value >= 0)
|
|
425
|
-
return { count: value };
|
|
426
|
-
const share = typeof value === "string" ? /^\s*(\d+(?:\.\d+)?)\s*%\s*$/.exec(value) : null;
|
|
427
|
-
if (share !== null && Number(share[1]) <= 100)
|
|
428
|
-
return { share: Number(share[1]) / 100 };
|
|
429
|
-
return undefined;
|
|
430
|
-
}
|
|
431
|
-
/** How many functional specs a module of `count` may have chosen under a budget: the count, or the share rounded up - at least one. */
|
|
432
|
-
export function budgetFor(budget, count) {
|
|
433
|
-
return "count" in budget ? budget.count : Math.max(1, Math.ceil(budget.share * count));
|
|
434
|
-
}
|
|
435
428
|
function text(value) {
|
|
436
429
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : undefined;
|
|
437
430
|
}
|
|
@@ -483,10 +476,6 @@ export function debugMode(project) {
|
|
|
483
476
|
export function overrideConfig(overrides) {
|
|
484
477
|
runOverrides = { ...overrides };
|
|
485
478
|
}
|
|
486
|
-
/** `--conformance-tests <value>`: the config's own values - all (or true), chosen, module, false. Undefined for anything else. */
|
|
487
|
-
export function conformanceOption(value) {
|
|
488
|
-
return conformanceSetting(value);
|
|
489
|
-
}
|
|
490
479
|
/** `--review <value>`, `--mutation-testing <value>`: the config's own, true or false. Undefined for anything else. */
|
|
491
480
|
export function booleanOption(value) {
|
|
492
481
|
const word = value.trim().toLowerCase();
|
|
@@ -530,13 +519,19 @@ function agentEnvSetting(value) {
|
|
|
530
519
|
function withoutUndefined(config) {
|
|
531
520
|
return Object.fromEntries(Object.entries(config).filter(([, value]) => value !== undefined));
|
|
532
521
|
}
|
|
522
|
+
/** Where the test plain files are when `test-dir:` does not say. */
|
|
523
|
+
export const DEFAULT_TEST_DIR = "tests";
|
|
524
|
+
/** The folder of a module's project's test plain files: `test-dir:` - its stack's over the project's - from the project's folder. */
|
|
525
|
+
export function testDirOf(plainFile) {
|
|
526
|
+
return resolve(projectDirOf(resolve(plainFile)), configForSpec(plainFile).testDir ?? DEFAULT_TEST_DIR);
|
|
527
|
+
}
|
|
533
528
|
/** The config a spec is built with: its project's, with its module's stack over it (`stackForModule`). */
|
|
534
529
|
export function configForSpec(plainFile) {
|
|
535
530
|
const root = projectDirOf(resolve(plainFile));
|
|
536
531
|
return readProjectConfig(root, stackForModule(plainFile));
|
|
537
532
|
}
|
|
538
533
|
/** One config file, read, or nothing of it when it is not there or does not parse. */
|
|
539
|
-
function readConfigFile(path) {
|
|
534
|
+
export function readConfigFile(path) {
|
|
540
535
|
let parsed;
|
|
541
536
|
try {
|
|
542
537
|
if (!statSync(path).isFile())
|
|
@@ -549,19 +544,20 @@ function readConfigFile(path) {
|
|
|
549
544
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
550
545
|
return {};
|
|
551
546
|
const raw = Object.fromEntries(Object.entries(parsed).map(([key, value]) => [key.replace(/_/g, "-"), value]));
|
|
552
|
-
const conformance = raw[CONFIG_KEYS.conformanceTests];
|
|
553
547
|
return {
|
|
554
548
|
module: text(raw[CONFIG_KEYS.module]),
|
|
555
549
|
harnessModel: modelChoice(raw[CONFIG_KEYS.harnessModel]),
|
|
556
550
|
codingModel: modelChoice(raw[CONFIG_KEYS.codingModel]) ?? modelChoice(raw.model),
|
|
557
551
|
judgeModel: modelChoice(raw[CONFIG_KEYS.judgeModel]),
|
|
558
|
-
conformanceTests: conformanceSetting(conformance),
|
|
559
|
-
conformanceBudget: budgetSetting(raw[CONFIG_KEYS.conformanceBudget]),
|
|
560
552
|
review: typeof raw[CONFIG_KEYS.review] === "boolean" ? raw[CONFIG_KEYS.review] : undefined,
|
|
561
553
|
mutationTesting: typeof raw[CONFIG_KEYS.mutationTesting] === "boolean" ? raw[CONFIG_KEYS.mutationTesting] : undefined,
|
|
562
554
|
allowToStopJobs: typeof raw[CONFIG_KEYS.allowToStopJobs] === "boolean" ? raw[CONFIG_KEYS.allowToStopJobs] : undefined,
|
|
563
555
|
releaseAfterPulse: typeof raw[CONFIG_KEYS.releaseAfterPulse] === "boolean" ? raw[CONFIG_KEYS.releaseAfterPulse] : undefined,
|
|
564
556
|
sentinel: typeof raw[CONFIG_KEYS.sentinel] === "boolean" || raw[CONFIG_KEYS.sentinel] === "ask" ? raw[CONFIG_KEYS.sentinel] : undefined,
|
|
557
|
+
testAdvisor: typeof raw[CONFIG_KEYS.testAdvisor] === "boolean" ? raw[CONFIG_KEYS.testAdvisor] : undefined,
|
|
558
|
+
testDir: text(raw[CONFIG_KEYS.testDir]),
|
|
559
|
+
conformanceTests: typeof raw[CONFIG_KEYS.conformanceTests] === "boolean" ? raw[CONFIG_KEYS.conformanceTests] : undefined,
|
|
560
|
+
baseFolder: text(raw[CONFIG_KEYS.baseFolder]),
|
|
565
561
|
unittestsScript: text(raw[CONFIG_KEYS.unittestsScript]),
|
|
566
562
|
conformanceTestsScript: text(raw[CONFIG_KEYS.conformanceTestsScript]),
|
|
567
563
|
prepareEnvironmentScript: text(raw[CONFIG_KEYS.prepareEnvironmentScript]),
|
package/dist/conform-cli.js
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
import { parseArgs } from "./cli-options.js";
|
|
2
2
|
import { headlessOptions, runLoop } from "./loop-cli.js";
|
|
3
|
-
const USAGE = `usage: turri conform <file.plain> [
|
|
3
|
+
const USAGE = `usage: turri conform <file.plain> [module:func-id ...] [options]
|
|
4
4
|
|
|
5
|
-
Writes and runs the black-box conformance tests of a module's functional specs - those named,
|
|
6
|
-
every one - on the code as it is built, as the chat's conform does
|
|
7
|
-
conformance
|
|
8
|
-
module inherits, a failure fixed in the test or the code, whichever is wrong.
|
|
9
|
-
|
|
5
|
+
Writes and runs the black-box conformance tests of a module's functional specs - those named, each
|
|
6
|
+
as module:func-id, or every one with scenarios - on the code as it is built, as the chat's conform does:
|
|
7
|
+
exactly their conformance and acceptance scenarios, following the spec's test reqs, with the whole suite
|
|
8
|
+
the module inherits, a failure fixed in the test or the code, whichever is wrong. A functional spec with
|
|
9
|
+
no scenarios is refused: write them first. So is a module with no test reqs, or no conformance testing
|
|
10
|
+
script for its stack: the refusal names the next step. Every functional spec tested goes in one pulse,
|
|
11
|
+
as far as the size guardrail lets.
|
|
10
12
|
|
|
11
13
|
--one-by-one a pulse a functional spec instead
|
|
12
|
-
--harness-model <p/id> config.turri.yaml's harness-model for this run: the planner,
|
|
14
|
+
--harness-model <p/id> config.turri.yaml's harness-model for this run: the planner, a diagnosis
|
|
13
15
|
--coding-model <p/id> its coding-model, --model too: the agents that build
|
|
14
16
|
--judge-model <p/id> its judge-model: the judge and the test review
|
|
15
17
|
--review <true|false> its review: whether the code and its tests are reviewed once they pass
|
|
16
18
|
--build-dir <dir> as the run ends, export the code there (see turri regenerate --help)
|
|
17
19
|
--report <file.json> write a report of the run there (see turri regenerate --help)`;
|
|
18
20
|
const { positional, options } = parseArgs(process.argv.slice(2), ["--one-by-one"], USAGE, ["--build-dir", "--report", "--harness-model", "--judge-model", "--review"]);
|
|
19
|
-
const { report, buildDir } = headlessOptions(options
|
|
20
|
-
const [plainFile, ...
|
|
21
|
+
const { report, buildDir } = headlessOptions(options);
|
|
22
|
+
const [plainFile, ...funcIds] = positional;
|
|
21
23
|
if (plainFile === undefined) {
|
|
22
24
|
console.error(USAGE);
|
|
23
25
|
process.exit(1);
|
|
@@ -28,7 +30,7 @@ runLoop({
|
|
|
28
30
|
...(report !== undefined ? { report } : {}),
|
|
29
31
|
command: ["conform", ...process.argv.slice(2)],
|
|
30
32
|
ask: (loop) => loop.conformance(plainFile, {
|
|
31
|
-
...(
|
|
33
|
+
...(funcIds.length > 0 ? { funcIds } : {}),
|
|
32
34
|
...(options["one-by-one"] !== undefined ? { separately: true } : {}),
|
|
33
35
|
}),
|
|
34
36
|
}).catch((error) => {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
/**
|
|
3
|
+
* Whether a project's functional specs are conformance tested: `conformance-tests:` in its config, a stack's own over the
|
|
4
|
+
* project's, false when unset. Off, nothing of conformance testing runs - no conformance pulse, no conformance testing
|
|
5
|
+
* script, the test advisor and the chat's conform and evaluate_tests off; the test plain files there are kept, and not
|
|
6
|
+
* tested. The chat always knows it, and how they are turned on: the person asking for tests, or agreeing to the chat's
|
|
7
|
+
* offer of them, turns them on - for this session and the next, written into the config.
|
|
8
|
+
*/
|
|
9
|
+
/** The chat's tools that run conformance testing: there while the tests are on. */
|
|
10
|
+
export declare const CONFORMANCE_TOOLS: string[];
|
|
11
|
+
/** The chat's tool that turns them on: there while they are off. */
|
|
12
|
+
export declare const TURN_ON_TOOL = "turn_on_conformance_tests";
|
|
13
|
+
/** Whether a module's functional specs are conformance tested: its stack's `conformance-tests:` over the project's. */
|
|
14
|
+
export declare function conformanceTestsOn(plainFile: string): boolean;
|
|
15
|
+
/** Whether the project conformance tests anything: its own config, or a stack's - for the chat's tools, which are the project's. */
|
|
16
|
+
export declare function conformanceTestsOnIn(project: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Turn conformance testing on: `conformance-tests: true` written where the module's value comes from - its stack's file
|
|
19
|
+
* when that names the key, else config.turri.yaml - and in effect at once. Says which file.
|
|
20
|
+
*/
|
|
21
|
+
export declare function turnOnConformanceTests(project: string, plainFile?: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* What the chat is told of conformance testing, every turn: what it is, whether it is on here, and - off - how it is
|
|
24
|
+
* turned on, and that it may offer it.
|
|
25
|
+
*/
|
|
26
|
+
export declare function conformanceBlock(on: boolean): string;
|
|
27
|
+
/**
|
|
28
|
+
* turn_on_conformance_tests: the chat turns conformance testing on, the person having asked for it or agreed to it.
|
|
29
|
+
* `turnOn` is the session's (extension.ts `turnOnConformance`): the setting written, every chat's tools switched - the
|
|
30
|
+
* file written, from the project.
|
|
31
|
+
*/
|
|
32
|
+
export declare function turnOnConformanceTestsTool(options: {
|
|
33
|
+
turnOn: (plainFile?: string) => string;
|
|
34
|
+
}): ToolDefinition;
|