aontu 0.55.0 → 0.56.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 +3 -3
- package/dist/agentsmd.d.ts +1 -0
- package/dist/agentsmd.js +10 -3
- package/dist/agentsmd.js.map +1 -1
- package/dist/aontu.d.ts +3 -2
- package/dist/aontu.js +5 -2
- package/dist/aontu.js.map +1 -1
- package/dist/cli.d.ts +5 -2
- package/dist/cli.js +236 -49
- package/dist/cli.js.map +1 -1
- package/dist/diff.d.ts +1 -0
- package/dist/diff.js +3 -2
- package/dist/diff.js.map +1 -1
- package/dist/format.d.ts +17 -0
- package/dist/format.js +1000 -0
- package/dist/format.js.map +1 -0
- package/dist/hints.js +4 -0
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.d.ts +1 -0
- package/dist/jsonschema.js +3 -2
- package/dist/jsonschema.js.map +1 -1
- package/dist/lang.js +64 -5
- package/dist/lang.js.map +1 -1
- package/dist/lsp.d.ts +2 -1
- package/dist/lsp.js +1 -1
- package/dist/lsp.js.map +1 -1
- package/dist/mcp.js +6 -4
- package/dist/mcp.js.map +1 -1
- package/dist/patch.d.ts +1 -0
- package/dist/patch.js +1 -0
- package/dist/patch.js.map +1 -1
- package/dist/query.d.ts +1 -0
- package/dist/query.js +4 -3
- package/dist/query.js.map +1 -1
- package/dist/reach.d.ts +1 -0
- package/dist/reach.js +3 -2
- package/dist/reach.js.map +1 -1
- package/dist/relation.d.ts +1 -0
- package/dist/relation.js +3 -2
- package/dist/relation.js.map +1 -1
- package/dist/std.js +2 -1
- package/dist/std.js.map +1 -1
- package/dist/subsume.d.ts +1 -0
- package/dist/subsume.js +3 -2
- package/dist/subsume.js.map +1 -1
- package/dist/trim.d.ts +1 -0
- package/dist/trim.js +3 -2
- package/dist/trim.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.d.ts +1 -0
- package/dist/type.js.map +1 -1
- package/dist/utility.d.ts +8 -2
- package/dist/utility.js +9 -1
- package/dist/utility.js.map +1 -1
- package/dist/vet.d.ts +1 -0
- package/dist/vet.js +1 -1
- package/dist/vet.js.map +1 -1
- package/dist/view.d.ts +2 -1
- package/dist/view.js +379 -8
- package/dist/view.js.map +1 -1
- package/grammar/aontu.abnf +155 -0
- package/package.json +2 -1
- package/skill/grammar-card.md +5 -2
- package/src/agentsmd.ts +15 -3
- package/src/aontu.ts +7 -1
- package/src/cli.ts +267 -53
- package/src/diff.ts +7 -2
- package/src/format.ts +1146 -0
- package/src/hints.ts +5 -0
- package/src/jsonschema.ts +7 -1
- package/src/lang.ts +69 -5
- package/src/lsp.ts +5 -3
- package/src/mcp.ts +6 -4
- package/src/patch.ts +7 -0
- package/src/query.ts +8 -4
- package/src/reach.ts +7 -2
- package/src/relation.ts +7 -2
- package/src/std.ts +2 -1
- package/src/subsume.ts +7 -2
- package/src/trim.ts +7 -2
- package/src/type.ts +8 -0
- package/src/utility.ts +27 -2
- package/src/vet.ts +9 -3
- package/src/view.ts +442 -9
package/dist/cli.js
CHANGED
|
@@ -20,6 +20,7 @@ exports.runWhy = runWhy;
|
|
|
20
20
|
exports.renderWhyText = renderWhyText;
|
|
21
21
|
exports.runSet = runSet;
|
|
22
22
|
exports.runAgentsMd = runAgentsMd;
|
|
23
|
+
exports.runFmt = runFmt;
|
|
23
24
|
exports.watchChange = watchChange;
|
|
24
25
|
exports.watchSignature = watchSignature;
|
|
25
26
|
exports.deprecatedAt = deprecatedAt;
|
|
@@ -46,6 +47,8 @@ const vet_1 = require("./vet");
|
|
|
46
47
|
const reach_1 = require("./reach");
|
|
47
48
|
const view_1 = require("./view");
|
|
48
49
|
const agentsmd_1 = require("./agentsmd");
|
|
50
|
+
const format_1 = require("./format");
|
|
51
|
+
const utility_1 = require("./utility");
|
|
49
52
|
const HELP = `Usage: aontu [options] [file]
|
|
50
53
|
aontu vet [options] <schema> <data> [more-data...]
|
|
51
54
|
aontu subsume [options] <general> <specific>
|
|
@@ -62,6 +65,7 @@ const HELP = `Usage: aontu [options] [file]
|
|
|
62
65
|
aontu why <path> [options] <file>
|
|
63
66
|
aontu set <path>=<value>... --entry <file> --overlay <file>
|
|
64
67
|
aontu agentsmd [--write <AGENTS.md>] <file>
|
|
68
|
+
aontu fmt [-w|-l|--check|-d] <file>...
|
|
65
69
|
|
|
66
70
|
Evaluate an Aontu source file and print the result as JSON.
|
|
67
71
|
With no file on an interactive terminal, start a REPL.
|
|
@@ -84,6 +88,10 @@ Options:
|
|
|
84
88
|
Every verb takes it too, and a bare root means the
|
|
85
89
|
document's own directory
|
|
86
90
|
--include-root <dir> Shorthand for --trust root:<dir>
|
|
91
|
+
--text-ext <e> Read these extensions as text too, comma-separated
|
|
92
|
+
and without dots (md,sql). .txt needs no flag; a
|
|
93
|
+
named format keeps its meaning, and .js stays
|
|
94
|
+
refused. Every verb takes it
|
|
87
95
|
|
|
88
96
|
Mod options:
|
|
89
97
|
--format <f> text (default) or json
|
|
@@ -175,8 +183,8 @@ Why options:
|
|
|
175
183
|
Why exit codes mirror get's: 0 explained, 1 the path names nothing,
|
|
176
184
|
2 usage, 4 the document does not stand up on its own.
|
|
177
185
|
|
|
178
|
-
View kinds: tree, matrix, graph, layer, sets, layers,
|
|
179
|
-
(the poset takes several files). The figure goes to stdout, the loss
|
|
186
|
+
View kinds: doc, lattice, tree, matrix, graph, layer, sets, layers,
|
|
187
|
+
ladder, poset (the poset takes several files). The figure goes to stdout, the loss
|
|
180
188
|
report to stderr. With --views it draws every figure a document
|
|
181
189
|
declares as data, from one evaluation: each declaration names its own
|
|
182
190
|
kind and out file, nothing is written unless every figure rendered,
|
|
@@ -184,13 +192,13 @@ and --check gates the committed set.
|
|
|
184
192
|
|
|
185
193
|
View options:
|
|
186
194
|
--as <profile> text | mermaid | dot | er | svg, per kind: doc,
|
|
187
|
-
tree, matrix, sets and layers draw text
|
|
188
|
-
or svg; graph draws mermaid (default),
|
|
189
|
-
layer draws text (default), mermaid or
|
|
190
|
-
and poset draw mermaid (default) or dot
|
|
195
|
+
lattice, tree, matrix, sets and layers draw text
|
|
196
|
+
(default) or svg; graph draws mermaid (default),
|
|
197
|
+
dot or er; layer draws text (default), mermaid or
|
|
198
|
+
svg; ladder and poset draw mermaid (default) or dot
|
|
191
199
|
--at <path> Restrict the figure to nodes under this path; the
|
|
192
|
-
subtree doc draws; the
|
|
193
|
-
where the poset compares
|
|
200
|
+
subtree doc draws; the subtree the lattice counts;
|
|
201
|
+
the path the ladder draws; where the poset compares
|
|
194
202
|
--views <path> Draw every figure the document declares at this
|
|
195
203
|
path, one evaluation, all or nothing; each
|
|
196
204
|
declaration names its own kind and out file
|
|
@@ -269,6 +277,19 @@ Agentsmd options:
|
|
|
269
277
|
Agentsmd exit codes: 0 generated, 2 usage, 4 the document does not
|
|
270
278
|
stand up on its own.
|
|
271
279
|
|
|
280
|
+
Fmt options:
|
|
281
|
+
-w, --write Rewrite each file in place, when its form would change
|
|
282
|
+
-l, --list Print the name of each file whose form would change
|
|
283
|
+
--check Like --list, and exit 1 when any would: the CI gate
|
|
284
|
+
-d, --diff Print a unified diff for each file whose form would
|
|
285
|
+
change
|
|
286
|
+
|
|
287
|
+
The fmt verb prints one document in the agreed form; with no file it
|
|
288
|
+
reads standard input. Several files need one of the options above.
|
|
289
|
+
|
|
290
|
+
Fmt exit codes: 0 formatted or clean, 1 a --check file would change,
|
|
291
|
+
2 usage, 4 a document does not parse.
|
|
292
|
+
|
|
272
293
|
REPL commands:
|
|
273
294
|
:help Show REPL help
|
|
274
295
|
:load <file> Evaluate a document and hold it for the commands below
|
|
@@ -333,15 +354,16 @@ function makeTrustWarn() {
|
|
|
333
354
|
// entryRoot (the entry file's directory, or the working directory for
|
|
334
355
|
// stdin/REPL).
|
|
335
356
|
function trustOpts(trust, entryRoot) {
|
|
357
|
+
const text = 0 === trust.textExt.length ? {} : { textExt: trust.textExt };
|
|
336
358
|
switch (trust.kind) {
|
|
337
359
|
case 'none':
|
|
338
|
-
return { trust: { include: 'none' } };
|
|
360
|
+
return { ...text, trust: { include: 'none' } };
|
|
339
361
|
case 'root':
|
|
340
|
-
return { trust: { include: { root: trust.dir ?? entryRoot } } };
|
|
362
|
+
return { ...text, trust: { include: { root: trust.dir ?? entryRoot } } };
|
|
341
363
|
case 'system':
|
|
342
|
-
return {};
|
|
364
|
+
return { ...text };
|
|
343
365
|
default: // system-warn: today's default plus the warning window
|
|
344
|
-
return { trustWarn: makeTrustWarn(), trustWarnRoot: entryRoot };
|
|
366
|
+
return { ...text, trustWarn: makeTrustWarn(), trustWarnRoot: entryRoot };
|
|
345
367
|
}
|
|
346
368
|
}
|
|
347
369
|
// EVERY VERB honours the include capability, not just the bare
|
|
@@ -356,7 +378,8 @@ function trustOpts(trust, entryRoot) {
|
|
|
356
378
|
// already printed: the caller answers the usage class.
|
|
357
379
|
function takeTrust(argv) {
|
|
358
380
|
const rest = [];
|
|
359
|
-
let trust = { kind: 'system-warn' };
|
|
381
|
+
let trust = { kind: 'system-warn', textExt: [] };
|
|
382
|
+
let textExt = [];
|
|
360
383
|
for (let i = 0; i < argv.length; i++) {
|
|
361
384
|
const arg = argv[i];
|
|
362
385
|
if ('--trust' === arg) {
|
|
@@ -373,18 +396,42 @@ function takeTrust(argv) {
|
|
|
373
396
|
process.stderr.write('aontu: --include-root needs a directory\n');
|
|
374
397
|
return undefined;
|
|
375
398
|
}
|
|
376
|
-
trust = { kind: 'root', dir };
|
|
399
|
+
trust = { kind: 'root', dir, textExt };
|
|
400
|
+
}
|
|
401
|
+
else if ('--text-ext' === arg) {
|
|
402
|
+
const list = null == argv[i + 1] ? undefined : parseTextExt(argv[++i]);
|
|
403
|
+
if (null == list) {
|
|
404
|
+
process.stderr.write('aontu: --text-ext needs extensions, without dots' +
|
|
405
|
+
' (--text-ext md,sql)\n');
|
|
406
|
+
return undefined;
|
|
407
|
+
}
|
|
408
|
+
textExt = [...textExt, ...list];
|
|
377
409
|
}
|
|
378
410
|
else {
|
|
379
411
|
rest.push(arg);
|
|
380
412
|
}
|
|
381
413
|
}
|
|
382
|
-
return { argv: rest, trust };
|
|
414
|
+
return { argv: rest, trust: { ...trust, textExt } };
|
|
415
|
+
}
|
|
416
|
+
// `md,sql` or `.md,.sql` -- the dot is accepted and dropped, because a
|
|
417
|
+
// reader who has just written `@"notes.txt"` reaches for one. An empty
|
|
418
|
+
// element, or anything that is not an extension, is a usage error
|
|
419
|
+
// rather than a silently ignored word: a flag that quietly does
|
|
420
|
+
// nothing is how a document ends up refused with no reason visible.
|
|
421
|
+
function parseTextExt(arg) {
|
|
422
|
+
const out = [];
|
|
423
|
+
for (const raw of arg.split(',')) {
|
|
424
|
+
const ext = raw.trim().replace(/^\./, '').toLowerCase();
|
|
425
|
+
if ('' === ext || !/^[a-z0-9]+$/.test(ext)) {
|
|
426
|
+
return undefined;
|
|
427
|
+
}
|
|
428
|
+
out.push(ext);
|
|
429
|
+
}
|
|
430
|
+
return out;
|
|
383
431
|
}
|
|
384
432
|
// The evaluator options a REPL session's capability means.
|
|
385
433
|
function replTrust(state, entryRoot) {
|
|
386
|
-
|
|
387
|
-
return null == capability ? {} : { trust: capability };
|
|
434
|
+
return verbOpts(state.trust ?? { kind: 'system-warn', textExt: [] }, entryRoot);
|
|
388
435
|
}
|
|
389
436
|
// The capability a verb's engine runs under. `system` and the staged
|
|
390
437
|
// warning default both mean today's behaviour (no option); the warning
|
|
@@ -400,6 +447,18 @@ function verbTrust(trust, entryRoot) {
|
|
|
400
447
|
return undefined;
|
|
401
448
|
}
|
|
402
449
|
}
|
|
450
|
+
// THE INCLUDE OPTIONS A VERB RUNS UNDER, spread into its engine call:
|
|
451
|
+
// the capability above, and the extensions `--text-ext` widened. Both
|
|
452
|
+
// are absent when unset rather than present-and-undefined, so a verb's
|
|
453
|
+
// options bag is byte-identical to what it was before either flag
|
|
454
|
+
// existed and no engine sees a key it has to ignore.
|
|
455
|
+
function verbOpts(trust, entryRoot) {
|
|
456
|
+
const include = verbTrust(trust, entryRoot);
|
|
457
|
+
return {
|
|
458
|
+
...(undefined === include ? {} : { trust: include }),
|
|
459
|
+
...(0 === trust.textExt.length ? {} : { textExt: trust.textExt }),
|
|
460
|
+
};
|
|
461
|
+
}
|
|
403
462
|
// The directory a bare `--trust root` confines to for a verb: the
|
|
404
463
|
// primary document's own, matching the bare command's entry root.
|
|
405
464
|
function entryRootOf(file) {
|
|
@@ -505,7 +564,7 @@ function replCommand(state, line, read) {
|
|
|
505
564
|
if (':why' === cmd) {
|
|
506
565
|
const report = (0, aontu_1.why)(src, path, {
|
|
507
566
|
path: state.name,
|
|
508
|
-
|
|
567
|
+
...verbOpts(state.trust ?? { kind: 'system-warn', textExt: [] }, entryRootOf(state.name)),
|
|
509
568
|
});
|
|
510
569
|
return report.ok
|
|
511
570
|
? answer(renderWhyText(report.record))
|
|
@@ -515,7 +574,7 @@ function replCommand(state, line, read) {
|
|
|
515
574
|
? 'keys' : 'canon' === state.mode ? 'canon' : 'json';
|
|
516
575
|
const report = (0, aontu_1.get)(src, path, {
|
|
517
576
|
view, path: state.name,
|
|
518
|
-
|
|
577
|
+
...verbOpts(state.trust ?? { kind: 'system-warn', textExt: [] }, entryRootOf(state.name)),
|
|
519
578
|
});
|
|
520
579
|
return report.ok
|
|
521
580
|
? answer(report.out)
|
|
@@ -746,7 +805,7 @@ function vetOnce(args, trust) {
|
|
|
746
805
|
const findings = [];
|
|
747
806
|
for (const source of sources) {
|
|
748
807
|
const report = (0, aontu_1.vet)(schemaSrc, source.src, {
|
|
749
|
-
|
|
808
|
+
...verbOpts(trust, entryRootOf(args.schema)),
|
|
750
809
|
at: args.at,
|
|
751
810
|
closed: args.closed,
|
|
752
811
|
partial: args.partial,
|
|
@@ -985,7 +1044,7 @@ function runSubsume(argv) {
|
|
|
985
1044
|
return 2;
|
|
986
1045
|
}
|
|
987
1046
|
const report = (0, aontu_1.subsume)(generalSrc, specificSrc, {
|
|
988
|
-
|
|
1047
|
+
...verbOpts(trust, entryRootOf(args.general)),
|
|
989
1048
|
profile: args.profile,
|
|
990
1049
|
at: args.at,
|
|
991
1050
|
generalUrl: args.general,
|
|
@@ -1165,15 +1224,17 @@ function oldVersion(spec, file) {
|
|
|
1165
1224
|
// The document's own compatibility declaration: `$.aontu_policy.compat`,
|
|
1166
1225
|
// a disjunction whose default is the declared mode. Undefined when the
|
|
1167
1226
|
// key is absent or does not spell a mode.
|
|
1168
|
-
function policyCompat(newSrc, path,
|
|
1227
|
+
function policyCompat(newSrc, path, include) {
|
|
1169
1228
|
const aontu = new aontu_1.Aontu();
|
|
1170
1229
|
const ctx = aontu.ctx({ collect: true });
|
|
1171
1230
|
// The declaration is read by EVALUATING the document, so this leg
|
|
1172
|
-
// runs the include resolver too and has to run it under the
|
|
1173
|
-
//
|
|
1174
|
-
// through an unconfined resolver would confine the
|
|
1175
|
-
// not the question (use-cases/REVIEW.md finding G)
|
|
1176
|
-
|
|
1231
|
+
// runs the include resolver too and has to run it under BOTH of the
|
|
1232
|
+
// verb's include options -- a `breaking --trust none` that read its
|
|
1233
|
+
// own mode through an unconfined resolver would confine the
|
|
1234
|
+
// comparison and not the question (use-cases/REVIEW.md finding G),
|
|
1235
|
+
// and one that took the capability alone read no mode at all when
|
|
1236
|
+
// the declaration arrived through a `--text-ext` include.
|
|
1237
|
+
const v = aontu.unify(newSrc, { path, ...(0, utility_1.includeOpts)(include) }, ctx);
|
|
1177
1238
|
if (0 < ctx.err.length || true === v?.isNil) {
|
|
1178
1239
|
return undefined;
|
|
1179
1240
|
}
|
|
@@ -1266,7 +1327,7 @@ function runBreaking(argv) {
|
|
|
1266
1327
|
// neither means backward, the index's framing (v1-valid documents
|
|
1267
1328
|
// stay valid).
|
|
1268
1329
|
const mode = args.mode ??
|
|
1269
|
-
policyCompat(newSrc, args.file,
|
|
1330
|
+
policyCompat(newSrc, args.file, verbOpts(trust, entryRootOf(args.file))) ??
|
|
1270
1331
|
'backward';
|
|
1271
1332
|
if ('none' === mode) {
|
|
1272
1333
|
// The document declares no compatibility promise: nothing to check.
|
|
@@ -1309,7 +1370,7 @@ function runBreaking(argv) {
|
|
|
1309
1370
|
const oldPath = old.path;
|
|
1310
1371
|
for (const check of checks) {
|
|
1311
1372
|
const report = (0, aontu_1.subsume)(check.general[0], check.specific[0], {
|
|
1312
|
-
|
|
1373
|
+
...verbOpts(trust, entryRootOf(args.file)),
|
|
1313
1374
|
at: args.at,
|
|
1314
1375
|
generalUrl: check.general[1],
|
|
1315
1376
|
specificUrl: check.specific[1],
|
|
@@ -1439,7 +1500,7 @@ function runTrim(argv) {
|
|
|
1439
1500
|
return 2;
|
|
1440
1501
|
}
|
|
1441
1502
|
const report = (0, aontu_1.trimCheck)(src, {
|
|
1442
|
-
path: files[0],
|
|
1503
|
+
path: files[0], ...verbOpts(trust, entryRootOf(files[0])),
|
|
1443
1504
|
});
|
|
1444
1505
|
const text = 'json' === format
|
|
1445
1506
|
? renderTrimJson(report)
|
|
@@ -1490,8 +1551,8 @@ const REACHES_EXIT = {
|
|
|
1490
1551
|
error: 4,
|
|
1491
1552
|
};
|
|
1492
1553
|
const VIEW_HELP = 'aontu view <kind> [options] <file>... (try --help)';
|
|
1493
|
-
const VIEW_KINDS = ['doc', 'tree', 'matrix', 'graph', 'layer', 'sets', 'layers',
|
|
1494
|
-
'poset'];
|
|
1554
|
+
const VIEW_KINDS = ['doc', 'lattice', 'tree', 'matrix', 'graph', 'layer', 'sets', 'layers',
|
|
1555
|
+
'ladder', 'poset'];
|
|
1495
1556
|
const VIEW_PROFILES = ['text', 'mermaid', 'dot', 'er', 'svg'];
|
|
1496
1557
|
const VIEW_EDGES = ['upward', 'all', 'none'];
|
|
1497
1558
|
// The styles the CLI accepts (VIEWS.0.md, "7. Styling"). `auto` is
|
|
@@ -1764,7 +1825,7 @@ function runRelations(argv) {
|
|
|
1764
1825
|
return 2;
|
|
1765
1826
|
}
|
|
1766
1827
|
const report = (0, aontu_1.relationCheck)(src, {
|
|
1767
|
-
path: files[0],
|
|
1828
|
+
path: files[0], ...verbOpts(trust, entryRootOf(files[0])),
|
|
1768
1829
|
});
|
|
1769
1830
|
const text = 'json' === format
|
|
1770
1831
|
? renderRelationsJson(report)
|
|
@@ -1825,7 +1886,7 @@ function runReaches(argv) {
|
|
|
1825
1886
|
}
|
|
1826
1887
|
const report = (0, reach_1.reachCheck)(src, rest[0], rest[1], {
|
|
1827
1888
|
path: rest[2], relation,
|
|
1828
|
-
|
|
1889
|
+
...verbOpts(trust, entryRootOf(rest[2])),
|
|
1829
1890
|
});
|
|
1830
1891
|
const text = 'json' === format
|
|
1831
1892
|
? renderReachesJson(report)
|
|
@@ -2052,7 +2113,7 @@ function runView(argv) {
|
|
|
2052
2113
|
kind,
|
|
2053
2114
|
path: files[0],
|
|
2054
2115
|
roots,
|
|
2055
|
-
|
|
2116
|
+
...verbOpts(trust, entryRootOf(files[0])),
|
|
2056
2117
|
docs: files.slice(1).map((path, i) => ({ src: srcs[i + 1], path })),
|
|
2057
2118
|
});
|
|
2058
2119
|
if ('json' === format) {
|
|
@@ -2122,7 +2183,7 @@ function runViewSet(rest, opts, trust, how) {
|
|
|
2122
2183
|
return 2;
|
|
2123
2184
|
}
|
|
2124
2185
|
const report = (0, view_1.viewSet)(src, {
|
|
2125
|
-
...opts, path: file,
|
|
2186
|
+
...opts, path: file, ...verbOpts(trust, entryRootOf(file)),
|
|
2126
2187
|
});
|
|
2127
2188
|
if ('json' === how.format) {
|
|
2128
2189
|
process.stdout.write(renderViewSetJson(report) + '\n');
|
|
@@ -2319,7 +2380,7 @@ function runJsonSchema(argv) {
|
|
|
2319
2380
|
return 2;
|
|
2320
2381
|
}
|
|
2321
2382
|
const report = (0, jsonschema_1.jsonSchema)(src, {
|
|
2322
|
-
at, path: files[0],
|
|
2383
|
+
at, path: files[0], ...verbOpts(trust, entryRootOf(files[0])),
|
|
2323
2384
|
});
|
|
2324
2385
|
if ('json' === format) {
|
|
2325
2386
|
process.stdout.write((0, aontu_1.exactJSON)({
|
|
@@ -2402,8 +2463,7 @@ function runHash(argv) {
|
|
|
2402
2463
|
}
|
|
2403
2464
|
// The file's own directory is the include base, as every verb
|
|
2404
2465
|
// resolves a named file (vet's aontuForPath rule).
|
|
2405
|
-
const
|
|
2406
|
-
const aontu = new aontu_1.Aontu(null == capability ? undefined : { trust: capability });
|
|
2466
|
+
const aontu = new aontu_1.Aontu(verbOpts(trust, entryRootOf(files[0])));
|
|
2407
2467
|
const ctx = aontu.ctx({ collect: true });
|
|
2408
2468
|
const v = aontu.unify(src, { path: files[0] }, ctx);
|
|
2409
2469
|
if (0 < ctx.err.length || true === v?.isNil) {
|
|
@@ -2507,7 +2567,7 @@ function runGet(argv) {
|
|
|
2507
2567
|
return 2;
|
|
2508
2568
|
}
|
|
2509
2569
|
const report = (0, aontu_1.get)(src, path, {
|
|
2510
|
-
view, depth, path: file,
|
|
2570
|
+
view, depth, path: file, ...verbOpts(trust, entryRootOf(file)),
|
|
2511
2571
|
});
|
|
2512
2572
|
if ('json' === format) {
|
|
2513
2573
|
process.stdout.write((0, aontu_1.exactJSON)({
|
|
@@ -2582,7 +2642,7 @@ function runWhy(argv) {
|
|
|
2582
2642
|
return 2;
|
|
2583
2643
|
}
|
|
2584
2644
|
const report = (0, aontu_1.why)(src, path, {
|
|
2585
|
-
path: file,
|
|
2645
|
+
path: file, ...verbOpts(trust, entryRootOf(file)),
|
|
2586
2646
|
});
|
|
2587
2647
|
if ('json' === format) {
|
|
2588
2648
|
process.stdout.write((0, aontu_1.exactJSON)({
|
|
@@ -2703,7 +2763,7 @@ function runSet(argv) {
|
|
|
2703
2763
|
}
|
|
2704
2764
|
}
|
|
2705
2765
|
const report = (0, aontu_1.patch)(entrySrc, overlaySrc, assignments, {
|
|
2706
|
-
|
|
2766
|
+
...verbOpts(trust, entryRootOf(entry)),
|
|
2707
2767
|
entryPath: entry,
|
|
2708
2768
|
overlayPath: overlayFile,
|
|
2709
2769
|
inPlace,
|
|
@@ -2823,7 +2883,7 @@ function runAgentsMd(argv) {
|
|
|
2823
2883
|
}
|
|
2824
2884
|
const report = (0, aontu_1.agentsMd)(src, {
|
|
2825
2885
|
name: files[0], path: files[0],
|
|
2826
|
-
|
|
2886
|
+
...verbOpts(trust, entryRootOf(files[0])),
|
|
2827
2887
|
});
|
|
2828
2888
|
if (!report.ok) {
|
|
2829
2889
|
process.stderr.write(report.findings.map(renderFinding).join('\n') + '\n');
|
|
@@ -2869,6 +2929,116 @@ function runAgentsMd(argv) {
|
|
|
2869
2929
|
// on the parity-probe discipline in AGENTS.md, which derives expected
|
|
2870
2930
|
// spec values by piping BOTH CLIs and comparing. A truncated pipe there
|
|
2871
2931
|
// reads as a port divergence.
|
|
2932
|
+
// ---------------------------------------------------------------------
|
|
2933
|
+
// The source formatter (docs/design/FMT.0.md): one agreed form, in the
|
|
2934
|
+
// tradition of gofmt. The verb prints, lists, checks, diffs or rewrites;
|
|
2935
|
+
// the form itself is the library's (ts/src/format.ts), and the two
|
|
2936
|
+
// ports agree on it row by row in test/spec/fmt.tsv.
|
|
2937
|
+
const FMT_HELP = 'aontu fmt [-w|-l|--check|-d] <file>... (try --help)';
|
|
2938
|
+
function runFmt(argv) {
|
|
2939
|
+
const files = [];
|
|
2940
|
+
const flags = { write: false, list: false, check: false, diff: false };
|
|
2941
|
+
for (const arg of argv) {
|
|
2942
|
+
if ('-h' === arg || '--help' === arg) {
|
|
2943
|
+
process.stdout.write(HELP);
|
|
2944
|
+
return 0;
|
|
2945
|
+
}
|
|
2946
|
+
if ('-w' === arg || '--write' === arg) {
|
|
2947
|
+
flags.write = true;
|
|
2948
|
+
}
|
|
2949
|
+
else if ('-l' === arg || '--list' === arg) {
|
|
2950
|
+
flags.list = true;
|
|
2951
|
+
}
|
|
2952
|
+
else if ('--check' === arg) {
|
|
2953
|
+
flags.check = true;
|
|
2954
|
+
}
|
|
2955
|
+
else if ('-d' === arg || '--diff' === arg) {
|
|
2956
|
+
flags.diff = true;
|
|
2957
|
+
}
|
|
2958
|
+
else if (arg.startsWith('-')) {
|
|
2959
|
+
process.stderr.write(`aontu: unknown fmt option ${arg} (try --help)\n`);
|
|
2960
|
+
return 2;
|
|
2961
|
+
}
|
|
2962
|
+
else {
|
|
2963
|
+
files.push(arg);
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
if (0 === files.length) {
|
|
2967
|
+
// Standard input: formatted onto standard output, or listed,
|
|
2968
|
+
// checked and diffed under the name <stdin>. It cannot be written
|
|
2969
|
+
// back.
|
|
2970
|
+
if (flags.write) {
|
|
2971
|
+
process.stderr.write(`aontu: --write needs a file\n${FMT_HELP}\n`);
|
|
2972
|
+
return 2;
|
|
2973
|
+
}
|
|
2974
|
+
return new Promise((resolve) => {
|
|
2975
|
+
let src = '';
|
|
2976
|
+
process.stdin.setEncoding('utf8');
|
|
2977
|
+
process.stdin.on('data', (d) => (src += d));
|
|
2978
|
+
process.stdin.on('end', () => resolve(fmtOne('<stdin>', src, flags)));
|
|
2979
|
+
});
|
|
2980
|
+
}
|
|
2981
|
+
// Several files onto standard output would be one stream nobody can
|
|
2982
|
+
// split again (the note's X-6): the verb refuses unless an option
|
|
2983
|
+
// says what to do with each.
|
|
2984
|
+
if (1 < files.length && !fmtQuiet(flags)) {
|
|
2985
|
+
process.stderr.write(`aontu: fmt prints one file; with ${files.length}, say --write, ` +
|
|
2986
|
+
`--list, --check or --diff\n${FMT_HELP}\n`);
|
|
2987
|
+
return 2;
|
|
2988
|
+
}
|
|
2989
|
+
let worst = 0;
|
|
2990
|
+
for (const file of files) {
|
|
2991
|
+
let src;
|
|
2992
|
+
try {
|
|
2993
|
+
src = (0, node_fs_1.readFileSync)(file, 'utf8');
|
|
2994
|
+
}
|
|
2995
|
+
catch (err) {
|
|
2996
|
+
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2997
|
+
return 2;
|
|
2998
|
+
}
|
|
2999
|
+
worst = Math.max(worst, fmtOne(file, src, flags));
|
|
3000
|
+
}
|
|
3001
|
+
return worst;
|
|
3002
|
+
}
|
|
3003
|
+
// An option that says what to do with a file that would change, in
|
|
3004
|
+
// place of printing it.
|
|
3005
|
+
function fmtQuiet(flags) {
|
|
3006
|
+
return flags.write || flags.list || flags.check || flags.diff;
|
|
3007
|
+
}
|
|
3008
|
+
// One document: 0 printed, clean or done; 1 a --check that would
|
|
3009
|
+
// change; 2 a file that cannot be written; 4 a document that does not
|
|
3010
|
+
// format, with the finding that says why.
|
|
3011
|
+
function fmtOne(name, src, flags) {
|
|
3012
|
+
const report = (0, format_1.format)(src, { path: name });
|
|
3013
|
+
if ('error' === report.verdict) {
|
|
3014
|
+
process.stderr.write(`aontu: ${name} was not formatted\n` +
|
|
3015
|
+
report.errors.map(renderFinding).join('\n') + '\n');
|
|
3016
|
+
return 4;
|
|
3017
|
+
}
|
|
3018
|
+
if (!fmtQuiet(flags)) {
|
|
3019
|
+
process.stdout.write(report.text);
|
|
3020
|
+
return 0;
|
|
3021
|
+
}
|
|
3022
|
+
if (!report.changed) {
|
|
3023
|
+
return 0;
|
|
3024
|
+
}
|
|
3025
|
+
if (flags.list || flags.check) {
|
|
3026
|
+
process.stdout.write(name + '\n');
|
|
3027
|
+
}
|
|
3028
|
+
if (flags.diff) {
|
|
3029
|
+
process.stdout.write((0, format_1.unifiedDiff)(name, src, report.text));
|
|
3030
|
+
}
|
|
3031
|
+
if (flags.write) {
|
|
3032
|
+
try {
|
|
3033
|
+
(0, node_fs_1.writeFileSync)(name, report.text);
|
|
3034
|
+
}
|
|
3035
|
+
catch (err) {
|
|
3036
|
+
process.stderr.write(`aontu: cannot write ${name}: ${err.message}\n`);
|
|
3037
|
+
return 2;
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
return flags.check ? 1 : 0;
|
|
3041
|
+
}
|
|
2872
3042
|
function finish(code) {
|
|
2873
3043
|
process.exitCode = code;
|
|
2874
3044
|
}
|
|
@@ -2876,16 +3046,16 @@ function finish(code) {
|
|
|
2876
3046
|
// spelling, so the caller owns the usage error.
|
|
2877
3047
|
function parseTrustArg(value) {
|
|
2878
3048
|
if ('system' === value) {
|
|
2879
|
-
return { kind: 'system' };
|
|
3049
|
+
return { kind: 'system', textExt: [] };
|
|
2880
3050
|
}
|
|
2881
3051
|
if ('none' === value) {
|
|
2882
|
-
return { kind: 'none' };
|
|
3052
|
+
return { kind: 'none', textExt: [] };
|
|
2883
3053
|
}
|
|
2884
3054
|
if ('root' === value) {
|
|
2885
|
-
return { kind: 'root' };
|
|
3055
|
+
return { kind: 'root', textExt: [] };
|
|
2886
3056
|
}
|
|
2887
3057
|
if (value.startsWith('root:') && 'root:'.length < value.length) {
|
|
2888
|
-
return { kind: 'root', dir: value.slice('root:'.length) };
|
|
3058
|
+
return { kind: 'root', dir: value.slice('root:'.length), textExt: [] };
|
|
2889
3059
|
}
|
|
2890
3060
|
return undefined;
|
|
2891
3061
|
}
|
|
@@ -2906,7 +3076,8 @@ function main(argv) {
|
|
|
2906
3076
|
// overwritten twice. In a tool loop that reads as a passing
|
|
2907
3077
|
// validation. Counting them is what lets the refusal below happen.
|
|
2908
3078
|
const files = [];
|
|
2909
|
-
let trust = { kind: 'system-warn' };
|
|
3079
|
+
let trust = { kind: 'system-warn', textExt: [] };
|
|
3080
|
+
let textExt = [];
|
|
2910
3081
|
// The REPL's SESSION protocol (G7 phase 7): one JSON line per
|
|
2911
3082
|
// answer, so a harness can drive the session. Named --jsonl rather
|
|
2912
3083
|
// than the design's --json, which would read as the `:json` output
|
|
@@ -2933,6 +3104,9 @@ function main(argv) {
|
|
|
2933
3104
|
if ('agentsmd' === argv[2]) {
|
|
2934
3105
|
return finish(runAgentsMd(argv.slice(3)));
|
|
2935
3106
|
}
|
|
3107
|
+
if ('fmt' === argv[2]) {
|
|
3108
|
+
return void Promise.resolve(runFmt(argv.slice(3))).then(finish);
|
|
3109
|
+
}
|
|
2936
3110
|
if ('set' === argv[2]) {
|
|
2937
3111
|
return finish(runSet(argv.slice(3)));
|
|
2938
3112
|
}
|
|
@@ -3000,7 +3174,16 @@ function main(argv) {
|
|
|
3000
3174
|
process.stderr.write('aontu: --include-root needs a directory\n');
|
|
3001
3175
|
return finish(2);
|
|
3002
3176
|
}
|
|
3003
|
-
trust = { kind: 'root', dir };
|
|
3177
|
+
trust = { kind: 'root', dir, textExt };
|
|
3178
|
+
}
|
|
3179
|
+
else if ('--text-ext' === arg) {
|
|
3180
|
+
const list = null == args[i + 1] ? undefined : parseTextExt(args[++i]);
|
|
3181
|
+
if (null == list) {
|
|
3182
|
+
process.stderr.write('aontu: --text-ext needs extensions, without dots' +
|
|
3183
|
+
' (--text-ext md,sql)\n');
|
|
3184
|
+
return finish(2);
|
|
3185
|
+
}
|
|
3186
|
+
textExt = [...textExt, ...list];
|
|
3004
3187
|
}
|
|
3005
3188
|
else if (arg.startsWith('-')) {
|
|
3006
3189
|
process.stderr.write(`aontu: unknown option ${arg} (try --help)\n`);
|
|
@@ -3024,6 +3207,10 @@ function main(argv) {
|
|
|
3024
3207
|
' (try --help)\n');
|
|
3025
3208
|
return finish(2);
|
|
3026
3209
|
}
|
|
3210
|
+
// The extensions ride with the capability from here on, so the three
|
|
3211
|
+
// entry shapes below (file, REPL, stdin) each get them by threading
|
|
3212
|
+
// the one value they already thread.
|
|
3213
|
+
trust = { ...trust, textExt };
|
|
3027
3214
|
const file = files[0];
|
|
3028
3215
|
if (null != file) {
|
|
3029
3216
|
finish(runFile(file, mode, trust));
|