@turri-dev/cli 0.1.27 → 0.1.28-next.d5f2680
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/advisor-chat.d.ts +63 -0
- package/dist/advisor-chat.js +290 -0
- package/dist/background-skills.d.ts +53 -0
- package/dist/background-skills.js +121 -0
- package/dist/bedrock-region.d.ts +66 -0
- package/dist/bedrock-region.js +144 -0
- package/dist/btw.d.ts +1 -1
- package/dist/btw.js +1 -1
- package/dist/change-plain-cli.js +20 -13
- package/dist/chat-idle.d.ts +7 -0
- package/dist/chat-idle.js +20 -0
- package/dist/chats.d.ts +10 -0
- package/dist/chats.js +23 -0
- package/dist/cli-options.d.ts +1 -2
- package/dist/cli-options.js +2 -7
- package/dist/cli.js +11 -3
- package/dist/config-command.d.ts +14 -0
- package/dist/config-command.js +35 -15
- package/dist/config-edit.d.ts +3 -3
- package/dist/config-edit.js +16 -12
- package/dist/config.d.ts +54 -34
- package/dist/config.js +40 -44
- package/dist/conform-cli.js +12 -10
- package/dist/conformance-switch.d.ts +34 -0
- package/dist/conformance-switch.js +108 -0
- package/dist/cultivate-cli.js +15 -5
- package/dist/drift-cli.js +2 -0
- package/dist/extension.d.ts +15 -0
- package/dist/extension.js +260 -83
- package/dist/host-session.d.ts +26 -0
- package/dist/host-session.js +30 -2
- package/dist/host.d.ts +5 -2
- package/dist/host.js +7 -1
- package/dist/init-config.d.ts +1 -1
- package/dist/init-config.js +20 -11
- package/dist/loop-cli.d.ts +3 -3
- package/dist/loop-cli.js +13 -16
- package/dist/loop-tools.js +18 -10
- package/dist/model-check.d.ts +8 -3
- package/dist/model-check.js +13 -8
- package/dist/new-project.js +12 -8
- package/dist/{validate-cli.js → parse-cli.js} +11 -5
- package/dist/parse-tool.d.ts +9 -0
- package/dist/parse-tool.js +33 -0
- package/dist/pi-launch.js +1 -1
- package/dist/plain/check.d.ts +53 -6
- package/dist/plain/check.js +217 -24
- package/dist/plain/concepts.d.ts +8 -0
- package/dist/plain/concepts.js +66 -23
- package/dist/plain/cycles.d.ts +21 -0
- package/dist/plain/cycles.js +190 -0
- package/dist/plain/errors.d.ts +4 -0
- package/dist/plain/errors.js +7 -0
- package/dist/plain/files.d.ts +18 -1
- package/dist/plain/files.js +39 -2
- package/dist/plain/graph.d.ts +33 -4
- package/dist/plain/graph.js +60 -12
- package/dist/plain/highlight.d.ts +3 -2
- package/dist/plain/highlight.js +4 -3
- package/dist/plain/index.d.ts +8 -5
- package/dist/plain/index.js +8 -5
- package/dist/plain/liquid.js +1 -6
- package/dist/plain/markdown.d.ts +32 -3
- package/dist/plain/markdown.js +146 -24
- package/dist/plain/module-concepts.js +2 -2
- package/dist/plain/parser.d.ts +83 -28
- package/dist/plain/parser.js +381 -260
- package/dist/plain/plain.tmLanguage.json +29 -3
- package/dist/plain/project.d.ts +48 -0
- package/dist/plain/project.js +155 -0
- package/dist/plain/spec.d.ts +90 -28
- package/dist/plain/spec.js +107 -133
- package/dist/plain/test-plain-file.d.ts +59 -0
- package/dist/plain/test-plain-file.js +232 -0
- package/dist/regenerate/activity.d.ts +20 -9
- package/dist/regenerate/activity.js +11 -4
- package/dist/regenerate/advisor-records.d.ts +93 -0
- package/dist/regenerate/advisor-records.js +110 -0
- package/dist/regenerate/advisor-runs.d.ts +87 -0
- package/dist/regenerate/advisor-runs.js +327 -0
- package/dist/regenerate/base-folder.d.ts +68 -0
- package/dist/regenerate/base-folder.js +168 -0
- package/dist/regenerate/cases.d.ts +9 -6
- package/dist/regenerate/cases.js +70 -14
- package/dist/regenerate/change-view.d.ts +8 -3
- package/dist/regenerate/change-view.js +71 -22
- package/dist/regenerate/chunk-plan.d.ts +36 -15
- package/dist/regenerate/chunk-plan.js +165 -59
- package/dist/regenerate/conform.d.ts +3 -0
- package/dist/regenerate/conform.js +6 -5
- package/dist/regenerate/conformance-agents.d.ts +18 -39
- package/dist/regenerate/conformance-agents.js +60 -88
- package/dist/regenerate/conformance.d.ts +23 -13
- package/dist/regenerate/conformance.js +119 -82
- package/dist/regenerate/diff-view.d.ts +1 -1
- package/dist/regenerate/diff-view.js +20 -4
- package/dist/regenerate/drift.d.ts +47 -15
- package/dist/regenerate/drift.js +101 -30
- package/dist/regenerate/jobs.d.ts +2 -2
- package/dist/regenerate/jobs.js +1 -1
- package/dist/regenerate/ledger.d.ts +19 -0
- package/dist/regenerate/loop.d.ts +62 -43
- package/dist/regenerate/loop.js +472 -341
- package/dist/regenerate/paths.d.ts +4 -0
- package/dist/regenerate/paths.js +7 -1
- package/dist/regenerate/plain-palette.js +2 -0
- package/dist/regenerate/prompt.d.ts +57 -19
- package/dist/regenerate/prompt.js +157 -122
- package/dist/regenerate/records.d.ts +43 -12
- package/dist/regenerate/records.js +102 -88
- package/dist/regenerate/regenerate.js +29 -11
- package/dist/regenerate/regression.d.ts +4 -4
- package/dist/regenerate/regression.js +14 -10
- package/dist/regenerate/renames.d.ts +42 -0
- package/dist/regenerate/renames.js +185 -0
- package/dist/regenerate/requires.d.ts +1 -1
- package/dist/regenerate/requires.js +10 -3
- package/dist/regenerate/resources.d.ts +5 -3
- package/dist/regenerate/resources.js +4 -4
- package/dist/regenerate/scripts-being-written.d.ts +19 -0
- package/dist/regenerate/scripts-being-written.js +30 -0
- package/dist/regenerate/spec-map-view.d.ts +2 -2
- package/dist/regenerate/spec-map-view.js +46 -15
- package/dist/regenerate/spec-map.d.ts +27 -5
- package/dist/regenerate/spec-map.js +92 -60
- package/dist/regenerate/spec-steps.d.ts +48 -5
- package/dist/regenerate/spec-steps.js +213 -28
- package/dist/regenerate/state.d.ts +4 -3
- package/dist/regenerate/stop-report.d.ts +1 -1
- package/dist/regenerate/stop-report.js +10 -10
- package/dist/regenerate/test-advisor.d.ts +101 -0
- package/dist/regenerate/test-advisor.js +379 -0
- package/dist/regenerate/test-kinds.d.ts +71 -28
- package/dist/regenerate/test-kinds.js +110 -63
- package/dist/regenerate/test-scripts.d.ts +2 -0
- package/dist/regenerate/test-scripts.js +4 -0
- package/dist/regenerate/testing-steps.d.ts +41 -0
- package/dist/regenerate/testing-steps.js +110 -0
- package/dist/regenerate/testing.d.ts +1 -1
- package/dist/regenerate/testing.js +5 -4
- package/dist/regenerate/unit-review.d.ts +1 -1
- package/dist/regenerate/unit-review.js +3 -3
- package/dist/regenerate-cli.js +11 -12
- package/dist/release-agent.js +4 -0
- package/dist/release-cli.js +2 -0
- package/dist/release-tools.js +2 -0
- package/dist/run-report.d.ts +2 -2
- package/dist/run-report.js +4 -3
- package/dist/self-invocation.d.ts +1 -1
- package/dist/self-invocation.js +1 -1
- package/dist/sentinel.js +1 -1
- package/dist/setup.d.ts +10 -0
- package/dist/setup.js +52 -4
- package/dist/skill.d.ts +10 -0
- package/dist/skill.js +6 -0
- package/dist/skills.js +3 -1
- package/dist/spec-tools.js +21 -31
- package/dist/test-plain-files.d.ts +41 -0
- package/dist/test-plain-files.js +177 -0
- package/docs/README.md +3 -1
- package/docs/authoring-plain.md +46 -13
- package/docs/chats.md +3 -1
- package/docs/config.md +20 -15
- package/docs/deploy.md +1 -1
- package/docs/development.md +2 -1
- package/docs/headless.md +15 -18
- package/docs/hosting.md +28 -12
- package/docs/installation.md +1 -0
- package/docs/parser.md +88 -27
- package/docs/regenerating.md +87 -52
- package/docs/sentinel.md +1 -1
- package/docs/skills-and-gates.md +3 -1
- package/docs/test-advisor.md +110 -0
- package/docs/theming.md +1 -1
- package/docs/using.md +17 -15
- package/genome/rules/bullet-continuation.md +8 -8
- package/genome/rules/concise-specs-examples.md +111 -80
- package/genome/rules/concise-specs-integration-examples.md +56 -41
- package/genome/rules/concise-specs.md +17 -16
- package/genome/rules/definitions.md +5 -5
- package/genome/rules/examples/integration-embedded-testing/run_conformance_tests_java.sh +1 -1
- package/genome/rules/func-specs.md +69 -74
- package/genome/rules/impl-reqs.md +4 -4
- package/genome/rules/integration-embedded-testing.md +20 -20
- package/genome/rules/integration-embedded.md +31 -31
- package/genome/rules/integration-standalone.md +9 -9
- package/genome/rules/integrations.md +18 -18
- package/genome/rules/linked-resources.md +19 -16
- package/genome/rules/module-structure.md +21 -14
- package/genome/rules/project-model.md +18 -17
- package/genome/rules/required-concepts.md +1 -1
- package/genome/rules/requires-modules.md +6 -5
- package/genome/rules/semantic-ids.md +49 -0
- package/genome/rules/stdlib.md +4 -5
- package/genome/rules/test-plain-files.md +130 -0
- package/genome/rules/test-reqs.md +8 -8
- package/genome/rules/turri-regeneration.md +23 -8
- package/genome/skills/analyze-2-func-specs/SKILL.md +36 -21
- package/genome/skills/analyze-func-specs/SKILL.md +46 -32
- package/genome/skills/break-down-func-spec/SKILL.md +91 -67
- package/genome/skills/consolidate-concepts/SKILL.md +10 -10
- package/genome/skills/convert-old-syntax/SKILL.md +68 -0
- package/genome/skills/convert-old-syntax/references/rubric.md +11 -0
- package/genome/skills/debug-specs/SKILL.md +62 -56
- package/genome/skills/implement-conformance-testing-script/SKILL.md +19 -15
- package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +2 -2
- package/genome/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +2 -2
- package/genome/skills/implement-unit-testing-script/SKILL.md +14 -10
- package/genome/skills/refactor-module/SKILL.md +35 -35
- package/genome/skills/resolve-section-ownership/SKILL.md +9 -9
- package/genome/skills/resolve-spec-conflict/SKILL.md +35 -29
- package/package.json +7 -6
- package/dist/regenerate/choose-conformance.d.ts +0 -32
- package/dist/regenerate/choose-conformance.js +0 -117
- /package/dist/{validate-cli.d.ts → parse-cli.d.ts} +0 -0
package/dist/regenerate/drift.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_CONCEPTS, extractConceptsFromDefinition, extractConceptsFromSpecText } from "../plain/concepts.js";
|
|
2
|
-
import { DEFINITIONS, FUNCTIONAL_REQUIREMENTS, REQUIRED_FUNCTIONAL_SPECS } from "../plain/spec.js";
|
|
2
|
+
import { ACCEPTANCE_TESTS, CONFORMANCE_TESTS, DEFINITIONS, FUNCTIONAL_REQUIREMENTS, REQUIRED_FUNCTIONAL_SPECS } from "../plain/spec.js";
|
|
3
3
|
import { codeTree, conformanceTarget, marksRegenerateAgain } from "./records.js";
|
|
4
|
-
import { applyChanges, changesBetween, parseTree, resourcesChanged, serializeTree } from "./spec-steps.js";
|
|
4
|
+
import { applyChanges, changesBetween, isMove, parseTree, resourcesChanged, serializeTree } from "./spec-steps.js";
|
|
5
5
|
/**
|
|
6
6
|
* The work, derived from the records - see docs/regenerating.md. Nothing here is stored: what is left
|
|
7
7
|
* to build is the difference between what a record says is built and what the spec says now, worked
|
|
@@ -9,7 +9,7 @@ import { applyChanges, changesBetween, parseTree, resourcesChanged, serializeTre
|
|
|
9
9
|
*
|
|
10
10
|
* - Code work: from the code record to the spec as the code sees it.
|
|
11
11
|
* - Conformance work: from the tests record to what the conformance tests are to be written for now -
|
|
12
|
-
* the
|
|
12
|
+
* the functional specs the code is built from that have scenarios.
|
|
13
13
|
*
|
|
14
14
|
* A job is a set of those changes. What it tells its agents follows from the functional specs it
|
|
15
15
|
* touches - its cases - and a running job is stopped once the spec no longer wants what it makes.
|
|
@@ -19,11 +19,52 @@ export function codeWork(record, spec) {
|
|
|
19
19
|
return changesBetween(serializeTree(codeTree(record ?? {})), serializeTree(codeTree(spec)));
|
|
20
20
|
}
|
|
21
21
|
/** Everything left to do in the conformance tests: from what the tests record says they are written for, to what they are to be now. */
|
|
22
|
-
export function conformanceWork(tests, code, spec
|
|
23
|
-
return changesBetween(serializeTree(tests ?? {}), serializeTree(conformanceTarget(code, tests, spec
|
|
22
|
+
export function conformanceWork(tests, code, spec) {
|
|
23
|
+
return changesBetween(serializeTree(tests ?? {}), serializeTree(conformanceTarget(code, tests, spec)));
|
|
24
|
+
}
|
|
25
|
+
/** Whether an item of a tree carries scenarios - a tree of the conformance tests' - rather than being the code's. */
|
|
26
|
+
const carriesScenarios = (item) => item !== undefined && (CONFORMANCE_TESTS in item || ACCEPTANCE_TESTS in item);
|
|
27
|
+
/** Every scenario of an item, by its kind and scenario-id. */
|
|
28
|
+
function scenariosIn(item) {
|
|
29
|
+
const found = new Map();
|
|
30
|
+
for (const kind of ["conformance", "acceptance"]) {
|
|
31
|
+
for (const scenario of (item?.[kind === "conformance" ? CONFORMANCE_TESTS : ACCEPTANCE_TESTS] ?? [])) {
|
|
32
|
+
found.set(`${kind} ${scenario.id}`, { kind, id: scenario.id, text: scenario.text, line: JSON.stringify([scenario.text.trim(), scenario.linked_resources ?? []]) });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return found;
|
|
36
|
+
}
|
|
37
|
+
/** What of a functional spec the code is built from: everything but its scenarios. */
|
|
38
|
+
function codeOf(item) {
|
|
39
|
+
if (item === undefined)
|
|
40
|
+
return "";
|
|
41
|
+
const { [CONFORMANCE_TESTS]: _conformance, [ACCEPTANCE_TESTS]: _acceptance, regenerate_again: _again, ...rest } = item;
|
|
42
|
+
return JSON.stringify({ ...rest, markdown: rest.markdown.trim() });
|
|
43
|
+
}
|
|
44
|
+
/** A functional spec's scenarios by case, from the item its tests were written for to the one they are to be. */
|
|
45
|
+
function scenarioCasesOf(spec, was, is, code) {
|
|
46
|
+
const before = scenariosIn(was);
|
|
47
|
+
const after = scenariosIn(is);
|
|
48
|
+
const plain = ({ kind, id, text }) => ({ kind, id, text });
|
|
49
|
+
const cases = { ...spec, added: [], changed: [], removed: [], unchanged: [] };
|
|
50
|
+
for (const [key, scenario] of after) {
|
|
51
|
+
const old = before.get(key);
|
|
52
|
+
if (old === undefined)
|
|
53
|
+
cases.added.push(plain(scenario));
|
|
54
|
+
else if (old.line !== scenario.line)
|
|
55
|
+
cases.changed.push(plain(scenario));
|
|
56
|
+
else
|
|
57
|
+
cases.unchanged.push(plain(scenario));
|
|
58
|
+
}
|
|
59
|
+
for (const [key, scenario] of before)
|
|
60
|
+
if (!after.has(key))
|
|
61
|
+
cases.removed.push(plain(scenario));
|
|
62
|
+
const moved = code ?? (was !== undefined && is !== undefined && codeOf(was) !== codeOf(is) ? "text" : undefined);
|
|
63
|
+
return moved !== undefined && cases.unchanged.length > 0 ? { ...cases, codeChanged: moved } : cases;
|
|
24
64
|
}
|
|
25
65
|
const functionalSpecs = (tree) => tree[FUNCTIONAL_REQUIREMENTS] ?? [];
|
|
26
|
-
const
|
|
66
|
+
const inheritedSpecs = (tree) => tree[REQUIRED_FUNCTIONAL_SPECS] ?? [];
|
|
67
|
+
const firstLine = (markdown) => markdown.trim().split("\n")[0].trim();
|
|
27
68
|
/** An item of a serialized tree, read back. */
|
|
28
69
|
const itemOfLine = (line) => {
|
|
29
70
|
if (line === undefined)
|
|
@@ -74,38 +115,44 @@ export function conceptsUsed(markdown, definitions) {
|
|
|
74
115
|
export function casesOf(before, changes, options = {}) {
|
|
75
116
|
const beforeText = serializeTree(before);
|
|
76
117
|
const after = parseTree(applyChanges(beforeText, changes));
|
|
77
|
-
const numberIn = (tree, item, position) => {
|
|
78
|
-
if (item?.frid !== undefined)
|
|
79
|
-
return item.frid;
|
|
80
|
-
const specs = functionalSpecs(tree);
|
|
81
|
-
const at = item === undefined ? -1 : specs.findIndex((spec) => spec.markdown === item.markdown);
|
|
82
|
-
return String(at === -1 ? position : at + 1);
|
|
83
|
-
};
|
|
84
118
|
const own = options.module !== undefined ? { module: options.module } : {};
|
|
119
|
+
const touchedOf = (item, required) => ({
|
|
120
|
+
funcId: item.id,
|
|
121
|
+
text: firstLine(item.markdown),
|
|
122
|
+
...(required ? (item.module !== undefined ? { module: item.module } : {}) : own),
|
|
123
|
+
});
|
|
85
124
|
const add = [];
|
|
86
125
|
const patch = [];
|
|
87
126
|
const again = [];
|
|
88
127
|
const removed = [];
|
|
128
|
+
/** Each functional spec touched, as the tests record has it and as it is to be: its scenarios' cases are worked out from them. */
|
|
129
|
+
const items = new Map();
|
|
130
|
+
const keyOf = (spec) => `${spec.module ?? ""}:${spec.funcId}`;
|
|
131
|
+
const seen = (spec, was, is) => {
|
|
132
|
+
items.set(keyOf(spec), { ...(was !== undefined ? { was } : {}), ...(is !== undefined ? { is } : {}) });
|
|
133
|
+
return spec;
|
|
134
|
+
};
|
|
89
135
|
for (const change of changes) {
|
|
136
|
+
// A module below's functional specs are cased as the codebase's own are: the codebase at the tip holds their code.
|
|
137
|
+
if (change.section !== FUNCTIONAL_REQUIREMENTS && change.section !== REQUIRED_FUNCTIONAL_SPECS)
|
|
138
|
+
continue;
|
|
139
|
+
const required = change.section === REQUIRED_FUNCTIONAL_SPECS;
|
|
90
140
|
const was = itemOfLine(change.before);
|
|
91
141
|
const is = itemOfLine(change.after);
|
|
92
142
|
// Marked to regenerate again: regenerated again, whatever else changed in its text - its own or, required, another module's.
|
|
93
143
|
if (change.kind === "change" && is !== undefined && marksRegenerateAgain(was)) {
|
|
94
|
-
|
|
95
|
-
if (change.section === FUNCTIONAL_REQUIREMENTS)
|
|
96
|
-
again.push({ frid: numberIn(after, is, change.position), text: firstLine(is.markdown), ...own });
|
|
97
|
-
else if (required !== undefined)
|
|
98
|
-
again.push({ frid: `${required.frid ?? change.position}`, text: firstLine(is.markdown), ...(required.module !== undefined ? { module: required.module } : {}) });
|
|
144
|
+
again.push(seen(touchedOf(is, required), was, is));
|
|
99
145
|
continue;
|
|
100
146
|
}
|
|
101
|
-
|
|
147
|
+
// Moved, and nothing else: none.
|
|
148
|
+
if (isMove(change))
|
|
102
149
|
continue;
|
|
103
150
|
if (change.kind === "add" && is !== undefined)
|
|
104
|
-
add.push(
|
|
151
|
+
add.push(seen(touchedOf(is, required), undefined, is));
|
|
105
152
|
else if (change.kind === "remove" && was !== undefined)
|
|
106
|
-
removed.push(
|
|
153
|
+
removed.push(seen(touchedOf(was, required), was, undefined));
|
|
107
154
|
else if (change.kind === "change" && is !== undefined)
|
|
108
|
-
patch.push(
|
|
155
|
+
patch.push(seen(touchedOf(is, required), was, is));
|
|
109
156
|
}
|
|
110
157
|
// The concepts the job defines anew, changes or takes out.
|
|
111
158
|
const redefined = new Set();
|
|
@@ -119,20 +166,43 @@ export function casesOf(before, changes, options = {}) {
|
|
|
119
166
|
redefined.add(concept);
|
|
120
167
|
}
|
|
121
168
|
}
|
|
169
|
+
// Every functional spec of the chain, as it is after the job and as it was: those of the modules below, then the
|
|
170
|
+
// codebase's own - the order every case lists them in.
|
|
171
|
+
const chainOf = (tree) => [...inheritedSpecs(tree).map((item) => ({ item, required: true })), ...functionalSpecs(tree).map((item) => ({ item, required: false }))];
|
|
172
|
+
const chain = chainOf(after);
|
|
122
173
|
if (redefined.size > 0) {
|
|
123
|
-
const touched = new Set([...add, ...patch, ...again].
|
|
174
|
+
const touched = new Set([...add, ...patch, ...again].map(keyOf));
|
|
124
175
|
const definitionsAfter = after[DEFINITIONS] ?? [];
|
|
125
176
|
const definitionsBefore = before[DEFINITIONS] ?? [];
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
if (touched.has(
|
|
129
|
-
|
|
177
|
+
for (const { item, required } of chain) {
|
|
178
|
+
const spec = touchedOf(item, required);
|
|
179
|
+
if (touched.has(keyOf(spec)))
|
|
180
|
+
continue;
|
|
130
181
|
const uses = new Set([...conceptsUsed(item.markdown, definitionsAfter), ...conceptsUsed(item.markdown, definitionsBefore)]);
|
|
131
182
|
if ([...redefined].some((concept) => uses.has(concept)))
|
|
132
|
-
patch.push(
|
|
133
|
-
}
|
|
134
|
-
patch.sort((a, b) => Number(a.frid) - Number(b.frid));
|
|
183
|
+
patch.push(seen(spec, item, item));
|
|
184
|
+
}
|
|
135
185
|
}
|
|
186
|
+
// In the chain's order: one taken out where it was.
|
|
187
|
+
const orderIn = (specs) => new Map(specs.map(({ item, required }, index) => [keyOf(touchedOf(item, required)), index]));
|
|
188
|
+
const inOrder = (list, order) => list.sort((a, b) => (order.get(keyOf(a)) ?? Number.MAX_SAFE_INTEGER) - (order.get(keyOf(b)) ?? Number.MAX_SAFE_INTEGER));
|
|
189
|
+
const order = orderIn(chain);
|
|
190
|
+
for (const list of [add, patch, again])
|
|
191
|
+
inOrder(list, order);
|
|
192
|
+
inOrder(removed, orderIn(chainOf(before)));
|
|
193
|
+
// The conformance tests' trees carry the scenarios: each functional spec touched, scenario by scenario.
|
|
194
|
+
const touchedItems = [...items.values()];
|
|
195
|
+
const scenarios = touchedItems.some(({ was, is }) => carriesScenarios(was) || carriesScenarios(is))
|
|
196
|
+
? [
|
|
197
|
+
...add.map((spec) => scenarioCasesOf(spec, undefined, items.get(keyOf(spec))?.is)),
|
|
198
|
+
...patch.map((spec) => {
|
|
199
|
+
const { was, is } = items.get(keyOf(spec)) ?? {};
|
|
200
|
+
return scenarioCasesOf(spec, was, is, was === is ? "concept" : undefined);
|
|
201
|
+
}),
|
|
202
|
+
...again.map((spec) => scenarioCasesOf(spec, items.get(keyOf(spec))?.was, items.get(keyOf(spec))?.is, "again")),
|
|
203
|
+
...removed.map((spec) => scenarioCasesOf(spec, items.get(keyOf(spec))?.was, undefined)),
|
|
204
|
+
]
|
|
205
|
+
: undefined;
|
|
136
206
|
return {
|
|
137
207
|
fresh: options.fresh === true,
|
|
138
208
|
add,
|
|
@@ -140,6 +210,7 @@ export function casesOf(before, changes, options = {}) {
|
|
|
140
210
|
again,
|
|
141
211
|
delete: removed,
|
|
142
212
|
mechanical: add.length === 0 && patch.length === 0 && again.length === 0 && removed.length === 0,
|
|
213
|
+
...(scenarios !== undefined ? { scenarios } : {}),
|
|
143
214
|
};
|
|
144
215
|
}
|
|
145
216
|
/** Two changes are the same change when they do the same to the same item. */
|
|
@@ -8,10 +8,10 @@ import { type AgentTally, type BuildingSpec, type SpecConflict, type TranscriptE
|
|
|
8
8
|
* carries on while the agents work.
|
|
9
9
|
*/
|
|
10
10
|
export type JobStatus = "queued" | "running" | "succeeded" | "failed" | "stopped";
|
|
11
|
-
/** A functional spec a pulse covers: the module whose spec it is - the pulse's own, or one below it - and its
|
|
11
|
+
/** A functional spec a pulse covers: the module whose spec it is - the pulse's own, or one below it - and its func-id there. */
|
|
12
12
|
export interface PulseSpec {
|
|
13
13
|
module: string;
|
|
14
|
-
|
|
14
|
+
funcId: string;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* The functional specs a pulse covers, by what it does to each (`cases.ts`): new, changed, regenerated again - its text
|
package/dist/regenerate/jobs.js
CHANGED
|
@@ -137,7 +137,7 @@ export function createJobRegistry(options) {
|
|
|
137
137
|
...(input.module !== undefined ? { module: input.module } : {}),
|
|
138
138
|
specConflict(conflict) {
|
|
139
139
|
job.specConflict = conflict;
|
|
140
|
-
this.transcript({ kind: "stage", text: `the spec contradicts itself:
|
|
140
|
+
this.transcript({ kind: "stage", text: `the spec contradicts itself: functional specs ${conflict.specs.map((spec) => `${spec.module}:${spec.funcId}`).join(" and ")} cannot both hold` });
|
|
141
141
|
changed();
|
|
142
142
|
},
|
|
143
143
|
stage(label) {
|
|
@@ -117,6 +117,12 @@ export type LedgerEvent = {
|
|
|
117
117
|
} | {
|
|
118
118
|
kind: "loop.stopped";
|
|
119
119
|
why: string;
|
|
120
|
+
} | {
|
|
121
|
+
kind: "loop.renamed";
|
|
122
|
+
what: "func-id" | "scenario-id";
|
|
123
|
+
from: string;
|
|
124
|
+
to: string;
|
|
125
|
+
spec: string;
|
|
120
126
|
} | {
|
|
121
127
|
kind: "planner.failed";
|
|
122
128
|
step: "group" | "place" | "title";
|
|
@@ -233,6 +239,19 @@ export type LedgerEvent = {
|
|
|
233
239
|
missing: string;
|
|
234
240
|
source: string;
|
|
235
241
|
sandbox: boolean;
|
|
242
|
+
} | {
|
|
243
|
+
kind: "advisor.classified";
|
|
244
|
+
spec: string;
|
|
245
|
+
verdict: "yes" | "no";
|
|
246
|
+
questions: string[];
|
|
247
|
+
asked: boolean;
|
|
248
|
+
} | {
|
|
249
|
+
kind: "advisor.dropped";
|
|
250
|
+
spec: string;
|
|
251
|
+
} | {
|
|
252
|
+
kind: "advisor.failed";
|
|
253
|
+
spec: string;
|
|
254
|
+
reason: string;
|
|
236
255
|
};
|
|
237
256
|
export type LedgerKind = LedgerEvent["kind"];
|
|
238
257
|
/** One line of the ledger: the event, and where and when it happened. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type MarshalledPlainSource } from "../plain/spec.ts";
|
|
1
2
|
import { type ChunkAgents } from "./chunk-plan.ts";
|
|
2
3
|
import { type SpecGap } from "./notes.ts";
|
|
3
4
|
import { type Job, type JobRegistry, type PulseCases } from "./jobs.ts";
|
|
@@ -6,7 +7,7 @@ import { type ChainEntry } from "./requires.ts";
|
|
|
6
7
|
import { type SpecSnapshot } from "./regenerate.ts";
|
|
7
8
|
import { type JobSteering } from "./steering.ts";
|
|
8
9
|
import { type SpecStep } from "./spec-steps.ts";
|
|
9
|
-
import { type JobCases
|
|
10
|
+
import { type JobCases } from "./drift.ts";
|
|
10
11
|
/**
|
|
11
12
|
* The work loop - see docs/regenerating.md.
|
|
12
13
|
*
|
|
@@ -67,18 +68,18 @@ export interface ModuleStatus {
|
|
|
67
68
|
steered?: string[];
|
|
68
69
|
};
|
|
69
70
|
/**
|
|
70
|
-
* The jobs planned after it, in order: the module's code jobs, then its conformance jobs.
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
71
|
+
* The jobs planned after it, in order: the module's code jobs, then its conformance jobs. The conformance tests of
|
|
72
|
+
* its functional specs with scenarios, behind while its code is still to build - `afterCode`, `specs` those
|
|
73
|
+
* functional specs as `module:func-id` - come last: they are planned into pulses only once the code is built, but are
|
|
74
|
+
* shown, so what follows the code is seen.
|
|
74
75
|
*/
|
|
75
76
|
planned: Array<{
|
|
76
77
|
title: string;
|
|
77
78
|
cases: JobCases;
|
|
78
79
|
track: Track;
|
|
79
|
-
waitsFor?: string[];
|
|
80
80
|
planning?: true;
|
|
81
81
|
afterCode?: true;
|
|
82
|
+
specs?: string[];
|
|
82
83
|
}>;
|
|
83
84
|
/**
|
|
84
85
|
* What the plan of its code did not do as asked: the person's wishes its planner did not follow and why, an answer
|
|
@@ -87,19 +88,33 @@ export interface ModuleStatus {
|
|
|
87
88
|
planNotes?: string[];
|
|
88
89
|
/** Why nothing runs there, when nothing does. */
|
|
89
90
|
why?: string;
|
|
90
|
-
/** What asking for conformance tests changed there, when it changed nothing: they
|
|
91
|
+
/** What asking for conformance tests changed there, when it changed nothing: they are written for what is built already. */
|
|
91
92
|
conformanceNote?: string;
|
|
92
93
|
/**
|
|
93
94
|
* It now requires modules its code was not built on - `requires` - and is built only once its code is started
|
|
94
95
|
* over on them: these codebases' code and tests taken out, kept in their history, and built again from the
|
|
95
|
-
* bottom of the chain.
|
|
96
|
+
* bottom of the chain. Or - `old` - these codebases were built when functional specs were numbered, before they had
|
|
97
|
+
* func-ids: nothing is built on them, and the whole chain is regenerated from scratch. Never done unasked:
|
|
98
|
+
* `startOver` does it.
|
|
96
99
|
*/
|
|
97
100
|
startOver?: {
|
|
98
101
|
requires: string[];
|
|
99
102
|
codebases: string[];
|
|
103
|
+
old?: true;
|
|
100
104
|
};
|
|
101
105
|
/** The stack it is built with - its config.turri.<stack>.yaml over config.turri.yaml - when one is. */
|
|
102
106
|
stack?: string;
|
|
107
|
+
/** Pure renames turri makes once the running pulse ends - a func-id or a scenario-id, nothing else with it: nothing regenerated. */
|
|
108
|
+
renames?: string[];
|
|
109
|
+
/**
|
|
110
|
+
* The base folder its codebase started from (base-folder.ts): the folder as `base-folder:` named it, and how many of
|
|
111
|
+
* the files that came from it the codebase has still - carried up with the code to a module built on it. None when it
|
|
112
|
+
* started from none, or has no code yet.
|
|
113
|
+
*/
|
|
114
|
+
base?: {
|
|
115
|
+
folder: string;
|
|
116
|
+
files: number;
|
|
117
|
+
};
|
|
103
118
|
}
|
|
104
119
|
/** What is left to regenerate in a codebase - see `WorkLoop.drift`. */
|
|
105
120
|
export interface DriftReport {
|
|
@@ -109,11 +124,6 @@ export interface DriftReport {
|
|
|
109
124
|
code: JobCases | null | undefined;
|
|
110
125
|
/** The conformance tests' work: null, none; undefined, none are written here. */
|
|
111
126
|
conformance: JobCases | null | undefined;
|
|
112
|
-
/** Conformance tests scheduled ahead of their code, and which of their functional specs are not built yet. */
|
|
113
|
-
scheduled: Array<{
|
|
114
|
-
frids: string[];
|
|
115
|
-
unbuilt: string[];
|
|
116
|
-
}>;
|
|
117
127
|
running?: {
|
|
118
128
|
jobId: string;
|
|
119
129
|
title: string;
|
|
@@ -121,9 +131,23 @@ export interface DriftReport {
|
|
|
121
131
|
/** Why nothing is regenerated there: halted, or its spec does not parse. */
|
|
122
132
|
why?: string;
|
|
123
133
|
startOver?: ModuleStatus["startOver"];
|
|
134
|
+
/** Pure renames not made yet - a func-id or a scenario-id, nothing else changed with it: made by turri, nothing regenerated. */
|
|
135
|
+
renames?: string[];
|
|
136
|
+
/** How its base folder stands against what its codebase started from, when they do not agree (base-folder.ts). */
|
|
137
|
+
baseFolder?: string;
|
|
138
|
+
/** conform named these functional specs, as `module:func-id`: the conformance tests are written for them alone until the module is asked for again. */
|
|
139
|
+
conformanceOnly?: string[];
|
|
140
|
+
/** Conformance tests are off here (`conformance-tests:`): none written or run. */
|
|
141
|
+
conformanceOff?: true;
|
|
124
142
|
}
|
|
125
143
|
/** What is left to regenerate, as the conversation and the command line read it. */
|
|
126
144
|
export declare function describeDrift(reports: DriftReport[]): string;
|
|
145
|
+
/** A codebase as the loop has just looked at it: its chain, its spec now, and what its code is built from (`codeTree` form). */
|
|
146
|
+
export interface SeenSpec {
|
|
147
|
+
chain: ChainEntry[];
|
|
148
|
+
tree: MarshalledPlainSource;
|
|
149
|
+
built: MarshalledPlainSource;
|
|
150
|
+
}
|
|
127
151
|
export interface WorkLoop {
|
|
128
152
|
/**
|
|
129
153
|
* Bring a spec's module up to the spec as the .plain files have it now - in the codebases where its
|
|
@@ -138,12 +162,12 @@ export interface WorkLoop {
|
|
|
138
162
|
specChange?: boolean;
|
|
139
163
|
}): Promise<ModuleStatus[]>;
|
|
140
164
|
/**
|
|
141
|
-
* Regenerate functional specs of a module again, their spec changed or not: each is marked to regenerate again in
|
|
165
|
+
* Regenerate functional specs of a module again, their spec changed or not - each named by its func-id: each is marked to regenerate again in
|
|
142
166
|
* the record of every codebase it is built in - committed - and they are brought up to their spec, the marked ones
|
|
143
167
|
* planned as any change is. Their code is there: the jobs that regenerate them are told to regenerate it again, not
|
|
144
168
|
* to build it anew.
|
|
145
169
|
*/
|
|
146
|
-
regenerateAgain(plainFile: string,
|
|
170
|
+
regenerateAgain(plainFile: string, funcIds: string | string[], options?: {
|
|
147
171
|
model?: string;
|
|
148
172
|
guidance?: string;
|
|
149
173
|
}): Promise<ModuleStatus[]>;
|
|
@@ -158,10 +182,9 @@ export interface WorkLoop {
|
|
|
158
182
|
* again, it clears a halt. Says what it planned.
|
|
159
183
|
*/
|
|
160
184
|
conformance(plainFile: string, options?: {
|
|
161
|
-
|
|
185
|
+
funcIds?: string[];
|
|
162
186
|
model?: string;
|
|
163
187
|
separately?: boolean;
|
|
164
|
-
groups?: string[][];
|
|
165
188
|
}): Promise<ModuleStatus[]>;
|
|
166
189
|
/**
|
|
167
190
|
* Start over the codebases of a spec's module that now require a module their code was not built on (see
|
|
@@ -229,8 +252,8 @@ export interface MapPulse {
|
|
|
229
252
|
before: string;
|
|
230
253
|
after: string;
|
|
231
254
|
/**
|
|
232
|
-
*
|
|
233
|
-
*
|
|
255
|
+
* The conformance tests that follow the code still to build - not planned, so with no trees: the functional specs they
|
|
256
|
+
* are written for, each as `module:func-id`.
|
|
234
257
|
*/
|
|
235
258
|
specs?: string[];
|
|
236
259
|
}
|
|
@@ -245,11 +268,11 @@ export interface MapCodebase {
|
|
|
245
268
|
planning?: Track;
|
|
246
269
|
/** The module below it that it waits for. */
|
|
247
270
|
waitsFor?: string;
|
|
248
|
-
/**
|
|
271
|
+
/** Whether any of its functional specs has scenarios, and so conformance tests. */
|
|
249
272
|
conformance: boolean;
|
|
250
273
|
/** Why nothing runs there, when nothing does. */
|
|
251
274
|
why?: string;
|
|
252
|
-
/** What asking for conformance tests changed there, when it changed nothing: they
|
|
275
|
+
/** What asking for conformance tests changed there, when it changed nothing: they are written for what is built already. */
|
|
253
276
|
conformanceNote?: string;
|
|
254
277
|
/**
|
|
255
278
|
* Halted, or the planner found no plan: it needs the person. `pulse`, the pulse that did not land; `cause`, what went
|
|
@@ -279,11 +302,13 @@ export interface ModuleCompletion {
|
|
|
279
302
|
specified: number;
|
|
280
303
|
/** Of those, the ones the delivered codebase's code record has as the spec has them now. */
|
|
281
304
|
completed: number;
|
|
282
|
-
/**
|
|
305
|
+
/** Its own functional specs with scenarios: those that are tested - one with no test plain file is not. */
|
|
306
|
+
withScenarios: number;
|
|
307
|
+
/** Of the completed ones, those its conformance tests are recorded as written for, as the spec has them now - their scenarios too. */
|
|
283
308
|
conformanceTested: number;
|
|
284
|
-
/** Those conformance-tested ones, by
|
|
309
|
+
/** Those conformance-tested ones, by func-id: for a host that shows each functional spec's state. */
|
|
285
310
|
tested: string[];
|
|
286
|
-
/** Its functional specs not completed, by
|
|
311
|
+
/** Its functional specs not completed, by func-id. */
|
|
287
312
|
incomplete: string[];
|
|
288
313
|
}
|
|
289
314
|
/**
|
|
@@ -313,25 +338,6 @@ export declare function createWorkLoop(options: {
|
|
|
313
338
|
run?: JobRunner;
|
|
314
339
|
/** Writes and runs a conformance job's tests. Default: a spec diff's conformance run, the whole suite with it. */
|
|
315
340
|
runConformance?: JobRunner;
|
|
316
|
-
/** Whether the config has a module's conformance tests on. Default: its `conformance-tests:`, off unless it turns them on. */
|
|
317
|
-
conformanceOn?: (plainFile: string) => boolean;
|
|
318
|
-
/**
|
|
319
|
-
* Whether a module's conformance tests are for the functional specs chosen, not every one: those with acceptance
|
|
320
|
-
* tests, those the conversation asked for, and those tested already. Default: `conformance-tests: chosen`.
|
|
321
|
-
*/
|
|
322
|
-
conformanceChosen?: (plainFile: string) => boolean;
|
|
323
|
-
/**
|
|
324
|
-
* Under `conformance-tests: chosen`, asked what a code job that landed built or changed that no conformance test is
|
|
325
|
-
* for - by whoever chooses without a conversation (`turri regenerate`) - before the job ends: the functional specs it
|
|
326
|
-
* names are scheduled as conform schedules them. The conversation is told in the job's report instead.
|
|
327
|
-
*/
|
|
328
|
-
onChoose?: (plainFile: string, specs: TouchedSpec[], budget: number | undefined, when: "pulse" | "module") => Promise<{
|
|
329
|
-
frids: string[];
|
|
330
|
-
groups?: string[][];
|
|
331
|
-
why?: string;
|
|
332
|
-
} | undefined>;
|
|
333
|
-
/** When the chooser is asked: after each code pulse, once the module is regenerated, or never. Default: `conformance-tests:`. */
|
|
334
|
-
conformanceChoosing?: (plainFile: string) => "pulse" | "module" | undefined;
|
|
335
341
|
/**
|
|
336
342
|
* Under `release-after-pulse: true`, what releases a pulse that landed, as its last stage - before the pulse ends, so
|
|
337
343
|
* the module's next pulse starts on what is released. Its last reply goes in the pulse's report. Not given: nothing is.
|
|
@@ -344,9 +350,22 @@ export declare function createWorkLoop(options: {
|
|
|
344
350
|
}) => Promise<string>;
|
|
345
351
|
/** Plan, and keep the job each codebase would start (`firsts`) - but start none. */
|
|
346
352
|
dryRun?: boolean;
|
|
353
|
+
/**
|
|
354
|
+
* Told each time the loop looks at a codebase whose spec parses: its chain, the spec as the .plain files have it now,
|
|
355
|
+
* and what its code is built from - what the test advisor watches (advisor-runs.ts). Nothing it does is the loop's
|
|
356
|
+
* concern: one that throws is ignored.
|
|
357
|
+
*/
|
|
358
|
+
onSpec?: (seen: SeenSpec) => void;
|
|
347
359
|
}): WorkLoop;
|
|
348
360
|
/** Why nothing runs in a codebase whose code - and conformance tests, where they are wanted - is built from its spec as it is. */
|
|
349
361
|
export declare const UP_TO_DATE = "built from the ***plain as it is";
|
|
362
|
+
/** Functional specs as a person names them: `module:func-id`, each. */
|
|
363
|
+
export declare function namesOf(module: string, funcIds: string[]): string;
|
|
364
|
+
/**
|
|
365
|
+
* The func-ids a person names in a module, each as `module:func-id` - a bare func-id, or another module's, is refused:
|
|
366
|
+
* a func-id is unique in its module only.
|
|
367
|
+
*/
|
|
368
|
+
export declare function funcIdsNamed(module: string, names: string[]): string[];
|
|
350
369
|
/** The codebases the loop looks after, as the person reads them: what runs, what is planned after it, and why nothing does. */
|
|
351
370
|
/**
|
|
352
371
|
* The coding agent's task for a dry run's first job, built as the render builds it - and all it did rolled back. Not for
|