@yansirplus/cli 0.5.17
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/PUBLIC_API.md +22 -0
- package/README.md +34 -0
- package/dist/build/agent-authoring/config.d.ts +177 -0
- package/dist/build/agent-authoring/config.js +607 -0
- package/dist/build/agent-authoring/manifest-compiler.d.ts +159 -0
- package/dist/build/agent-authoring/manifest-compiler.js +737 -0
- package/dist/build/agent-authoring/shared.d.ts +10 -0
- package/dist/build/agent-authoring/shared.js +57 -0
- package/dist/build/agent-authoring/static-target.d.ts +59 -0
- package/dist/build/agent-authoring/static-target.js +1857 -0
- package/dist/build/agent-authoring.d.ts +9 -0
- package/dist/build/agent-authoring.js +5 -0
- package/dist/build/build-cli.d.ts +2 -0
- package/dist/build/build-cli.js +264 -0
- package/dist/check/algorithmic/architecture-checks.mjs +971 -0
- package/dist/check/algorithmic/client-boundary-checks.mjs +337 -0
- package/dist/check/algorithmic/convergence-smoke-checks.mjs +608 -0
- package/dist/check/algorithmic/distribution-checks.mjs +919 -0
- package/dist/check/algorithmic/owner-checks.mjs +647 -0
- package/dist/check/algorithmic/package-boundary-checks.mjs +985 -0
- package/dist/check/algorithmic/projection-boundary-checks.mjs +302 -0
- package/dist/check/algorithmic/repo-surface-checks.mjs +267 -0
- package/dist/check/algorithmic/runtime-structural-checks.mjs +264 -0
- package/dist/check/algorithmic/source-alias-checks.mjs +106 -0
- package/dist/check/algorithmic/static-target-checks.mjs +447 -0
- package/dist/check/algorithmic-checks.mjs +482 -0
- package/dist/check/check-coverage.mjs +231 -0
- package/dist/check/command-runner.mjs +22 -0
- package/dist/check/default-gate.mjs +51 -0
- package/dist/check/gate-selector.mjs +305 -0
- package/dist/check/manifest-rules.mjs +223 -0
- package/dist/check/package-graph.mjs +464 -0
- package/dist/generate/generate-agent-docs.mjs +435 -0
- package/dist/generate/generate-carrier-reference.mjs +514 -0
- package/dist/generate/generate-docs.mjs +345 -0
- package/dist/generate/generate-effect-skill-manifests.mjs +193 -0
- package/dist/generate/project-docs-site.mjs +190 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +25 -0
- package/dist/lib/agent-docs-model.mjs +888 -0
- package/dist/lib/boundary-rules.mjs +63 -0
- package/dist/lib/capability-routes.mjs +354 -0
- package/dist/lib/projection-sink.mjs +113 -0
- package/dist/lib/public-api-model.mjs +306 -0
- package/dist/main.mjs +233 -0
- package/dist/runner.mjs +127 -0
- package/package.json +32 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import {
|
|
7
|
+
checkProjectionSink,
|
|
8
|
+
defineProjectionSpec,
|
|
9
|
+
runProjectionSink,
|
|
10
|
+
} from "../lib/projection-sink.mjs";
|
|
11
|
+
import { collectAgentDocsModel } from "../lib/agent-docs-model.mjs";
|
|
12
|
+
import { buildCapabilityRouteProjection } from "../lib/capability-routes.mjs";
|
|
13
|
+
|
|
14
|
+
const root = process.cwd();
|
|
15
|
+
const check = process.argv.includes("--check");
|
|
16
|
+
const failures = [];
|
|
17
|
+
|
|
18
|
+
const abs = (file) => path.join(root, file);
|
|
19
|
+
const exists = (file) => fs.existsSync(abs(file));
|
|
20
|
+
const read = (file) => fs.readFileSync(abs(file), "utf8");
|
|
21
|
+
|
|
22
|
+
const generatedNotice = (source) =>
|
|
23
|
+
`<!-- generated by packages/cli/src/generate/generate-agent-docs.mjs; edit ${source} -->`;
|
|
24
|
+
|
|
25
|
+
const agentDocsSourceFacts = {
|
|
26
|
+
kind: "source-set",
|
|
27
|
+
ref: "docs.generate-agent-docs.source-facts",
|
|
28
|
+
sources: [
|
|
29
|
+
{ kind: "directory", ref: "docs/agent/*.source.json" },
|
|
30
|
+
{ kind: "file", ref: "docs/surface.json" },
|
|
31
|
+
{ kind: "directory", ref: "packages/*/package.json" },
|
|
32
|
+
{ kind: "tsdoc", ref: "exported @agentosPrimitive tags" },
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const fileProjection = (file) =>
|
|
37
|
+
defineProjectionSpec({
|
|
38
|
+
id: `docs.generate-agent-docs:${file}`,
|
|
39
|
+
version: 1,
|
|
40
|
+
source: agentDocsSourceFacts,
|
|
41
|
+
project: (expected, ctx) => ctx.ok(expected),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const fileSink = (file) => {
|
|
45
|
+
const target = abs(file);
|
|
46
|
+
return {
|
|
47
|
+
id: file,
|
|
48
|
+
read: () =>
|
|
49
|
+
fs.existsSync(target)
|
|
50
|
+
? { _tag: "found", output: fs.readFileSync(target, "utf8") }
|
|
51
|
+
: { _tag: "missing" },
|
|
52
|
+
write: (output) => {
|
|
53
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
54
|
+
fs.writeFileSync(target, output);
|
|
55
|
+
},
|
|
56
|
+
equals: (actual, expected) => actual === expected,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const formatGeneratedText = (file, text) => {
|
|
61
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agent-docs-"));
|
|
62
|
+
const tmpFile = path.join(tmpDir, path.basename(file));
|
|
63
|
+
try {
|
|
64
|
+
fs.writeFileSync(tmpFile, `${text.replace(/\s+$/u, "")}\n`);
|
|
65
|
+
const result = spawnSync("vp", ["fmt", tmpFile, "--write"], {
|
|
66
|
+
cwd: root,
|
|
67
|
+
encoding: "utf8",
|
|
68
|
+
});
|
|
69
|
+
if (result.status !== 0) {
|
|
70
|
+
failures.push(
|
|
71
|
+
`${file} failed generated formatting: ${result.stderr || result.stdout || result.status}`,
|
|
72
|
+
);
|
|
73
|
+
return `${text.replace(/\s+$/u, "")}\n`;
|
|
74
|
+
}
|
|
75
|
+
return fs.readFileSync(tmpFile, "utf8");
|
|
76
|
+
} finally {
|
|
77
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const write = async (file, text) => {
|
|
82
|
+
const expected = formatGeneratedText(file, text);
|
|
83
|
+
const spec = fileProjection(file);
|
|
84
|
+
const sink = fileSink(file);
|
|
85
|
+
if (check) {
|
|
86
|
+
const result = await checkProjectionSink(spec, expected, sink);
|
|
87
|
+
if (result._tag === "projection_failed") {
|
|
88
|
+
failures.push(`${file} projection failed: ${result.result.reason}`);
|
|
89
|
+
} else if (result._tag === "stale") {
|
|
90
|
+
failures.push(`${file} is stale`);
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const result = await runProjectionSink(spec, expected, sink);
|
|
95
|
+
if (result._tag === "projection_failed") {
|
|
96
|
+
failures.push(`${file} projection failed: ${result.result.reason}`);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const writeJson = async (file, value) => write(file, JSON.stringify(value, null, 2));
|
|
101
|
+
|
|
102
|
+
const replaceGeneratedBlock = async ({ file, startMarker, endMarker, block, insertBefore }) => {
|
|
103
|
+
const current = exists(file) ? read(file) : "";
|
|
104
|
+
const startIndex = current.indexOf(startMarker);
|
|
105
|
+
const endIndex = current.indexOf(endMarker);
|
|
106
|
+
const normalizedBlock = block.replace(/\s+$/u, "");
|
|
107
|
+
let next;
|
|
108
|
+
|
|
109
|
+
if ((startIndex === -1) !== (endIndex === -1)) {
|
|
110
|
+
failures.push(`${file} has incomplete generated block markers`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (startIndex >= 0 && endIndex > startIndex) {
|
|
115
|
+
const endLineIndex = current.indexOf("\n", endIndex);
|
|
116
|
+
let afterIndex = endLineIndex === -1 ? current.length : endLineIndex + 1;
|
|
117
|
+
while (current[afterIndex] === "\n") afterIndex += 1;
|
|
118
|
+
next = `${current.slice(0, startIndex)}${normalizedBlock}\n\n${current.slice(afterIndex)}`;
|
|
119
|
+
} else {
|
|
120
|
+
const insertIndex = current.indexOf(insertBefore);
|
|
121
|
+
if (insertIndex < 0) {
|
|
122
|
+
failures.push(`${file} missing insertion anchor ${insertBefore}`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
next = `${current.slice(0, insertIndex)}${normalizedBlock}\n\n${current.slice(insertIndex)}`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
await write(file, next);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const relativeLink = (fromFile, targetFile) => {
|
|
132
|
+
const fromDir = path.posix.dirname(fromFile);
|
|
133
|
+
const target = path.posix.relative(fromDir, targetFile);
|
|
134
|
+
return target.length === 0 ? path.posix.basename(targetFile) : target;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const mdLink = (fromFile, label, targetFile) => `[${label}](${relativeLink(fromFile, targetFile)})`;
|
|
138
|
+
|
|
139
|
+
const table = (headers, rows) => {
|
|
140
|
+
const widths = headers.map((header, index) =>
|
|
141
|
+
Math.max(header.length, ...rows.map((row) => row[index].length)),
|
|
142
|
+
);
|
|
143
|
+
const line = (row) =>
|
|
144
|
+
`| ${row.map((cell, index) => `${cell}${" ".repeat(Math.max(0, widths[index] - cell.length))}`).join(" | ")} |`;
|
|
145
|
+
return [
|
|
146
|
+
line(headers),
|
|
147
|
+
`| ${widths.map((width) => "-".repeat(width)).join(" | ")} |`,
|
|
148
|
+
...rows.map(line),
|
|
149
|
+
].join("\n");
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const model = collectAgentDocsModel(root);
|
|
153
|
+
failures.push(...model.failures);
|
|
154
|
+
|
|
155
|
+
const {
|
|
156
|
+
recipesSource,
|
|
157
|
+
capabilityRulesSource,
|
|
158
|
+
invariantsSource,
|
|
159
|
+
primitives,
|
|
160
|
+
errors,
|
|
161
|
+
invariantMatrix,
|
|
162
|
+
rootScripts,
|
|
163
|
+
namespaceModel,
|
|
164
|
+
} = model;
|
|
165
|
+
const boundaryRuleSource = JSON.parse(read("docs/agent/boundary-rules.source.json"));
|
|
166
|
+
const boundaryRuleCommands = Object.fromEntries(
|
|
167
|
+
(Array.isArray(boundaryRuleSource.rules) ? boundaryRuleSource.rules : []).map((rule) => [
|
|
168
|
+
rule.id,
|
|
169
|
+
`agentos check guard ${rule.id}`,
|
|
170
|
+
]),
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const capabilityProjection = buildCapabilityRouteProjection({
|
|
174
|
+
source: capabilityRulesSource,
|
|
175
|
+
recipes: recipesSource.recipes,
|
|
176
|
+
primitives,
|
|
177
|
+
invariants: invariantsSource.invariants,
|
|
178
|
+
rootScripts: { ...rootScripts, ...boundaryRuleCommands },
|
|
179
|
+
namespaceOwners: namespaceModel.owners,
|
|
180
|
+
});
|
|
181
|
+
failures.push(...capabilityProjection.failures);
|
|
182
|
+
|
|
183
|
+
const primitivesJson = {
|
|
184
|
+
generatedBy: "packages/cli/src/generate/generate-agent-docs.mjs",
|
|
185
|
+
source: [
|
|
186
|
+
"exported TSDoc @agentosPrimitive tags",
|
|
187
|
+
"docs/agent/invariants.source.json",
|
|
188
|
+
"docs/agent/primitive-evidence.source.json",
|
|
189
|
+
],
|
|
190
|
+
primitives,
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const recipesJson = {
|
|
194
|
+
generatedBy: "packages/cli/src/generate/generate-agent-docs.mjs",
|
|
195
|
+
source: "docs/agent/recipes.source.json",
|
|
196
|
+
recipes: recipesSource.recipes,
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const errorsJson = {
|
|
200
|
+
generatedBy: "packages/cli/src/generate/generate-agent-docs.mjs",
|
|
201
|
+
source: ["packages/**/*.ts agent_os.* tags", "docs/agent/error-metadata.source.json"],
|
|
202
|
+
errors,
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const invariantMatrixJson = {
|
|
206
|
+
generatedBy: "packages/cli/src/generate/generate-agent-docs.mjs",
|
|
207
|
+
source: [
|
|
208
|
+
"docs/agent/invariants.source.json",
|
|
209
|
+
"exported TSDoc @agentosInvariant tags",
|
|
210
|
+
"docs/agent/error-metadata.source.json",
|
|
211
|
+
],
|
|
212
|
+
invariants: invariantMatrix,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const decisionGraphJson = {
|
|
216
|
+
generatedBy: "packages/cli/src/generate/generate-agent-docs.mjs",
|
|
217
|
+
source: [
|
|
218
|
+
"docs/agent/capability-rules.source.json",
|
|
219
|
+
"docs/agent/recipes.source.json",
|
|
220
|
+
"exported TSDoc @agentosPrimitive tags",
|
|
221
|
+
"BoundaryContract/event namespace declarations",
|
|
222
|
+
"docs/agent/boundary-rules.source.json",
|
|
223
|
+
],
|
|
224
|
+
routes: capabilityProjection.routes,
|
|
225
|
+
coverage: capabilityProjection.coverage,
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const startHere = [
|
|
229
|
+
generatedNotice("docs/agent/*.source.json and exported TSDoc @agentosPrimitive tags"),
|
|
230
|
+
"",
|
|
231
|
+
"# Start Here",
|
|
232
|
+
"",
|
|
233
|
+
"Agent-facing docs are generated projections. Source facts live in `docs/agent/*.source.json`, `docs/surface.json`, package manifests, and exported TSDoc annotation tags.",
|
|
234
|
+
"",
|
|
235
|
+
"## Navigation",
|
|
236
|
+
"",
|
|
237
|
+
table(
|
|
238
|
+
["Surface", "Generated File"],
|
|
239
|
+
[
|
|
240
|
+
[
|
|
241
|
+
"Recipes",
|
|
242
|
+
mdLink("docs/start-here.md", "docs/agent/recipes.json", "docs/agent/recipes.json"),
|
|
243
|
+
],
|
|
244
|
+
[
|
|
245
|
+
"Primitives",
|
|
246
|
+
mdLink("docs/start-here.md", "docs/agent/primitives.md", "docs/agent/primitives.md"),
|
|
247
|
+
],
|
|
248
|
+
[
|
|
249
|
+
"Decision Graph",
|
|
250
|
+
mdLink(
|
|
251
|
+
"docs/start-here.md",
|
|
252
|
+
"docs/agent/decision-graph.md",
|
|
253
|
+
"docs/agent/decision-graph.md",
|
|
254
|
+
),
|
|
255
|
+
],
|
|
256
|
+
["Errors", mdLink("docs/start-here.md", "docs/agent/errors.md", "docs/agent/errors.md")],
|
|
257
|
+
[
|
|
258
|
+
"Invariant Matrix",
|
|
259
|
+
mdLink(
|
|
260
|
+
"docs/start-here.md",
|
|
261
|
+
"docs/agent/invariant-matrix.md",
|
|
262
|
+
"docs/agent/invariant-matrix.md",
|
|
263
|
+
),
|
|
264
|
+
],
|
|
265
|
+
],
|
|
266
|
+
),
|
|
267
|
+
"",
|
|
268
|
+
"## Recipes",
|
|
269
|
+
"",
|
|
270
|
+
table(
|
|
271
|
+
["Recipe", "Tutorial", "Primary Primitives"],
|
|
272
|
+
recipesSource.recipes.map((recipe) => [
|
|
273
|
+
`\`${recipe.id}\``,
|
|
274
|
+
mdLink("docs/start-here.md", recipe.title, recipe.tutorial),
|
|
275
|
+
recipe.primitives.map((primitive) => `\`${primitive}\``).join(", "),
|
|
276
|
+
]),
|
|
277
|
+
),
|
|
278
|
+
"",
|
|
279
|
+
].join("\n");
|
|
280
|
+
|
|
281
|
+
const agentNavigationStart = "<!-- agent-docs-navigation:start -->";
|
|
282
|
+
const agentNavigationEnd = "<!-- agent-docs-navigation:end -->";
|
|
283
|
+
const agentNavigation = [
|
|
284
|
+
agentNavigationStart,
|
|
285
|
+
generatedNotice("docs/agent/*.source.json and exported TSDoc @agentosPrimitive tags"),
|
|
286
|
+
"## Agent Navigation Index",
|
|
287
|
+
"",
|
|
288
|
+
"Start at [docs/start-here.md](docs/start-here.md). It is the generated route from intent to primitive, invariant, error, docs, and tests.",
|
|
289
|
+
"",
|
|
290
|
+
table(
|
|
291
|
+
["Intent", "Route"],
|
|
292
|
+
[
|
|
293
|
+
["Start route", "[docs/start-here.md](docs/start-here.md)"],
|
|
294
|
+
["Primitive catalog", "[docs/agent/primitives.md](docs/agent/primitives.md)"],
|
|
295
|
+
["Decision graph", "[docs/agent/decision-graph.md](docs/agent/decision-graph.md)"],
|
|
296
|
+
["Error catalog", "[docs/agent/errors.md](docs/agent/errors.md)"],
|
|
297
|
+
["Invariant matrix", "[docs/agent/invariant-matrix.md](docs/agent/invariant-matrix.md)"],
|
|
298
|
+
...recipesSource.recipes.map((recipe) => [
|
|
299
|
+
recipe.title,
|
|
300
|
+
`[${recipe.tutorial}](${recipe.tutorial})`,
|
|
301
|
+
]),
|
|
302
|
+
],
|
|
303
|
+
),
|
|
304
|
+
agentNavigationEnd,
|
|
305
|
+
].join("\n");
|
|
306
|
+
|
|
307
|
+
const primitivesMd = [
|
|
308
|
+
generatedNotice(
|
|
309
|
+
"exported TSDoc @agentosPrimitive tags and docs/agent/primitive-evidence.source.json",
|
|
310
|
+
),
|
|
311
|
+
"",
|
|
312
|
+
"# Agent Primitives",
|
|
313
|
+
"",
|
|
314
|
+
table(
|
|
315
|
+
["Primitive", "Kind", "Export", "Invariant", "Docs", "Test Evidence"],
|
|
316
|
+
primitives.map((primitive) => [
|
|
317
|
+
`\`${primitive.id}\``,
|
|
318
|
+
`\`${primitive.capabilityKind}\``,
|
|
319
|
+
`\`${primitive.package}:${primitive.symbol}\``,
|
|
320
|
+
primitive.invariants.map((invariant) => `\`${invariant}\``).join(", "),
|
|
321
|
+
mdLink("docs/agent/primitives.md", path.posix.basename(primitive.docs), primitive.docs),
|
|
322
|
+
primitive.testEvidence.tests === undefined
|
|
323
|
+
? `no test: ${primitive.testEvidence.noTestReason}`
|
|
324
|
+
: primitive.testEvidence.tests
|
|
325
|
+
.map((test) => mdLink("docs/agent/primitives.md", path.posix.basename(test), test))
|
|
326
|
+
.join(", "),
|
|
327
|
+
]),
|
|
328
|
+
),
|
|
329
|
+
"",
|
|
330
|
+
].join("\n");
|
|
331
|
+
|
|
332
|
+
const errorsMd = [
|
|
333
|
+
generatedNotice("packages/**/*.ts agent_os.* tags and docs/agent/error-metadata.source.json"),
|
|
334
|
+
"",
|
|
335
|
+
"# Agent Error Catalog",
|
|
336
|
+
"",
|
|
337
|
+
table(
|
|
338
|
+
["Error", "Invariant", "Docs", "Fix"],
|
|
339
|
+
errors.map((error) => [
|
|
340
|
+
`\`${error.tag}\``,
|
|
341
|
+
error.invariants.map((invariant) => `\`${invariant}\``).join(", "),
|
|
342
|
+
mdLink("docs/agent/errors.md", path.posix.basename(error.docs), error.docs),
|
|
343
|
+
error.fix,
|
|
344
|
+
]),
|
|
345
|
+
),
|
|
346
|
+
"",
|
|
347
|
+
].join("\n");
|
|
348
|
+
|
|
349
|
+
const decisionGraphMd = [
|
|
350
|
+
generatedNotice(
|
|
351
|
+
"docs/agent/capability-rules.source.json, docs/agent/recipes.source.json, exported TSDoc @agentosPrimitive tags, BoundaryContract/event namespace declarations, and docs/agent/boundary-rules.source.json",
|
|
352
|
+
),
|
|
353
|
+
"",
|
|
354
|
+
"# Agent Decision Graph",
|
|
355
|
+
"",
|
|
356
|
+
"This is the generated owner compiler from natural-language intent to allowed substrate motion. Source rules name intent and constraints only; owner and package fields are generated.",
|
|
357
|
+
"",
|
|
358
|
+
table(
|
|
359
|
+
["Primitive", "Kind", "Intents", "Source Fact Owners", "Allowed Packages", "Gates"],
|
|
360
|
+
capabilityProjection.routes.map((route) => [
|
|
361
|
+
`\`${route.primitive}\``,
|
|
362
|
+
`\`${route.coordinationCapabilityKind}\``,
|
|
363
|
+
route.intents.join("; "),
|
|
364
|
+
route.sourceFactOwners
|
|
365
|
+
.map((entry) => `\`${String(entry.prefix)}\` -> \`${String(entry.owner)}\``)
|
|
366
|
+
.join(", "),
|
|
367
|
+
route.allowedPrimitivePackages.map((pkg) => `\`${String(pkg)}\``).join(", "),
|
|
368
|
+
route.gates.map((gate) => `\`${gate}\``).join(", "),
|
|
369
|
+
]),
|
|
370
|
+
),
|
|
371
|
+
"",
|
|
372
|
+
"## Coverage",
|
|
373
|
+
"",
|
|
374
|
+
table(
|
|
375
|
+
["Recipe", "Status"],
|
|
376
|
+
capabilityProjection.coverage.recipes.map((recipe) => [
|
|
377
|
+
`\`${recipe.id}\``,
|
|
378
|
+
recipe.routePrimitives.length > 0
|
|
379
|
+
? recipe.routePrimitives.map((primitive) => `\`${primitive}\``).join(", ")
|
|
380
|
+
: `no route: ${recipe.noRouteReason}`,
|
|
381
|
+
]),
|
|
382
|
+
),
|
|
383
|
+
"",
|
|
384
|
+
].join("\n");
|
|
385
|
+
|
|
386
|
+
const invariantMatrixMd = [
|
|
387
|
+
generatedNotice(
|
|
388
|
+
"docs/agent/invariants.source.json, exported TSDoc @agentosInvariant tags, and docs/agent/error-metadata.source.json",
|
|
389
|
+
),
|
|
390
|
+
"",
|
|
391
|
+
"# Agent Invariant Matrix",
|
|
392
|
+
"",
|
|
393
|
+
table(
|
|
394
|
+
["Invariant", "Primitives", "Errors", "Docs", "Tests"],
|
|
395
|
+
invariantMatrix.map((row) => [
|
|
396
|
+
`\`${row.invariant}\``,
|
|
397
|
+
row.primitives.map((primitive) => `\`${primitive}\``).join(", "),
|
|
398
|
+
row.errors.map((error) => `\`${error}\``).join(", "),
|
|
399
|
+
row.docs
|
|
400
|
+
.map((doc) => mdLink("docs/agent/invariant-matrix.md", path.posix.basename(doc), doc))
|
|
401
|
+
.join(", "),
|
|
402
|
+
row.tests.map((test) => `\`${test}\``).join(", "),
|
|
403
|
+
]),
|
|
404
|
+
),
|
|
405
|
+
"",
|
|
406
|
+
].join("\n");
|
|
407
|
+
|
|
408
|
+
if (failures.length === 0) {
|
|
409
|
+
await writeJson("docs/agent/recipes.json", recipesJson);
|
|
410
|
+
await writeJson("docs/agent/primitives.json", primitivesJson);
|
|
411
|
+
await write("docs/agent/primitives.md", primitivesMd);
|
|
412
|
+
await writeJson("docs/agent/decision-graph.json", decisionGraphJson);
|
|
413
|
+
await write("docs/agent/decision-graph.md", decisionGraphMd);
|
|
414
|
+
await writeJson("docs/agent/errors.json", errorsJson);
|
|
415
|
+
await write("docs/agent/errors.md", errorsMd);
|
|
416
|
+
await writeJson("docs/agent/invariant-matrix.json", invariantMatrixJson);
|
|
417
|
+
await write("docs/agent/invariant-matrix.md", invariantMatrixMd);
|
|
418
|
+
await write("docs/start-here.md", startHere);
|
|
419
|
+
await replaceGeneratedBlock({
|
|
420
|
+
file: "AGENTS.md",
|
|
421
|
+
startMarker: agentNavigationStart,
|
|
422
|
+
endMarker: agentNavigationEnd,
|
|
423
|
+
block: agentNavigation,
|
|
424
|
+
insertBefore: "## BoundaryContract Checklist",
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if (failures.length > 0) {
|
|
429
|
+
console.error(failures.join("\n"));
|
|
430
|
+
process.exit(1);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
console.log(
|
|
434
|
+
`generated agent docs: ${recipesSource.recipes.length} recipes, ${primitives.length} primitives, ${errors.length} errors`,
|
|
435
|
+
);
|