aontu 0.62.0 → 0.63.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 +1 -1
- package/dist/agentsmd.js +0 -27
- package/dist/agentsmd.js.map +1 -1
- package/dist/alias.js.map +1 -1
- package/dist/allow.js +0 -92
- package/dist/allow.js.map +1 -1
- package/dist/aontu.d.ts +1 -1
- package/dist/aontu.js +1 -79
- package/dist/aontu.js.map +1 -1
- package/dist/aontumodel.d.ts +4 -0
- package/dist/aontumodel.js +33 -0
- package/dist/aontumodel.js.map +1 -0
- package/dist/cli.js +101 -620
- package/dist/cli.js.map +1 -1
- package/dist/ctx.js +0 -48
- package/dist/ctx.js.map +1 -1
- package/dist/diff.js +0 -32
- package/dist/diff.js.map +1 -1
- package/dist/err.js +0 -40
- package/dist/err.js.map +1 -1
- package/dist/escape.js +0 -45
- package/dist/escape.js.map +1 -1
- package/dist/exactjson.d.ts +0 -35
- package/dist/exactjson.js +0 -131
- package/dist/exactjson.js.map +1 -1
- package/dist/format.js +13 -203
- package/dist/format.js.map +1 -1
- package/dist/grammar.d.ts +9 -0
- package/dist/grammar.js +54 -0
- package/dist/grammar.js.map +1 -0
- package/dist/graph.js +0 -26
- package/dist/graph.js.map +1 -1
- package/dist/hcanon.js +0 -82
- package/dist/hcanon.js.map +1 -1
- package/dist/helpdoc.js +1 -1
- package/dist/helpdoc.js.map +1 -1
- package/dist/hints.d.ts +0 -6
- package/dist/hints.js +54 -55
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.js +0 -114
- package/dist/jsonschema.js.map +1 -1
- package/dist/keyorder.d.ts +0 -7
- package/dist/keyorder.js +0 -41
- package/dist/keyorder.js.map +1 -1
- package/dist/lang.js +17 -915
- package/dist/lang.js.map +1 -1
- package/dist/lower.js +11 -61
- package/dist/lower.js.map +1 -1
- package/dist/lsp-server.js +0 -16
- package/dist/lsp-server.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/lsp.js +12 -159
- package/dist/lsp.js.map +1 -1
- package/dist/mcp-server.js +0 -26
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp.js +0 -113
- package/dist/mcp.js.map +1 -1
- package/dist/mod-tool.js +0 -130
- package/dist/mod-tool.js.map +1 -1
- package/dist/mod.js +0 -162
- package/dist/mod.js.map +1 -1
- package/dist/patch.js +0 -217
- package/dist/patch.js.map +1 -1
- package/dist/provenance.js +0 -140
- package/dist/provenance.js.map +1 -1
- package/dist/query.js +0 -75
- package/dist/query.js.map +1 -1
- package/dist/reach.js +0 -43
- package/dist/reach.js.map +1 -1
- package/dist/relation.js +0 -61
- package/dist/relation.js.map +1 -1
- package/dist/render.js +20 -135
- package/dist/render.js.map +1 -1
- package/dist/report-sarif.d.ts +0 -11
- package/dist/report-sarif.js +0 -28
- package/dist/report-sarif.js.map +1 -1
- package/dist/sig.js +0 -35
- package/dist/sig.js.map +1 -1
- package/dist/sigdecl.js +1 -1
- package/dist/sigdecl.js.map +1 -1
- package/dist/siggate.js +0 -4
- package/dist/siggate.js.map +1 -1
- package/dist/site.js +3 -29
- package/dist/site.js.map +1 -1
- package/dist/subsume.d.ts +0 -10
- package/dist/subsume.js +0 -137
- package/dist/subsume.js.map +1 -1
- package/dist/template.d.ts +2 -1
- package/dist/template.js +58 -138
- package/dist/template.js.map +1 -1
- package/dist/trim.js +0 -41
- package/dist/trim.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.js.map +1 -1
- package/dist/unify.js +12 -242
- package/dist/unify.js.map +1 -1
- package/dist/utility.js +0 -22
- package/dist/utility.js.map +1 -1
- package/dist/val/AbnfFuncVal.d.ts +18 -0
- package/dist/val/AbnfFuncVal.js +132 -0
- package/dist/val/AbnfFuncVal.js.map +1 -0
- package/dist/val/AbsentVal.d.ts +11 -0
- package/dist/val/AbsentVal.js +30 -0
- package/dist/val/AbsentVal.js.map +1 -0
- package/dist/val/AggFuncVal.d.ts +10 -1
- package/dist/val/AggFuncVal.js +104 -116
- package/dist/val/AggFuncVal.js.map +1 -1
- package/dist/val/ArithFuncVal.js +0 -12
- package/dist/val/ArithFuncVal.js.map +1 -1
- package/dist/val/BagVal.js +1 -78
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/BigDecimalVal.js +0 -16
- package/dist/val/BigDecimalVal.js.map +1 -1
- package/dist/val/BigIntegerVal.js +0 -16
- package/dist/val/BigIntegerVal.js.map +1 -1
- package/dist/val/CloseFuncVal.js +0 -9
- package/dist/val/CloseFuncVal.js.map +1 -1
- package/dist/val/CmpFuncVal.js +2 -59
- package/dist/val/CmpFuncVal.js.map +1 -1
- package/dist/val/ConjunctVal.js +0 -29
- package/dist/val/ConjunctVal.js.map +1 -1
- package/dist/val/ConstraintVal.js +0 -500
- package/dist/val/ConstraintVal.js.map +1 -1
- package/dist/val/ContainerKindVal.js +0 -2
- package/dist/val/ContainerKindVal.js.map +1 -1
- package/dist/val/CopyFuncVal.js +0 -3
- package/dist/val/CopyFuncVal.js.map +1 -1
- package/dist/val/Decimal.js +0 -179
- package/dist/val/Decimal.js.map +1 -1
- package/dist/val/DeprecateFuncVal.js.map +1 -1
- package/dist/val/DisjunctVal.js +0 -152
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/EachFuncVal.js +0 -3
- package/dist/val/EachFuncVal.js.map +1 -1
- package/dist/val/EmitFuncVal.d.ts +1 -1
- package/dist/val/EmitFuncVal.js +6 -119
- package/dist/val/EmitFuncVal.js.map +1 -1
- package/dist/val/ExpectVal.js +0 -62
- package/dist/val/ExpectVal.js.map +1 -1
- package/dist/val/FilterFuncVal.js +0 -25
- package/dist/val/FilterFuncVal.js.map +1 -1
- package/dist/val/FuncBaseVal.d.ts +1 -0
- package/dist/val/FuncBaseVal.js +7 -127
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/GraphAtomVal.js +0 -15
- package/dist/val/GraphAtomVal.js.map +1 -1
- package/dist/val/HideFuncVal.js +0 -13
- package/dist/val/HideFuncVal.js.map +1 -1
- package/dist/val/IntegerVal.js +0 -61
- package/dist/val/IntegerVal.js.map +1 -1
- package/dist/val/JunctionVal.js +0 -20
- package/dist/val/JunctionVal.js.map +1 -1
- package/dist/val/KeyFuncVal.js +0 -46
- package/dist/val/KeyFuncVal.js.map +1 -1
- package/dist/val/ListVal.js +0 -57
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js +0 -11
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +0 -151
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MatchFuncVal.js +0 -27
- package/dist/val/MatchFuncVal.js.map +1 -1
- package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
- package/dist/val/MaybeFuncVal.js +50 -0
- package/dist/val/MaybeFuncVal.js.map +1 -0
- package/dist/val/MoveFuncVal.js +0 -18
- package/dist/val/MoveFuncVal.js.map +1 -1
- package/dist/val/NilVal.js +0 -60
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/NomFuncVal.js +8 -42
- package/dist/val/NomFuncVal.js.map +1 -1
- package/dist/val/NumberVal.js +0 -15
- package/dist/val/NumberVal.js.map +1 -1
- package/dist/val/OpBaseVal.d.ts +1 -0
- package/dist/val/OpBaseVal.js +3 -15
- package/dist/val/OpBaseVal.js.map +1 -1
- package/dist/val/PackFuncVal.js +0 -34
- package/dist/val/PackFuncVal.js.map +1 -1
- package/dist/val/PathFuncVal.js +0 -6
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PathVal.js +0 -41
- package/dist/val/PathVal.js.map +1 -1
- package/dist/val/PlaceVal.js +0 -25
- package/dist/val/PlaceVal.js.map +1 -1
- package/dist/val/PlusOpVal.d.ts +1 -7
- package/dist/val/PlusOpVal.js +13 -74
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefFuncVal.js +0 -1
- package/dist/val/PrefFuncVal.js.map +1 -1
- package/dist/val/PrefVal.js +0 -167
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RecurseVal.js +0 -55
- package/dist/val/RecurseVal.js.map +1 -1
- package/dist/val/RefVal.js +0 -282
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ReferFuncVal.js +0 -232
- package/dist/val/ReferFuncVal.js.map +1 -1
- package/dist/val/ScalarKindVal.js +0 -49
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/ScalarVal.js +0 -11
- package/dist/val/ScalarVal.js.map +1 -1
- package/dist/val/StrFuncVal.js +0 -18
- package/dist/val/StrFuncVal.js.map +1 -1
- package/dist/val/SuperFuncVal.js +0 -32
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/TopVal.js +0 -1
- package/dist/val/TopVal.js.map +1 -1
- package/dist/val/TranslateFuncVal.js +1 -3
- package/dist/val/TranslateFuncVal.js.map +1 -1
- package/dist/val/UpperFuncVal.js +0 -11
- package/dist/val/UpperFuncVal.js.map +1 -1
- package/dist/val/Val.d.ts +1 -0
- package/dist/val/Val.js +2 -133
- package/dist/val/Val.js.map +1 -1
- package/dist/val/VarVal.js +0 -12
- package/dist/val/VarVal.js.map +1 -1
- package/dist/val/arith.js +0 -37
- package/dist/val/arith.js.map +1 -1
- package/dist/val/caserange.js +0 -61
- package/dist/val/caserange.js.map +1 -1
- package/dist/val/members.js +0 -6
- package/dist/val/members.js.map +1 -1
- package/dist/val/numcmp.js +0 -11
- package/dist/val/numcmp.js.map +1 -1
- package/dist/val/numkind.js +0 -145
- package/dist/val/numkind.js.map +1 -1
- package/dist/val/valutil.js +0 -16
- package/dist/val/valutil.js.map +1 -1
- package/dist/vet.js +0 -461
- package/dist/vet.js.map +1 -1
- package/dist/view.js +0 -414
- package/dist/view.js.map +1 -1
- package/dist/walk.js +0 -41
- package/dist/walk.js.map +1 -1
- package/grammar/aontu.abnf +8 -6
- package/grammar/aontu.gbnf +4 -4
- package/grammar/aontu.lark +4 -4
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +4 -2
- package/src/agentsmd.ts +0 -35
- package/src/alias.ts +0 -39
- package/src/allow.ts +1 -96
- package/src/aontu.ts +3 -110
- package/src/aontumodel.ts +32 -0
- package/src/cli.ts +113 -682
- package/src/ctx.ts +0 -103
- package/src/diff.ts +0 -40
- package/src/err.ts +0 -40
- package/src/escape.ts +0 -46
- package/src/exactjson.ts +0 -131
- package/src/format.ts +14 -257
- package/src/grammar.ts +72 -0
- package/src/graph.ts +0 -61
- package/src/hcanon.ts +0 -82
- package/src/helpdoc.ts +1 -1
- package/src/hints.ts +66 -57
- package/src/jsonschema.ts +0 -123
- package/src/keyorder.ts +0 -42
- package/src/lang.ts +19 -931
- package/src/lower.ts +12 -62
- package/src/lsp-server.ts +0 -16
- package/src/lsp.ts +12 -180
- package/src/mcp-server.ts +0 -31
- package/src/mcp.ts +0 -130
- package/src/mod-tool.ts +0 -158
- package/src/mod.ts +0 -178
- package/src/patch.ts +0 -232
- package/src/provenance.ts +0 -183
- package/src/query.ts +0 -84
- package/src/reach.ts +0 -53
- package/src/relation.ts +0 -84
- package/src/render.ts +20 -172
- package/src/report-sarif.ts +0 -48
- package/src/sig.ts +0 -35
- package/src/sigdecl.ts +1 -1
- package/src/siggate.ts +0 -30
- package/src/site.ts +3 -29
- package/src/subsume.ts +1 -161
- package/src/template.ts +69 -140
- package/src/trim.ts +0 -53
- package/src/type.ts +2 -45
- package/src/unify.ts +13 -251
- package/src/utility.ts +0 -31
- package/src/val/AbnfFuncVal.ts +181 -0
- package/src/val/AbsentVal.ts +54 -0
- package/src/val/AggFuncVal.ts +152 -188
- package/src/val/ArithFuncVal.ts +0 -20
- package/src/val/BagVal.ts +1 -78
- package/src/val/BigDecimalVal.ts +0 -16
- package/src/val/BigIntegerVal.ts +0 -16
- package/src/val/CloseFuncVal.ts +0 -9
- package/src/val/CmpFuncVal.ts +4 -166
- package/src/val/ConjunctVal.ts +0 -33
- package/src/val/ConstraintVal.ts +2 -537
- package/src/val/ContainerKindVal.ts +0 -18
- package/src/val/CopyFuncVal.ts +0 -5
- package/src/val/Decimal.ts +1 -185
- package/src/val/DeprecateFuncVal.ts +0 -10
- package/src/val/DisjunctVal.ts +0 -157
- package/src/val/EachFuncVal.ts +0 -40
- package/src/val/EmitFuncVal.ts +8 -208
- package/src/val/ExpectVal.ts +0 -62
- package/src/val/FilterFuncVal.ts +0 -55
- package/src/val/FuncBaseVal.ts +9 -130
- package/src/val/GraphAtomVal.ts +0 -42
- package/src/val/HideFuncVal.ts +0 -15
- package/src/val/IntegerVal.ts +0 -61
- package/src/val/JunctionVal.ts +0 -20
- package/src/val/KeyFuncVal.ts +0 -48
- package/src/val/ListVal.ts +0 -59
- package/src/val/LowerFuncVal.ts +0 -12
- package/src/val/MapVal.ts +0 -151
- package/src/val/MatchFuncVal.ts +0 -59
- package/src/val/MaybeFuncVal.ts +86 -0
- package/src/val/MoveFuncVal.ts +0 -20
- package/src/val/NilVal.ts +0 -60
- package/src/val/NomFuncVal.ts +8 -95
- package/src/val/NumberVal.ts +0 -16
- package/src/val/OpBaseVal.ts +4 -17
- package/src/val/PackFuncVal.ts +0 -63
- package/src/val/PathFuncVal.ts +0 -32
- package/src/val/PathVal.ts +0 -66
- package/src/val/PlaceVal.ts +0 -45
- package/src/val/PlusOpVal.ts +18 -75
- package/src/val/PrefFuncVal.ts +0 -1
- package/src/val/PrefVal.ts +0 -179
- package/src/val/RecurseVal.ts +0 -81
- package/src/val/RefVal.ts +1 -285
- package/src/val/ReferFuncVal.ts +0 -255
- package/src/val/ScalarKindVal.ts +0 -50
- package/src/val/ScalarVal.ts +0 -12
- package/src/val/StrFuncVal.ts +0 -44
- package/src/val/SuperFuncVal.ts +0 -42
- package/src/val/TopVal.ts +0 -1
- package/src/val/TranslateFuncVal.ts +1 -51
- package/src/val/UpperFuncVal.ts +0 -12
- package/src/val/Val.ts +3 -192
- package/src/val/VarVal.ts +0 -15
- package/src/val/arith.ts +0 -92
- package/src/val/caserange.ts +0 -62
- package/src/val/members.ts +0 -23
- package/src/val/numcmp.ts +1 -27
- package/src/val/numkind.ts +0 -149
- package/src/val/valutil.ts +0 -16
- package/src/vet.ts +1 -582
- package/src/view.ts +0 -507
- package/src/walk.ts +0 -41
- package/dist/std.d.ts +0 -3
- package/dist/std.js +0 -672
- package/dist/std.js.map +0 -1
- package/dist/val/FormFuncVal.js +0 -55
- package/dist/val/FormFuncVal.js.map +0 -1
- package/dist/val/NamerFuncVal.d.ts +0 -12
- package/dist/val/NamerFuncVal.js +0 -176
- package/dist/val/NamerFuncVal.js.map +0 -1
- package/src/std.ts +0 -683
package/dist/cli.js
CHANGED
|
@@ -32,13 +32,6 @@ exports.runFmt = runFmt;
|
|
|
32
32
|
exports.watchChange = watchChange;
|
|
33
33
|
exports.watchSignature = watchSignature;
|
|
34
34
|
exports.deprecatedAt = deprecatedAt;
|
|
35
|
-
// Command-line interface for Aontu.
|
|
36
|
-
//
|
|
37
|
-
// aontu [options] [file]
|
|
38
|
-
//
|
|
39
|
-
// With a file argument, the file is evaluated and the result printed.
|
|
40
|
-
// With no file on an interactive terminal, a REPL is started. With no
|
|
41
|
-
// file and piped input, the source is read from stdin. See HELP below.
|
|
42
35
|
// Named imports, not `import * as`: the namespace form makes tsc emit the
|
|
43
36
|
const query_1 = require("./query");
|
|
44
37
|
// __importStar downlevel helper, whose branches no supported Node takes.
|
|
@@ -77,7 +70,8 @@ const HELP = `Usage: aontu [options] [file]
|
|
|
77
70
|
aontu render [--at <path>] [--profile <file>]... [--unit <path>]
|
|
78
71
|
[--stdout | --out <dir> | --check <dir> | --coverage]
|
|
79
72
|
[--coverage-at <path>] [--strict] <file>
|
|
80
|
-
aontu template [--resugar] [--check] [--marker <token>]
|
|
73
|
+
aontu template [--resugar] [--check] [--marker <token>]
|
|
74
|
+
[--profile <file>] <file>
|
|
81
75
|
aontu hash [options] <file>
|
|
82
76
|
aontu mod tidy|verify|vendor|manifest [options] [dir]
|
|
83
77
|
aontu get <path> [options] <file>
|
|
@@ -85,7 +79,8 @@ const HELP = `Usage: aontu [options] [file]
|
|
|
85
79
|
aontu set <path>=<value>... --entry <file> --overlay <file>
|
|
86
80
|
aontu allow --role <role> [--at <path>] <roles-file> <path>...
|
|
87
81
|
aontu agentsmd [--write <AGENTS.md>] [--depth <n>] <file>
|
|
88
|
-
aontu fmt [-w|-l|--check|-d|--lint] [--marker <token>]
|
|
82
|
+
aontu fmt [-w|-l|--check|-d|--lint] [--marker <token>]
|
|
83
|
+
[--profile <file>] <file>...
|
|
89
84
|
aontu help [topic] [--format text|json]
|
|
90
85
|
aontu explain <code> | --list [--format text|json]
|
|
91
86
|
aontu init [dir]
|
|
@@ -325,8 +320,9 @@ up on its own, or a relation, root or path that names nothing.
|
|
|
325
320
|
Render options:
|
|
326
321
|
--at <path> Render the value at this path ($.a.b); the root by
|
|
327
322
|
default
|
|
328
|
-
--profile <file> A profile document,
|
|
329
|
-
against aontu:
|
|
323
|
+
--profile <file> A profile document, aontu: render: Lang: {lang,
|
|
324
|
+
...}, vetted against aontu:render; repeatable,
|
|
325
|
+
one per language
|
|
330
326
|
--unit <path> Render only the unit with this path
|
|
331
327
|
--stdout One unit's bytes and nothing else (with --unit when
|
|
332
328
|
the instance has several)
|
|
@@ -350,8 +346,8 @@ does not stand up or the instance is not aontu:code.
|
|
|
350
346
|
A render entry file whose extension is not .aon is a TEMPLATE: a
|
|
351
347
|
generator in the target's own syntax, whose marker lines carry aontu
|
|
352
348
|
and whose other lines are output. It is desugared before it is
|
|
353
|
-
evaluated, and
|
|
354
|
-
|
|
349
|
+
evaluated, and a language the table does not know names its marker with
|
|
350
|
+
--marker, or declares it once in a profile file that --profile reads.
|
|
355
351
|
|
|
356
352
|
Template options:
|
|
357
353
|
--resugar The file is the canonical aontu; print the template
|
|
@@ -359,7 +355,9 @@ Template options:
|
|
|
359
355
|
--check Desugar and resugar, and exit 1 if the file is not
|
|
360
356
|
what the round trip answers
|
|
361
357
|
--marker <t> The marker, when the extension does not name it
|
|
362
|
-
(default //-, and #- --- /*- by extension)
|
|
358
|
+
(default //-, and #- --- /*- <!--- by extension)
|
|
359
|
+
--profile <f> A profile file, whose template.ext names the
|
|
360
|
+
extensions it marks and template.marker the marker
|
|
363
361
|
|
|
364
362
|
The template verb prints the canonical aontu form of a generator
|
|
365
363
|
written in the target's own syntax: a marked line is aontu source, and
|
|
@@ -452,7 +450,9 @@ Fmt options:
|
|
|
452
450
|
shapes, on standard error, and print nothing else
|
|
453
451
|
--strict With --lint, and exit 1 when there is a finding
|
|
454
452
|
--marker <t> The file is a generator, and this is its marker
|
|
455
|
-
(default //-, and #- --- /*- by extension)
|
|
453
|
+
(default //-, and #- --- /*- <!--- by extension)
|
|
454
|
+
--profile <f> A profile file, whose template.ext names the
|
|
455
|
+
extensions it marks and template.marker the marker
|
|
456
456
|
|
|
457
457
|
The fmt verb prints one document in the agreed form; with no file it
|
|
458
458
|
reads standard input. Several files need one of the options above.
|
|
@@ -495,30 +495,7 @@ function version() {
|
|
|
495
495
|
return '0.0.0';
|
|
496
496
|
}
|
|
497
497
|
}
|
|
498
|
-
// The terminal colour escapes the parser puts in its message text. A
|
|
499
|
-
// machine-readable report is no place for them, which is the rule
|
|
500
|
-
// findingOf states in ts/src/vet.ts; the twin here rather than an
|
|
501
|
-
// import because go/cmd/aontu carries its own for the same reason (the
|
|
502
|
-
// engine's is not exported to its command).
|
|
503
498
|
const EVAL_ANSI = new RegExp('\u001b\\[[0-9;]*m', 'g');
|
|
504
|
-
// THE ENGINE'S DIAGNOSIS AS A FINDING (G11 phase 7). The bare command
|
|
505
|
-
// was the one verb whose failure had no machine-readable form, so the
|
|
506
|
-
// default entry point was the one an agent had to parse with a regular
|
|
507
|
-
// expression.
|
|
508
|
-
//
|
|
509
|
-
// THE HEADLINE ONLY, and no `hint`. Both are parity decisions rather
|
|
510
|
-
// than economies: the frames under the headline are drawn for a person
|
|
511
|
-
// reading a terminal and only the first line is held to byte parity
|
|
512
|
-
// between the ports (the rule findingOf states), and the hint TABLES
|
|
513
|
-
// are deliberately not in parity while the code registry is -- so a
|
|
514
|
-
// hint here would make the two ports answer differently for a code
|
|
515
|
-
// only one of them explains. `aontu explain <code>` is where the hint
|
|
516
|
-
// lives, which is what phase 3 built it for.
|
|
517
|
-
//
|
|
518
|
-
// The CLASS comes from the registry rather than from the nil, because
|
|
519
|
-
// the registry is what both ports hold set-equal
|
|
520
|
-
// (test/spec/errcodes.tsv). Mirrors evalFinding in
|
|
521
|
-
// go/cmd/aontu/main.go.
|
|
522
499
|
function evalFinding(code, text) {
|
|
523
500
|
return {
|
|
524
501
|
class: (0, hints_1.codeClass)(code),
|
|
@@ -526,10 +503,6 @@ function evalFinding(code, text) {
|
|
|
526
503
|
message: text.split('\n')[0].replace(EVAL_ANSI, ''),
|
|
527
504
|
path: '$',
|
|
528
505
|
severity: 'error',
|
|
529
|
-
// NO SITE. The bare command's failure is the whole document not
|
|
530
|
-
// standing up, and the two sites a conflict names are in the
|
|
531
|
-
// frames the text form prints; naming one of them here would be a
|
|
532
|
-
// choice the engine has not made.
|
|
533
506
|
sites: [],
|
|
534
507
|
};
|
|
535
508
|
}
|
|
@@ -537,12 +510,6 @@ function evalFinding(code, text) {
|
|
|
537
510
|
// message, and the failure in the finding shape. Never throws.
|
|
538
511
|
function evalSource(aontu, src, mode) {
|
|
539
512
|
try {
|
|
540
|
-
// exactJSON, not JSON.stringify: a document using the `0d` exact
|
|
541
|
-
// leaves generates bigints and Decimals, which JSON.stringify cannot
|
|
542
|
-
// write (D9). The CLI prints INDENTED JSON and the shared suite's
|
|
543
|
-
// `gens` mode prints COMPACT JSON, but both go through this one
|
|
544
|
-
// emitter -- an indent argument rather than a second implementation,
|
|
545
|
-
// so the two cannot drift from each other or from the Go port.
|
|
546
513
|
const text = 'canon' === mode
|
|
547
514
|
? aontu.unify(src).canon
|
|
548
515
|
: (0, aontu_1.exactJSON)(aontu.generate(src), 2);
|
|
@@ -552,13 +519,6 @@ function evalSource(aontu, src, mode) {
|
|
|
552
519
|
const msg = (err instanceof aontu_1.AontuError || true === err?.aontu)
|
|
553
520
|
? err.message
|
|
554
521
|
: String(err?.message ?? err);
|
|
555
|
-
// WHAT THE ENGINE COLLECTED, when it collected anything: an
|
|
556
|
-
// AontuError carries the NilVals the run failed on, already
|
|
557
|
-
// materialised (handleErrors in ts/src/aontu.ts), and their first
|
|
558
|
-
// is the diagnosis every other verb reports. An error raised
|
|
559
|
-
// outside the engine's own collection -- exactJSON's circular
|
|
560
|
-
// refusal, a foreign object claiming to be one -- carries none,
|
|
561
|
-
// and answers with the text alone rather than an invented code.
|
|
562
522
|
const errs = 'function' === typeof err?.errs ? err.errs() : [];
|
|
563
523
|
const first = errs[0];
|
|
564
524
|
return {
|
|
@@ -623,16 +583,6 @@ function trustOpts(trust, entryRoot) {
|
|
|
623
583
|
return { ...text, trustWarn: makeTrustWarn(), trustWarnRoot: entryRoot };
|
|
624
584
|
}
|
|
625
585
|
}
|
|
626
|
-
// EVERY VERB honours the include capability, not just the bare
|
|
627
|
-
// command. G5 wired `--trust`/`--include-root` to `aontu <file>` alone,
|
|
628
|
-
// so `aontu vet schema.aon data.json` -- the surface an agent actually
|
|
629
|
-
// scripts -- ran the full system resolver with no flag to confine it
|
|
630
|
-
// and no warning (use-cases/REVIEW.md finding G). The flags are
|
|
631
|
-
// stripped here, before each verb parses its own tail, so a verb only
|
|
632
|
-
// has to pass the profile on to its engine.
|
|
633
|
-
//
|
|
634
|
-
// Returns undefined when the spelling is wrong, with the message
|
|
635
|
-
// already printed: the caller answers the usage class.
|
|
636
586
|
function takeTrust(argv) {
|
|
637
587
|
const rest = [];
|
|
638
588
|
let trust = { kind: 'system-warn', textExt: [] };
|
|
@@ -727,17 +677,6 @@ function runFile(file, mode, format, trust) {
|
|
|
727
677
|
src = (0, node_fs_1.readFileSync)(file, 'utf8');
|
|
728
678
|
}
|
|
729
679
|
catch (err) {
|
|
730
|
-
// A MISTYPED VERB READS AS A FILE NAME, and until G11 phase 2 that
|
|
731
|
-
// was only said when there were TWO of them. The one-argument case
|
|
732
|
-
// is the one an agent actually produces -- `aontu help`, `aontu
|
|
733
|
-
// init`, `aontu ontology` -- and it answered `cannot read help:
|
|
734
|
-
// ...`, which describes the symptom and hides the cause.
|
|
735
|
-
//
|
|
736
|
-
// The test is SHAPE, not existence: a bare word (no separator, no
|
|
737
|
-
// extension) that cannot be read was meant as a verb, while
|
|
738
|
-
// `./help`, `help.aon` and `/tmp/help` were meant as paths and keep
|
|
739
|
-
// the file diagnosis and its exit 1. That is the same escape hatch
|
|
740
|
-
// the subcommand dispatch documents. Mirrors go/cmd/aontu/main.go.
|
|
741
680
|
if (looksLikeVerb(file)) {
|
|
742
681
|
process.stderr.write(`aontu: \`${file}\` is not a file, and not a verb this port knows\n`);
|
|
743
682
|
const near = nearestVerb(file, KNOWN_VERBS);
|
|
@@ -751,12 +690,6 @@ function runFile(file, mode, format, trust) {
|
|
|
751
690
|
return 1;
|
|
752
691
|
}
|
|
753
692
|
const path = (0, node_path_1.resolve)(file);
|
|
754
|
-
// `fs` IS WHAT MAKES A FRAME EXCERPT THE FILE IT NAMES. Without it,
|
|
755
|
-
// err.ts's resolveSrc falls back to the ENTRY text, so a frame whose
|
|
756
|
-
// arrow says `lib/types.aon:2:6` printed the entry's line 2 under it
|
|
757
|
-
// -- a real file name over another file's line, which
|
|
758
|
-
// docs/reference-api.md forbids in the same words it uses to require
|
|
759
|
-
// the name.
|
|
760
693
|
const aontu = new aontu_1.Aontu({
|
|
761
694
|
path,
|
|
762
695
|
errfs: { existsSync: node_fs_1.existsSync, readFileSync: node_fs_1.readFileSync },
|
|
@@ -892,14 +825,6 @@ function runRepl(initialMode, jsonl, trust) {
|
|
|
892
825
|
rl.prompt();
|
|
893
826
|
});
|
|
894
827
|
rl.on('close', () => {
|
|
895
|
-
// The closing newline is for a HUMAN, so it is written only for
|
|
896
|
-
// one: it moves the terminal off the prompt line that `rl` left
|
|
897
|
-
// hanging. In `--jsonl` there is no prompt, every answer already
|
|
898
|
-
// ends in its own newline, and this one appended a bare empty line
|
|
899
|
-
// to the stream -- a record that is not JSON, at the end of a
|
|
900
|
-
// protocol whose whole contract is one JSON object per line. A
|
|
901
|
-
// harness parsing every line it receives failed on it, after the
|
|
902
|
-
// commands had all succeeded. Mirrors go/cmd/aontu/repl.go.
|
|
903
828
|
if (!jsonl) {
|
|
904
829
|
process.stdout.write('\n');
|
|
905
830
|
}
|
|
@@ -909,15 +834,6 @@ function runRepl(initialMode, jsonl, trust) {
|
|
|
909
834
|
process.exitCode = 0;
|
|
910
835
|
});
|
|
911
836
|
}
|
|
912
|
-
// THE VET VERB (G2 phase 3).
|
|
913
|
-
//
|
|
914
|
-
// Exit codes are VERDICT CLASSES, not a pass/fail bit: an agent loop
|
|
915
|
-
// branches on "the data contradicts the truth" (1) differently from
|
|
916
|
-
// "the data has not supplied everything the truth requires" (3), and
|
|
917
|
-
// differently again from "the schema itself is broken" (4), which is
|
|
918
|
-
// never the data's fault. 2 stays what it already was for this CLI --
|
|
919
|
-
// the caller got the invocation wrong -- which is why an unreadable
|
|
920
|
-
// file is a 2 rather than a 4.
|
|
921
837
|
const VET_EXIT = {
|
|
922
838
|
valid: 0,
|
|
923
839
|
invalid: 1,
|
|
@@ -961,14 +877,6 @@ function parseVetArgs(argv) {
|
|
|
961
877
|
format = f;
|
|
962
878
|
}
|
|
963
879
|
else if ('--max-errors' === arg) {
|
|
964
|
-
// ONE GRAMMAR, spelled the same way in both ports: decimal
|
|
965
|
-
// digits, one to nine of them, at least 1. `Number()` alone
|
|
966
|
-
// accepted `1.0`, `1e2`, `0x10` and ` 3`, which Go's parser
|
|
967
|
-
// refuses -- so the same documented invocation meant different
|
|
968
|
-
// things in the two shipped commands. The nine-digit ceiling is
|
|
969
|
-
// where the ports would part company again: beyond it Go's
|
|
970
|
-
// integer conversion saturates, and a cap nobody can reach is
|
|
971
|
-
// not worth a divergence.
|
|
972
880
|
const raw = argv[++i];
|
|
973
881
|
if (!/^[0-9]{1,9}$/.test(raw ?? '') || 1 > Number(raw)) {
|
|
974
882
|
return { err: 'aontu: --max-errors needs a positive whole number' };
|
|
@@ -1046,10 +954,6 @@ function renderFinding(f) {
|
|
|
1046
954
|
out.push(` actual: ${f.actual}`);
|
|
1047
955
|
}
|
|
1048
956
|
for (const s of f.sites) {
|
|
1049
|
-
// Every site carries the canon of the value it stands for: that is
|
|
1050
|
-
// what makes the two sides of a conflict readable side by side. A
|
|
1051
|
-
// site's file is always a string -- empty when the value belongs to
|
|
1052
|
-
// neither document -- so there is nothing to coalesce here.
|
|
1053
957
|
out.push(` ${s.role}: ${s.file}:${s.row}:${s.col} (${s.value})`);
|
|
1054
958
|
}
|
|
1055
959
|
return out.join('\n');
|
|
@@ -1141,18 +1045,9 @@ function vetOnce(args, trust) {
|
|
|
1141
1045
|
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
1142
1046
|
return 2;
|
|
1143
1047
|
}
|
|
1144
|
-
// Each data file is vetted on its own, because a parsed tree is
|
|
1145
|
-
// single-use (docs/reference-api.md) -- and because two data files
|
|
1146
|
-
// are two candidates for the same truth, not one merged candidate.
|
|
1147
1048
|
let verdict = 'valid';
|
|
1148
1049
|
let truncated = false;
|
|
1149
1050
|
const findings = [];
|
|
1150
|
-
// COVERAGE ACROSS SEVERAL DATA FILES (G11 phase 5). Two data files
|
|
1151
|
-
// are two candidates for one truth, so the schema side is the SAME
|
|
1152
|
-
// for each: `declared` is taken once, and a declaration is unused
|
|
1153
|
-
// only when NO file met it -- the intersection, because a
|
|
1154
|
-
// declaration one file exercised is exercised. The data side adds
|
|
1155
|
-
// up: leaves and checked leaves sum, and `unchecked` is the union.
|
|
1156
1051
|
let cov;
|
|
1157
1052
|
// Initialised rather than left undefined: it is filled in the same
|
|
1158
1053
|
// block that sets `cov`, so a fallback at the read below would be an
|
|
@@ -1170,12 +1065,6 @@ function vetOnce(args, trust) {
|
|
|
1170
1065
|
maxErrors: args.maxErrors,
|
|
1171
1066
|
schemaUrl: args.schema,
|
|
1172
1067
|
dataUrl: source.file,
|
|
1173
|
-
// The paths as well as the labels: a relative `@"file"` load
|
|
1174
|
-
// inside either document resolves from ITS OWN directory, the
|
|
1175
|
-
// way `aontu <file>` already resolves one (runFile above). The
|
|
1176
|
-
// path is passed AS TYPED, not resolved: it doubles as the
|
|
1177
|
-
// label above, and a report that mixed the typed path with an
|
|
1178
|
-
// absolute one would name the same file two ways.
|
|
1179
1068
|
schemaPath: args.schema,
|
|
1180
1069
|
dataPath: source.file,
|
|
1181
1070
|
coverage: args.coverage,
|
|
@@ -1204,26 +1093,10 @@ function vetOnce(args, trust) {
|
|
|
1204
1093
|
? new Set([...unusedEvery].filter((u) => mine.has(u))) : mine;
|
|
1205
1094
|
unusedSeen = true;
|
|
1206
1095
|
}
|
|
1207
|
-
// A SCHEMA-SIDE FAULT IS THE SAME FAULT FOR EVERY DATA FILE, so it
|
|
1208
|
-
// is reported ONCE. `error` means exactly that -- the run could not
|
|
1209
|
-
// be set up from the truth's side, never the data's (the exit table
|
|
1210
|
-
// in docs/reference-api.md) -- so the report the first file
|
|
1211
|
-
// produced is the report every later file would produce, character
|
|
1212
|
-
// for character. Concatenating them repeated one broken schema N
|
|
1213
|
-
// times and, past the cap, marked the report `truncated` over a
|
|
1214
|
-
// single underlying fault. It only became visible once the `error`
|
|
1215
|
-
// verdict started carrying findings at all: while the list was
|
|
1216
|
-
// empty there was nothing to duplicate.
|
|
1217
1096
|
if ('error' === report.verdict) {
|
|
1218
1097
|
break;
|
|
1219
1098
|
}
|
|
1220
1099
|
}
|
|
1221
|
-
// The cap is on the REPORT, not on each file. Capping every file's
|
|
1222
|
-
// list and then concatenating them let `--max-errors 1` emit one
|
|
1223
|
-
// finding PER FILE -- and leave `truncated` false while doing it,
|
|
1224
|
-
// because no single file had been cut. The engine still caps each
|
|
1225
|
-
// run, so a pathological file cannot flood the aggregate before it
|
|
1226
|
-
// gets here; this is the second, honest cut.
|
|
1227
1100
|
const cap = args.maxErrors ?? vet_1.VET_MAX_ERRORS;
|
|
1228
1101
|
const kept = cap < findings.length ? findings.slice(0, cap) : findings;
|
|
1229
1102
|
if (null != cov) {
|
|
@@ -1241,12 +1114,6 @@ function vetOnce(args, trust) {
|
|
|
1241
1114
|
'sarif' === args.format ? renderVetSarif(report) :
|
|
1242
1115
|
renderVetText(report);
|
|
1243
1116
|
process.stdout.write(text + '\n');
|
|
1244
|
-
// A VACUOUS CHECK IS A FAILED GATE UNDER `--strict-coverage`, and
|
|
1245
|
-
// only under it: the verdict WORD is unchanged, so nothing that
|
|
1246
|
-
// passes today starts failing, and a caller who wants the stronger
|
|
1247
|
-
// gate asks for it. The reason goes to stderr, because stdout is a
|
|
1248
|
-
// report contract -- a JSON consumer reads `coverage.vacuous` and a
|
|
1249
|
-
// person reads this.
|
|
1250
1117
|
if (true === args.strictCoverage && true === report.coverage?.vacuous) {
|
|
1251
1118
|
process.stderr.write('aontu: no data leaf was constrained by the schema:' +
|
|
1252
1119
|
' this run checked nothing\n' +
|
|
@@ -1273,19 +1140,6 @@ function watchSignature(files) {
|
|
|
1273
1140
|
function sleep(ms) {
|
|
1274
1141
|
return new Promise((done) => setTimeout(done, ms));
|
|
1275
1142
|
}
|
|
1276
|
-
// Resolve true when any watched file's signature moves off `before`.
|
|
1277
|
-
// This is the real waiter: it never resolves false, so a real watch
|
|
1278
|
-
// runs until the process is interrupted; tests inject their own waiter
|
|
1279
|
-
// to bound the loop, and pass a short pollMs when they drive this one
|
|
1280
|
-
// directly. The interval is a required argument (the command passes
|
|
1281
|
-
// WATCH_POLL_MS) so there is no defaulting branch a test could never
|
|
1282
|
-
// take.
|
|
1283
|
-
//
|
|
1284
|
-
// The BASELINE is an argument, not a snapshot taken here: the loop
|
|
1285
|
-
// records it BEFORE each vet run, so a save landing between the run's
|
|
1286
|
-
// reads and the wait still compares as a change. A waiter that
|
|
1287
|
-
// snapshotted on entry would adopt that unvetted save as its baseline
|
|
1288
|
-
// and wait indefinitely on a stale report.
|
|
1289
1143
|
async function watchChange(files, before, pollMs) {
|
|
1290
1144
|
for (;;) {
|
|
1291
1145
|
await sleep(pollMs);
|
|
@@ -1314,9 +1168,6 @@ async function watchVet(args, wait, trust) {
|
|
|
1314
1168
|
}
|
|
1315
1169
|
return code;
|
|
1316
1170
|
}
|
|
1317
|
-
// The vet verb. Non-watch runs are synchronous and return the exit
|
|
1318
|
-
// class directly; `--watch` returns a promise that resolves only when
|
|
1319
|
-
// the waiter says stop (never, for the real one).
|
|
1320
1171
|
function runVet(argv, wait) {
|
|
1321
1172
|
const trusted = takeTrust(argv);
|
|
1322
1173
|
if (null == trusted) {
|
|
@@ -1527,30 +1378,7 @@ function parseBreakingArgs(argv) {
|
|
|
1527
1378
|
},
|
|
1528
1379
|
};
|
|
1529
1380
|
}
|
|
1530
|
-
// A source file the include resolver can actually load. `git#<rev>`
|
|
1531
|
-
// materialises these and nothing else: an include names an Aontu
|
|
1532
|
-
// document (`.aon`/`.aontu`, the two extensions `@"foo"` tries) or a
|
|
1533
|
-
// JSON one, so the rest of a revision's tree cannot be part of any
|
|
1534
|
-
// include closure and copying it would be pure cost.
|
|
1535
1381
|
const INCLUDABLE = /\.(aon|aontu|jsonic|json)$/;
|
|
1536
|
-
// Resolve one --against spelling to an old version.
|
|
1537
|
-
//
|
|
1538
|
-
// A `git#<rev>` spelling is the old version of the WHOLE TREE, not of
|
|
1539
|
-
// the entry file alone. It used to be `git show <rev>:./<file>`, whose
|
|
1540
|
-
// text was then evaluated with `generalPath`/`specificPath` pointing at
|
|
1541
|
-
// the WORKING file -- so every `@"..."` include in the old document
|
|
1542
|
-
// resolved against the working tree, and the "old" side was old entry
|
|
1543
|
-
// text meeting new includes. A breaking change inside an included file
|
|
1544
|
-
// therefore compared against itself and answered `compatible`: the
|
|
1545
|
-
// documented CI gate silently un-gated every non-entry file of the
|
|
1546
|
-
// multi-file layout real models use (use-cases/BUGS.md §26). The old
|
|
1547
|
-
// tree's includable sources are copied into a temporary directory and
|
|
1548
|
-
// the old document is evaluated from THERE.
|
|
1549
|
-
//
|
|
1550
|
-
// Sources outside the revision -- package includes under node_modules,
|
|
1551
|
-
// the bundled `std/system` -- still resolve as they do today: they are
|
|
1552
|
-
// not in the tree, and their versions travel with the lockfile rather
|
|
1553
|
-
// than with this comparison.
|
|
1554
1382
|
function oldVersion(spec, file) {
|
|
1555
1383
|
if (!spec.startsWith('git#')) {
|
|
1556
1384
|
try {
|
|
@@ -1578,23 +1406,9 @@ function oldVersion(spec, file) {
|
|
|
1578
1406
|
// that only some failures take.
|
|
1579
1407
|
const temp = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'aontu-against-'));
|
|
1580
1408
|
try {
|
|
1581
|
-
// THE REPO-RELATIVE PATH COMES FROM GIT, not from path arithmetic.
|
|
1582
|
-
// Relativising `rev-parse --show-toplevel` against `resolve(file)`
|
|
1583
|
-
// puts two DIFFERENT COORDINATE SYSTEMS on either side of the
|
|
1584
|
-
// subtraction: git prints the real path, while the caller's is
|
|
1585
|
-
// whatever they typed. On macOS a temp file under /var is
|
|
1586
|
-
// /private/var to git, and on Windows a TMP short name
|
|
1587
|
-
// (RUNNER~1) is the long form to git -- so the subtraction gave a
|
|
1588
|
-
// `../..` climb, the entry was "not in that revision", and the
|
|
1589
|
-
// documented CI spelling failed on both platforms while passing on
|
|
1590
|
-
// Linux (this PR's own CI). `--show-prefix` is the same question
|
|
1591
|
-
// asked in git's coordinates: the repo-relative directory of the
|
|
1592
|
-
// cwd, already slash-separated and already normalised.
|
|
1593
1409
|
const prefix = git(['rev-parse', '--show-prefix'], dir).trim();
|
|
1594
1410
|
const entryRel = prefix + (0, node_path_1.basename)(file);
|
|
1595
1411
|
const top = git(['rev-parse', '--show-toplevel'], dir).trim();
|
|
1596
|
-
// `-z` so a path with a newline or a quote cannot be mistaken for
|
|
1597
|
-
// two paths (git otherwise quotes such names).
|
|
1598
1412
|
const listed = git(['ls-tree', '-r', '-z', '--name-only', rev], top)
|
|
1599
1413
|
.split('\0').filter((p) => '' !== p);
|
|
1600
1414
|
if (!listed.includes(entryRel)) {
|
|
@@ -1624,13 +1438,6 @@ function oldVersion(spec, file) {
|
|
|
1624
1438
|
function policyCompat(newSrc, path, include) {
|
|
1625
1439
|
const aontu = new aontu_1.Aontu();
|
|
1626
1440
|
const ctx = aontu.ctx({ collect: true });
|
|
1627
|
-
// The declaration is read by EVALUATING the document, so this leg
|
|
1628
|
-
// runs the include resolver too and has to run it under BOTH of the
|
|
1629
|
-
// verb's include options -- a `breaking --trust none` that read its
|
|
1630
|
-
// own mode through an unconfined resolver would confine the
|
|
1631
|
-
// comparison and not the question (use-cases/REVIEW.md finding G),
|
|
1632
|
-
// and one that took the capability alone read no mode at all when
|
|
1633
|
-
// the declaration arrived through a `--text-ext` include.
|
|
1634
1441
|
const v = aontu.unify(newSrc, { path, ...(0, utility_1.includeOpts)(include) }, ctx);
|
|
1635
1442
|
if (0 < ctx.err.length || true === v?.isNil) {
|
|
1636
1443
|
return undefined;
|
|
@@ -1649,11 +1456,6 @@ function policyCompat(newSrc, path, include) {
|
|
|
1649
1456
|
return 'backward' === m || 'forward' === m || 'full' === m || 'none' === m
|
|
1650
1457
|
? m : undefined;
|
|
1651
1458
|
}
|
|
1652
|
-
// Is the evaluated old version's value at the finding path deprecated?
|
|
1653
|
-
// The --allow-deprecated-removal downgrade (G3 phase 4): removing (or
|
|
1654
|
-
// otherwise changing) a value the old version already deprecated warns
|
|
1655
|
-
// instead of breaking. The Go port exports the same reader as
|
|
1656
|
-
// aontu.DeprecatedAt.
|
|
1657
1459
|
function deprecatedAt(oldSrc, path, filePath) {
|
|
1658
1460
|
const aontu = new aontu_1.Aontu();
|
|
1659
1461
|
const ctx = aontu.ctx({ collect: true });
|
|
@@ -1720,9 +1522,6 @@ function runBreaking(argv) {
|
|
|
1720
1522
|
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
1721
1523
|
return 2;
|
|
1722
1524
|
}
|
|
1723
|
-
// The declared mode: --mode overrides the document's own policy;
|
|
1724
|
-
// neither means backward, the index's framing (v1-valid documents
|
|
1725
|
-
// stay valid).
|
|
1726
1525
|
const mode = args.mode ??
|
|
1727
1526
|
policyCompat(newSrc, args.file, verbOpts(trust, entryRootOf(args.file))) ??
|
|
1728
1527
|
'backward';
|
|
@@ -1755,8 +1554,6 @@ function runBreaking(argv) {
|
|
|
1755
1554
|
if (null != old.temp) {
|
|
1756
1555
|
temps.push(old.temp);
|
|
1757
1556
|
}
|
|
1758
|
-
// backward: the NEW document is the general side — every old
|
|
1759
|
-
// instance must still be admitted. forward: the old one is.
|
|
1760
1557
|
const checks = [];
|
|
1761
1558
|
if ('backward' === mode || 'full' === mode) {
|
|
1762
1559
|
checks.push({ general: [newSrc, args.file], specific: [oldSrc, spec] });
|
|
@@ -1771,17 +1568,9 @@ function runBreaking(argv) {
|
|
|
1771
1568
|
at: args.at,
|
|
1772
1569
|
generalUrl: check.general[1],
|
|
1773
1570
|
specificUrl: check.specific[1],
|
|
1774
|
-
// The old side's relative loads resolve from ITS own tree --
|
|
1775
|
-
// the materialised revision for a git spelling, the named
|
|
1776
|
-
// file's directory otherwise -- so an included file's change
|
|
1777
|
-
// is part of the comparison rather than invisible to it.
|
|
1778
1571
|
generalPath: check.general[1] === spec ? oldPath : args.file,
|
|
1779
1572
|
specificPath: check.specific[1] === spec ? oldPath : args.file,
|
|
1780
1573
|
});
|
|
1781
|
-
// The deprecated-removal downgrade: a finding about a value the
|
|
1782
|
-
// OLD version already deprecated becomes a warning, and warnings
|
|
1783
|
-
// do not move the verdict. Deprecate-then-remove is the
|
|
1784
|
-
// supported rename path (the design's own sequencing).
|
|
1785
1574
|
let verdict = report.verdict;
|
|
1786
1575
|
if (args.allowDeprecatedRemoval) {
|
|
1787
1576
|
let liveFindings = 0;
|
|
@@ -1832,12 +1621,6 @@ function renderBreakingJson(report, mode) {
|
|
|
1832
1621
|
findings: report.findings,
|
|
1833
1622
|
}, 2);
|
|
1834
1623
|
}
|
|
1835
|
-
// ---------------------------------------------------------------------
|
|
1836
|
-
// The trim reporter (G3 phase 6): report redundant entries as paths.
|
|
1837
|
-
// Report-only — REWRITING needs G7's format-preserving patch surface —
|
|
1838
|
-
// which is why --check is REQUIRED rather than defaulted: `aontu trim
|
|
1839
|
-
// f.aon` reads as "trim this file", and doing something else silently
|
|
1840
|
-
// is worse than saying so.
|
|
1841
1624
|
const TRIM_HELP = 'aontu trim --check <file> (try --help)';
|
|
1842
1625
|
const TRIM_EXIT = {
|
|
1843
1626
|
clean: 0,
|
|
@@ -1907,8 +1690,6 @@ function runTrim(argv) {
|
|
|
1907
1690
|
}
|
|
1908
1691
|
function renderTrimText(report) {
|
|
1909
1692
|
const head = `verdict: ${report.verdict}`;
|
|
1910
|
-
// WHY, when the document could not be evaluated at all: rendered as
|
|
1911
|
-
// vet renders a finding, because it IS one (the review's finding F).
|
|
1912
1693
|
const errors = report.errors ?? [];
|
|
1913
1694
|
if (0 < errors.length) {
|
|
1914
1695
|
return [head, ''].concat(errors.map(renderFinding)).join('\n');
|
|
@@ -1957,27 +1738,10 @@ const VIEW_EDGES = ['upward', 'all', 'none'];
|
|
|
1957
1738
|
// is a terminal, which is the CLI's to know and the library's never --
|
|
1958
1739
|
// the same division err.ts already draws for the error frames.
|
|
1959
1740
|
const VIEW_STYLES = ['auto', 'none', 'ansi', 'css'];
|
|
1960
|
-
// `--style auto` resolved, which only the CLI can do. The mechanism is
|
|
1961
|
-
// the PROFILE's and the library knows it -- an SVG carries its
|
|
1962
|
-
// stylesheet unless told not to, which is what makes a figure stand
|
|
1963
|
-
// alone. What the library cannot know is whether the DESTINATION is a
|
|
1964
|
-
// terminal, so that is the only thing decided here: escapes on the
|
|
1965
|
-
// text profile when stdout is a terminal and NO_COLOR is unset, the
|
|
1966
|
-
// same two conditions the error frames use. `undefined` leaves the
|
|
1967
|
-
// profile's own default in place.
|
|
1968
1741
|
function viewStyleOf(asked, as) {
|
|
1969
1742
|
if (undefined !== asked && 'auto' !== asked) {
|
|
1970
1743
|
return asked;
|
|
1971
1744
|
}
|
|
1972
|
-
// STDOUT'S OWN TERMINAL-NESS, and NO_COLOR read here rather than
|
|
1973
|
-
// through colorActive(). The figure goes to STDOUT and the error
|
|
1974
|
-
// frames go to STDERR, and they are not the same destination: main()
|
|
1975
|
-
// has already called setColor for stderr, so asking colorActive()
|
|
1976
|
-
// would answer the wrong question twice --- no escapes for
|
|
1977
|
-
// `aontu view tree m.aon 2>/dev/null` at a terminal, and escapes
|
|
1978
|
-
// into the pipe for `aontu view tree m.aon | less`. The NO_COLOR
|
|
1979
|
-
// rule is the one no-color.org states and err.ts implements:
|
|
1980
|
-
// set, to anything but empty, means no colour.
|
|
1981
1745
|
const no = process.env.NO_COLOR;
|
|
1982
1746
|
return 'text' === as && true === process.stdout.isTTY
|
|
1983
1747
|
&& (null == no || '' === no) ? 'ansi' : undefined;
|
|
@@ -1999,24 +1763,6 @@ const VIEW_USAGE_CODES = [
|
|
|
1999
1763
|
'view_document_shape', 'view_style_profile', 'view_style_unknown',
|
|
2000
1764
|
];
|
|
2001
1765
|
const MOD_HELP = 'aontu mod tidy|verify|vendor|manifest [dir] (try --help)';
|
|
2002
|
-
// The module tooling (G6 phase 3, ts/src/mod-tool.ts). All LOCAL:
|
|
2003
|
-
// `tidy` resolves the closure from what is in the stores and rewrites
|
|
2004
|
-
// the lockfile, `verify` asks whether the stores still mean what the
|
|
2005
|
-
// lockfile pins and changes nothing, `vendor` materialises the locked
|
|
2006
|
-
// closure into the project, `manifest` prints what a publish would
|
|
2007
|
-
// push.
|
|
2008
|
-
//
|
|
2009
|
-
// TIDY AND VERIFY ARE DIFFERENT QUESTIONS, and that is why both exist.
|
|
2010
|
-
// Tidy recomputes and rewrites by design -- a pin is what a module
|
|
2011
|
-
// means NOW -- so it makes the lockfile agree with whatever the store
|
|
2012
|
-
// holds, tampering included. Verify is the gate: a CI job runs it
|
|
2013
|
-
// BEFORE tidy, or instead of it.
|
|
2014
|
-
//
|
|
2015
|
-
// `get` and `publish` are the NETWORK half of the design and are not in
|
|
2016
|
-
// this build. They are named here rather than left to fall out as an
|
|
2017
|
-
// unknown subcommand, because a reader of the design will type them and
|
|
2018
|
-
// deserves to be told which half is missing rather than that the word
|
|
2019
|
-
// is wrong.
|
|
2020
1766
|
function runMod(argv) {
|
|
2021
1767
|
const rest = [];
|
|
2022
1768
|
let format = 'text';
|
|
@@ -2063,10 +1809,6 @@ function runMod(argv) {
|
|
|
2063
1809
|
process.stderr.write(`aontu: mod needs tidy, verify, vendor or manifest\n${MOD_HELP}\n`);
|
|
2064
1810
|
return 2;
|
|
2065
1811
|
}
|
|
2066
|
-
// THE OLD LAYOUT IS NAMED, NOT READ. The lockfile and the vendored
|
|
2067
|
-
// closure moved under aontu_meta/; a project that still carries them
|
|
2068
|
-
// at its root would otherwise look untouched by any of these verbs,
|
|
2069
|
-
// which is the one silence worth breaking.
|
|
2070
1812
|
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(dir, 'aon_vendor')) || (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, 'mod-lock.aon'))) {
|
|
2071
1813
|
process.stderr.write('aontu: aon_vendor/ and mod-lock.aon now live under aontu_meta/: ' +
|
|
2072
1814
|
'move them, or run aontu mod tidy and aontu mod vendor\n');
|
|
@@ -2090,9 +1832,6 @@ const MOD_SUBS = ['tidy', 'verify', 'vendor', 'manifest'];
|
|
|
2090
1832
|
const MOD_EXIT = {
|
|
2091
1833
|
ok: 0,
|
|
2092
1834
|
missing: 1,
|
|
2093
|
-
// A REFUSED GATE, with `breaking`: a store that no longer means what
|
|
2094
|
-
// the lockfile pins is the integrity check saying no, and a CI job
|
|
2095
|
-
// reading exit codes should not have to learn a third class for it.
|
|
2096
1835
|
mismatch: 1,
|
|
2097
1836
|
// Likewise a lockfile that does not cover the project: the gate has
|
|
2098
1837
|
// nothing to check, which is a refusal and not a pass.
|
|
@@ -2138,11 +1877,6 @@ function modText(sub, report) {
|
|
|
2138
1877
|
for (const f of report.findings) {
|
|
2139
1878
|
lines.push(f.path + ': ' + f.message);
|
|
2140
1879
|
}
|
|
2141
|
-
// What a manifest lacks is a declaration the module does not make
|
|
2142
|
-
// or an entry file that is not there, and neither is something a
|
|
2143
|
-
// fetch would supply -- so this is not the tail the other two
|
|
2144
|
-
// subcommands share. The name says which kind it is: `mod.version`
|
|
2145
|
-
// is a declaration, `service.aon` is a file.
|
|
2146
1880
|
for (const miss of report.missing) {
|
|
2147
1881
|
lines.push(miss + ': missing');
|
|
2148
1882
|
}
|
|
@@ -2152,8 +1886,6 @@ function modText(sub, report) {
|
|
|
2152
1886
|
for (const mod of report.verified) {
|
|
2153
1887
|
lines.push(mod + ': verified');
|
|
2154
1888
|
}
|
|
2155
|
-
// BOTH HASHES, because the useful question is which way it moved:
|
|
2156
|
-
// an empty `got` is a module that no longer stands up at all.
|
|
2157
1889
|
for (const m of report.mismatched) {
|
|
2158
1890
|
lines.push(m.mod + ': pinned ' + m.want + ' but the store means ' +
|
|
2159
1891
|
('' === m.got ? 'nothing (it does not evaluate)' : m.got));
|
|
@@ -2186,26 +1918,6 @@ function modText(sub, report) {
|
|
|
2186
1918
|
}
|
|
2187
1919
|
return lines.join('\n');
|
|
2188
1920
|
}
|
|
2189
|
-
// VACUITY SIGNALS (G11 phase 4,
|
|
2190
|
-
// docs/capability-review/g11-agent-onramp.md).
|
|
2191
|
-
//
|
|
2192
|
-
// The same principle phase 5 applied to `vet`: a verb that did NOTHING
|
|
2193
|
-
// and a verb that did its job answer the same. `aontu view tree` over a
|
|
2194
|
-
// document declaring no relations printed one newline and exited 0;
|
|
2195
|
-
// `aontu render` with no profile printed nothing and exited 0; `aontu
|
|
2196
|
-
// relations` over a document declaring none answered `verdict: pass`.
|
|
2197
|
-
// For a person at a terminal that is a shrug. For an unattended agent
|
|
2198
|
-
// it is a green check mark on an empty box.
|
|
2199
|
-
//
|
|
2200
|
-
// ON STDERR, ALWAYS. stdout is a report contract -- a `--format json`
|
|
2201
|
-
// consumer parses it -- and the exit code is a verdict class that
|
|
2202
|
-
// callers already branch on. Neither changes here: what changes is
|
|
2203
|
-
// that the caller is TOLD. A caller who wants it to be fatal has
|
|
2204
|
-
// `vet --strict-coverage`, and the same argument would give the other
|
|
2205
|
-
// verbs a flag of their own if one is ever asked for.
|
|
2206
|
-
//
|
|
2207
|
-
// The repository already ruled this for one verb, in G8 phase 6 on
|
|
2208
|
-
// `trim`: "doing something else silently is worse than refusing".
|
|
2209
1921
|
function vacuous(what, why) {
|
|
2210
1922
|
process.stderr.write(`aontu: ${what}: ${why}\n`);
|
|
2211
1923
|
}
|
|
@@ -2469,12 +2181,6 @@ function runView(argv) {
|
|
|
2469
2181
|
rest.push(arg);
|
|
2470
2182
|
}
|
|
2471
2183
|
}
|
|
2472
|
-
// ESCAPES NEVER GO INTO A FILE. A pinned golden holding terminal
|
|
2473
|
-
// control codes is not a golden anybody can read, and a byte
|
|
2474
|
-
// comparison against one would fail on the reader's terminal
|
|
2475
|
-
// settings. `auto` resolves to `none` there on its own; asking for
|
|
2476
|
-
// `ansi` explicitly is a usage error rather than a silent downgrade,
|
|
2477
|
-
// so a script that wanted colour is told where it went.
|
|
2478
2184
|
if ('ansi' === style && (undefined !== out || undefined !== opts.views)) {
|
|
2479
2185
|
process.stderr.write('aontu: --style ansi writes to a terminal, not to a file\n');
|
|
2480
2186
|
return 2;
|
|
@@ -2482,10 +2188,6 @@ function runView(argv) {
|
|
|
2482
2188
|
// THE VIEW DOCUMENT draws every figure a document declares, so it
|
|
2483
2189
|
// names no kind: the declarations do, one each.
|
|
2484
2190
|
if (undefined !== opts.views) {
|
|
2485
|
-
// A declaration names its own profile, so the style is left to
|
|
2486
|
-
// each figure's own default; `--style none` still reaches every
|
|
2487
|
-
// one of them, which is how a host page that binds the CSS
|
|
2488
|
-
// variables asks for eight figures without eight stylesheets.
|
|
2489
2191
|
opts.style = viewStyleOf(style, undefined);
|
|
2490
2192
|
return runViewSet(rest, opts, trust, { format, check, strict, out });
|
|
2491
2193
|
}
|
|
@@ -2553,17 +2255,6 @@ function runView(argv) {
|
|
|
2553
2255
|
docs: files.slice(1).map((path, i) => ({ src: srcs[i + 1], path })),
|
|
2554
2256
|
};
|
|
2555
2257
|
const report = (0, view_1.view)(srcs[0], viewOpts);
|
|
2556
|
-
// AN EMPTY FIGURE IS THE SAME BYTES AS A DRAWN ONE MINUS ITS
|
|
2557
|
-
// CONTENT, and every profile spells "empty" differently: text draws
|
|
2558
|
-
// nothing at all, mermaid still draws its `flowchart LR` header, the
|
|
2559
|
-
// matrix still prints its count line. Rather than teach this one
|
|
2560
|
-
// place each of those spellings -- a list that goes stale the first
|
|
2561
|
-
// time a profile gains a header -- ASK THE SAME KIND TO DRAW AN
|
|
2562
|
-
// EMPTY DOCUMENT and compare. Equal texts mean this document
|
|
2563
|
-
// contributed nothing to the figure, whatever the profile.
|
|
2564
|
-
//
|
|
2565
|
-
// It costs one drawing of `{}`, which is the cheapest document
|
|
2566
|
-
// there is, and only on a run that produced a figure at all.
|
|
2567
2258
|
if ('error' !== report.verdict && null != report.text) {
|
|
2568
2259
|
const bare = (0, view_1.view)('{}', viewOpts);
|
|
2569
2260
|
if ('error' !== bare.verdict && bare.text === report.text) {
|
|
@@ -2612,13 +2303,6 @@ function runView(argv) {
|
|
|
2612
2303
|
}
|
|
2613
2304
|
return strict && 'lossy' === report.verdict ? 1 : VIEW_EXIT[report.verdict];
|
|
2614
2305
|
}
|
|
2615
|
-
// `aontu view --views <path> <file>`: every figure the document
|
|
2616
|
-
// declares, from one evaluation, all or nothing.
|
|
2617
|
-
//
|
|
2618
|
-
// A declared `out` is resolved against the DOCUMENT's own directory,
|
|
2619
|
-
// not the caller's: a view document is committed beside the figures it
|
|
2620
|
-
// gates, and a gate that only passes from one working directory is not
|
|
2621
|
-
// a gate.
|
|
2622
2306
|
function runViewSet(rest, opts, trust, how) {
|
|
2623
2307
|
if (1 !== rest.length) {
|
|
2624
2308
|
process.stderr.write('aontu: view --views takes one file\n');
|
|
@@ -2742,8 +2426,6 @@ function renderViewJson(report) {
|
|
|
2742
2426
|
}
|
|
2743
2427
|
function renderRelationsText(report) {
|
|
2744
2428
|
const head = `verdict: ${report.verdict}`;
|
|
2745
|
-
// WHY, when the document could not be evaluated at all: rendered as
|
|
2746
|
-
// vet renders a finding, because it IS one (the review's finding F).
|
|
2747
2429
|
const errors = report.errors ?? [];
|
|
2748
2430
|
if (0 < errors.length) {
|
|
2749
2431
|
return [head, ''].concat(errors.map(renderFinding)).join('\n');
|
|
@@ -2765,19 +2447,6 @@ function renderRelationsJson(report) {
|
|
|
2765
2447
|
...(null == report.errors ? {} : { errors: report.errors }),
|
|
2766
2448
|
}, 2);
|
|
2767
2449
|
}
|
|
2768
|
-
// ---------------------------------------------------------------------
|
|
2769
|
-
// JSON SCHEMA EXPORT (SUPPORT.md act 2, the review's finding I): the
|
|
2770
|
-
// bridge to every structured-output API, which constrains generation to
|
|
2771
|
-
// JSON Schema and nothing else. Export the model, let the provider
|
|
2772
|
-
// generate under it, then `vet` the result against the model itself --
|
|
2773
|
-
// the hybrid an enterprise actually deploys, and impossible without
|
|
2774
|
-
// this verb.
|
|
2775
|
-
//
|
|
2776
|
-
// THE SCHEMA GOES TO STDOUT AND THE LOSSES TO STDERR, so `aontu
|
|
2777
|
-
// jsonschema x.aon > schema.json` writes a schema and still tells the
|
|
2778
|
-
// reader what it could not carry. `--strict` makes a loss a refusal,
|
|
2779
|
-
// for the CI job that would rather fail than ship a schema weaker than
|
|
2780
|
-
// its model.
|
|
2781
2450
|
const JSONSCHEMA_HELP = 'aontu jsonschema [--at <path>] [--strict] <file> (try --help)';
|
|
2782
2451
|
function runJsonSchema(argv) {
|
|
2783
2452
|
const trusted = takeTrust(argv);
|
|
@@ -2861,14 +2530,6 @@ function runJsonSchema(argv) {
|
|
|
2861
2530
|
return 'error' === report.verdict ? 4 :
|
|
2862
2531
|
strict && 'lossy' === report.verdict ? 1 : 0;
|
|
2863
2532
|
}
|
|
2864
|
-
// ---------------------------------------------------------------------
|
|
2865
|
-
// THE RENDER VERB (docs/design/RENDER.0.md D8): evaluate a document,
|
|
2866
|
-
// vet the value at --at against aontu:code, fold code.units into bytes,
|
|
2867
|
-
// and put them where the flag says -- one unit on stdout, every unit
|
|
2868
|
-
// below --out (all or nothing), or compared against --check. Exit codes
|
|
2869
|
-
// mirror jsonschema's: 0 ok; 1 lossy under --strict or drift under
|
|
2870
|
-
// --check; 2 usage or I/O, a refused unit path included; 4 the
|
|
2871
|
-
// document does not stand up or the instance is not aontu:code.
|
|
2872
2533
|
const RENDER_HELP = 'aontu render [--at <path>] [--profile <file>]... [--unit <path>] ' +
|
|
2873
2534
|
'[--stdout | --out <dir> | --check <dir> | --coverage] ' +
|
|
2874
2535
|
'[--coverage-at <path>] [--strict] [--marker <token>] <file> (try --help)';
|
|
@@ -2997,44 +2658,14 @@ function runRender(argv) {
|
|
|
2997
2658
|
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2998
2659
|
return 2;
|
|
2999
2660
|
}
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
// carries the target's extension and never `.aon`. Desugared here
|
|
3004
|
-
// rather than anywhere deeper, because a template is an entry
|
|
3005
|
-
// spelling and not a value: an include is still aontu.
|
|
3006
|
-
if (!files[0].endsWith('.aon')) {
|
|
3007
|
-
src = (0, template_1.desugarTemplate)(src, marker ?? (0, template_1.markerFor)(files[0]));
|
|
2661
|
+
const loadedProfiles = loadProfiles(profileFiles, trust);
|
|
2662
|
+
if ('number' === typeof loadedProfiles) {
|
|
2663
|
+
return loadedProfiles;
|
|
3008
2664
|
}
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
// one lang is a usage error: the fold could not choose.
|
|
3014
|
-
const profiles = [];
|
|
3015
|
-
const langs = new Map();
|
|
3016
|
-
for (const pf of profileFiles) {
|
|
3017
|
-
let text;
|
|
3018
|
-
try {
|
|
3019
|
-
text = (0, node_fs_1.readFileSync)(pf, 'utf8');
|
|
3020
|
-
}
|
|
3021
|
-
catch (err) {
|
|
3022
|
-
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
3023
|
-
return 2;
|
|
3024
|
-
}
|
|
3025
|
-
const loaded = (0, aontu_1.renderProfile)(text, { path: (0, node_path_1.resolve)(pf), ...verbOpts(trust, entryRootOf(pf)) });
|
|
3026
|
-
if (undefined !== loaded.errors) {
|
|
3027
|
-
process.stderr.write(loaded.errors.map(renderFinding).join('\n') + '\n');
|
|
3028
|
-
return 4;
|
|
3029
|
-
}
|
|
3030
|
-
const profile = loaded.profile;
|
|
3031
|
-
const prev = langs.get(profile.lang);
|
|
3032
|
-
if (undefined !== prev) {
|
|
3033
|
-
process.stderr.write(`aontu: two profiles claim ${profile.lang}: ${prev} and ${pf}\n`);
|
|
3034
|
-
return 2;
|
|
3035
|
-
}
|
|
3036
|
-
langs.set(profile.lang, pf);
|
|
3037
|
-
profiles.push(profile);
|
|
2665
|
+
const profiles = loadedProfiles;
|
|
2666
|
+
if (!files[0].endsWith('.aon')) {
|
|
2667
|
+
src = (0, template_1.desugarTemplate)(src, marker ??
|
|
2668
|
+
(0, template_1.markerFromProfiles)(profiles, files[0]) ?? (0, template_1.markerFor)(files[0]));
|
|
3038
2669
|
}
|
|
3039
2670
|
// A RENDER WITH NO PROFILE PRODUCES NO UNITS, and said so with zero
|
|
3040
2671
|
// bytes and exit 0. The profile is what maps a model onto a
|
|
@@ -3174,18 +2805,19 @@ function renderExit(report, drift) {
|
|
|
3174
2805
|
}
|
|
3175
2806
|
return 0 < drift ? 1 : 0;
|
|
3176
2807
|
}
|
|
3177
|
-
// ---------------------------------------------------------------------
|
|
3178
|
-
// THE TEMPLATE SURFACE (docs/design/TEMPLATE.0.md; RENDER.0.md P8): the
|
|
3179
|
-
// two transforms and the round trip between them. `render` reads a
|
|
3180
|
-
// template directly, by its extension; this verb is for seeing the
|
|
3181
|
-
// canonical form, for writing one by hand and sugaring it, and for the
|
|
3182
|
-
// check that keeps a committed template and its meaning in agreement.
|
|
3183
2808
|
const TEMPLATE_HELP = 'aontu template [--resugar] [--check] [--marker <token>] <file> (try --help)';
|
|
3184
2809
|
function runTemplate(argv) {
|
|
2810
|
+
const trusted = takeTrust(argv);
|
|
2811
|
+
if (null == trusted) {
|
|
2812
|
+
return 2;
|
|
2813
|
+
}
|
|
2814
|
+
argv = trusted.argv;
|
|
2815
|
+
const trust = trusted.trust;
|
|
3185
2816
|
const files = [];
|
|
3186
2817
|
let resugar = false;
|
|
3187
2818
|
let check = false;
|
|
3188
2819
|
let marker = undefined;
|
|
2820
|
+
const profileFiles = [];
|
|
3189
2821
|
for (let i = 0; i < argv.length; i++) {
|
|
3190
2822
|
const arg = argv[i];
|
|
3191
2823
|
if ('-h' === arg || '--help' === arg) {
|
|
@@ -3205,6 +2837,14 @@ function runTemplate(argv) {
|
|
|
3205
2837
|
return 2;
|
|
3206
2838
|
}
|
|
3207
2839
|
}
|
|
2840
|
+
else if ('--profile' === arg) {
|
|
2841
|
+
const pf = argv[++i];
|
|
2842
|
+
if (null == pf) {
|
|
2843
|
+
process.stderr.write('aontu: --profile needs a file\n');
|
|
2844
|
+
return 2;
|
|
2845
|
+
}
|
|
2846
|
+
profileFiles.push(pf);
|
|
2847
|
+
}
|
|
3208
2848
|
else if (arg.startsWith('-')) {
|
|
3209
2849
|
process.stderr.write(`aontu: unknown template option ${arg} (try --help)\n`);
|
|
3210
2850
|
return 2;
|
|
@@ -3217,10 +2857,6 @@ function runTemplate(argv) {
|
|
|
3217
2857
|
process.stderr.write(`aontu: template needs one file\n${TEMPLATE_HELP}\n`);
|
|
3218
2858
|
return 2;
|
|
3219
2859
|
}
|
|
3220
|
-
// THE TWO ARE DIRECTIONS, NOT MODES THAT COMPOSE: `--check` reads a
|
|
3221
|
-
// template and asks whether the round trip answers it back, and
|
|
3222
|
-
// `--resugar` reads the canonical form instead. A run cannot be both
|
|
3223
|
-
// at once, because the file is one thing or the other.
|
|
3224
2860
|
if (resugar && check) {
|
|
3225
2861
|
process.stderr.write('aontu: template takes one of --resugar or --check\n');
|
|
3226
2862
|
return 2;
|
|
@@ -3233,18 +2869,13 @@ function runTemplate(argv) {
|
|
|
3233
2869
|
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
3234
2870
|
return 2;
|
|
3235
2871
|
}
|
|
3236
|
-
const
|
|
2872
|
+
const declared = loadProfiles(profileFiles, trust);
|
|
2873
|
+
if ('number' === typeof declared) {
|
|
2874
|
+
return declared;
|
|
2875
|
+
}
|
|
2876
|
+
const mark = marker ?? (0, template_1.markerFromProfiles)(declared, files[0]) ??
|
|
2877
|
+
(0, template_1.markerFor)(files[0]);
|
|
3237
2878
|
if (check) {
|
|
3238
|
-
// THE ROUND TRIP IS THE CHECK (D6): the file held to the spelling
|
|
3239
|
-
// the two transforms answer. What that names is a marker line the
|
|
3240
|
-
// transform would not have written -- one without its space, or one
|
|
3241
|
-
// whose aontu is indented after the marker rather than before it,
|
|
3242
|
-
// since the marker keeps its own indentation. It does NOT name a
|
|
3243
|
-
// changed body line: a template's whitespace is output, so a
|
|
3244
|
-
// trimmed trailing space is still a valid template and it is
|
|
3245
|
-
// `render --check` against the committed files that catches it.
|
|
3246
|
-
// The first line that differs is the report, since a whole diff of
|
|
3247
|
-
// a generator is the file again.
|
|
3248
2879
|
const back = (0, template_1.resugarTemplate)((0, template_1.desugarTemplate)(src, mark), mark);
|
|
3249
2880
|
if (back === src) {
|
|
3250
2881
|
return 0;
|
|
@@ -3255,12 +2886,6 @@ function runTemplate(argv) {
|
|
|
3255
2886
|
while (n < want.length && n < have.length && want[n] === have[n]) {
|
|
3256
2887
|
n++;
|
|
3257
2888
|
}
|
|
3258
|
-
// THE TWO ARE THE SAME LENGTH, always: each transform maps one
|
|
3259
|
-
// line to one line and applies the same trailing-newline rule, so
|
|
3260
|
-
// `back` has as many lines as `src`. The loop above therefore stops
|
|
3261
|
-
// at a real difference rather than by running out of either -- an
|
|
3262
|
-
// equal prefix all the way to the end IS `back === src`, which
|
|
3263
|
-
// returned above. So both indexes are in range here.
|
|
3264
2889
|
process.stderr.write(`aontu: ${files[0]}:${n + 1} is not what the round trip answers\n` +
|
|
3265
2890
|
` have: ${JSON.stringify(have[n])}\n` +
|
|
3266
2891
|
` want: ${JSON.stringify(want[n])}\n`);
|
|
@@ -3270,13 +2895,38 @@ function runTemplate(argv) {
|
|
|
3270
2895
|
(0, template_1.resugarTemplate)(src, mark) : (0, template_1.desugarTemplate)(src, mark));
|
|
3271
2896
|
return 0;
|
|
3272
2897
|
}
|
|
3273
|
-
//
|
|
3274
|
-
//
|
|
3275
|
-
//
|
|
3276
|
-
//
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
2898
|
+
// The profiles named by --profile, vetted, or the exit code that says
|
|
2899
|
+
// why not. A profile is a language declared as data: `render` matches
|
|
2900
|
+
// one to a unit by `lang`, and `template` and `fmt` match one to a file
|
|
2901
|
+
// by the extensions its `template.ext` names.
|
|
2902
|
+
function loadProfiles(profileFiles, trust) {
|
|
2903
|
+
const profiles = [];
|
|
2904
|
+
const langs = new Map();
|
|
2905
|
+
for (const pf of profileFiles) {
|
|
2906
|
+
let text;
|
|
2907
|
+
try {
|
|
2908
|
+
text = (0, node_fs_1.readFileSync)(pf, 'utf8');
|
|
2909
|
+
}
|
|
2910
|
+
catch (err) {
|
|
2911
|
+
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2912
|
+
return 2;
|
|
2913
|
+
}
|
|
2914
|
+
const loaded = (0, aontu_1.renderProfile)(text, { path: (0, node_path_1.resolve)(pf), ...verbOpts(trust, entryRootOf(pf)) });
|
|
2915
|
+
if (undefined !== loaded.errors) {
|
|
2916
|
+
process.stderr.write(loaded.errors.map(renderFinding).join('\n') + '\n');
|
|
2917
|
+
return 4;
|
|
2918
|
+
}
|
|
2919
|
+
const profile = loaded.profile;
|
|
2920
|
+
const prev = langs.get(profile.lang);
|
|
2921
|
+
if (undefined !== prev) {
|
|
2922
|
+
process.stderr.write(`aontu: two profiles claim ${profile.lang}: ${prev} and ${pf}\n`);
|
|
2923
|
+
return 2;
|
|
2924
|
+
}
|
|
2925
|
+
langs.set(profile.lang, pf);
|
|
2926
|
+
profiles.push(profile);
|
|
2927
|
+
}
|
|
2928
|
+
return profiles;
|
|
2929
|
+
}
|
|
3280
2930
|
const HASH_HELP = 'aontu hash <file> (try --help)';
|
|
3281
2931
|
function runHash(argv) {
|
|
3282
2932
|
const trusted = takeTrust(argv);
|
|
@@ -3331,14 +2981,6 @@ function runHash(argv) {
|
|
|
3331
2981
|
const ctx = aontu.ctx({ collect: true });
|
|
3332
2982
|
const v = aontu.unify(src, { path: files[0] }, ctx);
|
|
3333
2983
|
if (0 < ctx.err.length || true === v?.isNil) {
|
|
3334
|
-
// A document that does not stand up on its own has no meaning to
|
|
3335
|
-
// pin, and a hash of a broken evaluation would be a pin that
|
|
3336
|
-
// silently agrees with every other broken evaluation.
|
|
3337
|
-
// WHY it does not stand up, not just that it does not: the same
|
|
3338
|
-
// diagnosis `aontu <file>` prints (the review's finding F).
|
|
3339
|
-
// evalFailure unconditionally, as every other call site does: it
|
|
3340
|
-
// owns the "ctx.err is never empty here" contract, and a guard
|
|
3341
|
-
// that pretends otherwise is a dead arm asserting nothing.
|
|
3342
2984
|
process.stderr.write(`aontu: ${files[0]} does not evaluate on its own; nothing to hash\n` +
|
|
3343
2985
|
renderFinding((0, query_1.evalFailure)(ctx)) + '\n');
|
|
3344
2986
|
return 4;
|
|
@@ -3353,12 +2995,6 @@ function runHash(argv) {
|
|
|
3353
2995
|
process.stdout.write(text + '\n');
|
|
3354
2996
|
return 0;
|
|
3355
2997
|
}
|
|
3356
|
-
// ---------------------------------------------------------------------
|
|
3357
|
-
// The query surface (G7 phase 1): one node of an evaluated document,
|
|
3358
|
-
// selected by path and rendered. Evaluation is still GLOBAL -- what
|
|
3359
|
-
// `get` buys is the size of the ANSWER, not the cost of producing it --
|
|
3360
|
-
// and the projections are lattice abstractions, each a valid Aontu
|
|
3361
|
-
// document that subsumes the truth it summarises.
|
|
3362
2998
|
const GET_HELP = 'aontu get <path> <file> (try --help)';
|
|
3363
2999
|
function runGet(argv) {
|
|
3364
3000
|
const trusted = takeTrust(argv);
|
|
@@ -3527,11 +3163,6 @@ function runWhy(argv) {
|
|
|
3527
3163
|
}
|
|
3528
3164
|
return 'no_path' === report.findings[0]?.code ? 1 : 4;
|
|
3529
3165
|
}
|
|
3530
|
-
// One contribution per line, numbered in source order, each with what
|
|
3531
|
-
// was written, where, and how it got here. A siteless contribution
|
|
3532
|
-
// prints no location rather than a `-1:-1` that means nothing —
|
|
3533
|
-
// exported for the direct test, because the site SHAPE allows one
|
|
3534
|
-
// while no document has yet produced one (ADR-002).
|
|
3535
3166
|
function renderWhyText(record) {
|
|
3536
3167
|
const head = `${record.path} = ${record.value}`;
|
|
3537
3168
|
if (0 === record.conjuncts.length) {
|
|
@@ -3547,12 +3178,6 @@ function renderWhyText(record) {
|
|
|
3547
3178
|
('literal' === c.role ? '' : ` (${c.role})`);
|
|
3548
3179
|
})).join('\n');
|
|
3549
3180
|
}
|
|
3550
|
-
// ---------------------------------------------------------------------
|
|
3551
|
-
// The overlay patch verb (G7 phase 5): change a document by APPENDING
|
|
3552
|
-
// to an overlay, not by rewriting it. An overlay entry is just another
|
|
3553
|
-
// conjunct and unification is order-independent, so this needs no
|
|
3554
|
-
// rewriter — the format-preserving in-place edit is stage 2, and needs
|
|
3555
|
-
// a comment-preserving CST the parser stack does not have.
|
|
3556
3181
|
const SET_HELP = 'aontu set <path>=<value> --entry <file> --overlay <file> (try --help)';
|
|
3557
3182
|
function runSet(argv) {
|
|
3558
3183
|
const trusted = takeTrust(argv);
|
|
@@ -3659,27 +3284,10 @@ function runSet(argv) {
|
|
|
3659
3284
|
}, 2) + '\n');
|
|
3660
3285
|
}
|
|
3661
3286
|
else {
|
|
3662
|
-
// A replacement is REPORTED as the edit it is, not left for the
|
|
3663
|
-
// reader to infer from a changed file: `where: what -> what`, in
|
|
3664
|
-
// source spelling, because the spelling is what changed.
|
|
3665
|
-
//
|
|
3666
|
-
// PAST TENSE ONLY WHERE IT HAPPENED. A refused write leaves the
|
|
3667
|
-
// file exactly as it was, and one assignment can be replaceable
|
|
3668
|
-
// while another makes the whole run invalid — so `replaced:` there
|
|
3669
|
-
// tells an operator the pin was changed when it was not, and unlike
|
|
3670
|
-
// `--dry-run` there is nothing else on the line to say otherwise.
|
|
3671
3287
|
const verb = wrote ? 'replaced' : 'would replace';
|
|
3672
3288
|
const edits = report.replaced.map((r) => `${verb}: ${r.file}:${r.row}:${r.col} ${r.from} -> ${r.to}`);
|
|
3673
3289
|
const head = [`verdict: ${report.verdict}`].concat(edits).join('\n') +
|
|
3674
3290
|
(wrote ? `\nwrote: ${overlayFile}` : dryRun ? '\n(dry run)' : '');
|
|
3675
|
-
// A SUCCESSFUL COMMAND WRITES ITS STATUS TO STDOUT, findings or
|
|
3676
|
-
// not. Routing on `findings.length` was right while every finding
|
|
3677
|
-
// this verb could produce was an ERROR; `--in-place` made a WARNING
|
|
3678
|
-
// possible, and a run that held, wrote the file and exited 0 then
|
|
3679
|
-
// sent its whole report to stderr — leaving stdout empty, so
|
|
3680
|
-
// `$(aontu set ...)` captured nothing and only the JSON form
|
|
3681
|
-
// behaved like a success. The verdict decides the stream; warnings
|
|
3682
|
-
// are diagnostics and go to stderr beside it.
|
|
3683
3291
|
const failed = 'invalid' === report.verdict || 'error' === report.verdict;
|
|
3684
3292
|
const findingText = report.findings.map(renderFinding);
|
|
3685
3293
|
if (failed) {
|
|
@@ -3698,14 +3306,6 @@ function runSet(argv) {
|
|
|
3698
3306
|
}
|
|
3699
3307
|
return VET_EXIT[report.verdict];
|
|
3700
3308
|
}
|
|
3701
|
-
// ---------------------------------------------------------------------
|
|
3702
|
-
// The role gate (docs/design/ALLOW.0.md): may the role the caller is
|
|
3703
|
-
// operating under modify these subtrees? Asked before `set`, by an
|
|
3704
|
-
// agent whose skill names its role, and answered from a role model
|
|
3705
|
-
// that is itself an aontu document. The verdict is the exit code, as
|
|
3706
|
-
// it is for every gate here: 0 is yes, 1 is no, 4 is "the model that
|
|
3707
|
-
// was to decide does not stand up", and an agent branches on nothing
|
|
3708
|
-
// else.
|
|
3709
3309
|
const ALLOW_HELP = 'aontu allow --role <role> <roles-file> <path> [more-paths...] (try --help)';
|
|
3710
3310
|
const ALLOW_EXIT = {
|
|
3711
3311
|
allowed: 0,
|
|
@@ -3808,14 +3408,6 @@ function runAllow(argv) {
|
|
|
3808
3408
|
process.stderr.write('aontu: --role needs one key, without dots\n');
|
|
3809
3409
|
return 2;
|
|
3810
3410
|
}
|
|
3811
|
-
// A path may arrive in `set`'s spelling, `$.a.b=1`, so a skill can
|
|
3812
|
-
// hand the gate the very arguments the write will get. The text up
|
|
3813
|
-
// to the first `=` is the path, and it starts with `$`: an empty
|
|
3814
|
-
// argument, or a second file name, would otherwise read as a path
|
|
3815
|
-
// and be answered. The VALUE is checked to be one value. `set`
|
|
3816
|
-
// appends it as source after the flattened path, so a value carrying
|
|
3817
|
-
// a second pair -- `3 secrets: key: "x"` -- writes a sibling of the
|
|
3818
|
-
// overlay root, a subtree the gate was never asked about.
|
|
3819
3411
|
const paths = [];
|
|
3820
3412
|
for (const arg of asked) {
|
|
3821
3413
|
const eq = arg.indexOf('=');
|
|
@@ -3949,28 +3541,17 @@ function runAgentsMd(argv) {
|
|
|
3949
3541
|
process.stdout.write(`wrote: ${write}\n`);
|
|
3950
3542
|
return 0;
|
|
3951
3543
|
}
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
// process.exit() terminates immediately, discarding anything still
|
|
3955
|
-
// queued on stdout. A write to a PIPE is asynchronous once it exceeds
|
|
3956
|
-
// the pipe buffer, so `write(big); exit(0)` silently truncated output at
|
|
3957
|
-
// 65536 bytes — while a write to a TTY or a file, being synchronous,
|
|
3958
|
-
// looked fine. Setting exitCode instead lets the process end naturally,
|
|
3959
|
-
// after the queue drains.
|
|
3960
|
-
//
|
|
3961
|
-
// This predates the exact leaves but they make it trivially reachable
|
|
3962
|
-
// (one long biginteger canon exceeds the buffer), and it lands squarely
|
|
3963
|
-
// on the parity-probe discipline in AGENTS.md, which derives expected
|
|
3964
|
-
// spec values by piping BOTH CLIs and comparing. A truncated pipe there
|
|
3965
|
-
// reads as a port divergence.
|
|
3966
|
-
// ---------------------------------------------------------------------
|
|
3967
|
-
// The source formatter (docs/design/FMT.0.md): one agreed form, in the
|
|
3968
|
-
// tradition of gofmt. The verb prints, lists, checks, diffs or rewrites;
|
|
3969
|
-
// the form itself is the library's (ts/src/format.ts), and the two
|
|
3970
|
-
// ports agree on it row by row in test/spec/fmt.tsv.
|
|
3971
|
-
const FMT_HELP = 'aontu fmt [-w|-l|--check|-d|--lint] [--marker <token>] <file>... (try --help)';
|
|
3544
|
+
const FMT_HELP = 'aontu fmt [-w|-l|--check|-d|--lint] [--marker <token>] ' +
|
|
3545
|
+
'[--profile <file>] <file>... (try --help)';
|
|
3972
3546
|
function runFmt(argv) {
|
|
3547
|
+
const trusted = takeTrust(argv);
|
|
3548
|
+
if (null == trusted) {
|
|
3549
|
+
return 2;
|
|
3550
|
+
}
|
|
3551
|
+
argv = trusted.argv;
|
|
3552
|
+
const trust = trusted.trust;
|
|
3973
3553
|
const files = [];
|
|
3554
|
+
const profileFiles = [];
|
|
3974
3555
|
let marker = undefined;
|
|
3975
3556
|
const flags = {
|
|
3976
3557
|
write: false, list: false, check: false, diff: false, lint: false, strict: false,
|
|
@@ -4010,6 +3591,14 @@ function runFmt(argv) {
|
|
|
4010
3591
|
return 2;
|
|
4011
3592
|
}
|
|
4012
3593
|
}
|
|
3594
|
+
else if ('--profile' === arg) {
|
|
3595
|
+
const pf = argv[++i];
|
|
3596
|
+
if (null == pf) {
|
|
3597
|
+
process.stderr.write('aontu: --profile needs a file\n');
|
|
3598
|
+
return 2;
|
|
3599
|
+
}
|
|
3600
|
+
profileFiles.push(pf);
|
|
3601
|
+
}
|
|
4013
3602
|
else if (arg.startsWith('-')) {
|
|
4014
3603
|
process.stderr.write(`aontu: unknown fmt option ${arg} (try --help)\n`);
|
|
4015
3604
|
return 2;
|
|
@@ -4033,6 +3622,10 @@ function runFmt(argv) {
|
|
|
4033
3622
|
process.stdin.on('end', () => resolve(fmtOne('<stdin>', src, flags, marker)));
|
|
4034
3623
|
});
|
|
4035
3624
|
}
|
|
3625
|
+
const declared = loadProfiles(profileFiles, trust);
|
|
3626
|
+
if ('number' === typeof declared) {
|
|
3627
|
+
return declared;
|
|
3628
|
+
}
|
|
4036
3629
|
// Several files onto standard output would be one stream nobody can
|
|
4037
3630
|
// split again (the note's X-6): the verb refuses unless an option
|
|
4038
3631
|
// says what to do with each.
|
|
@@ -4051,32 +3644,18 @@ function runFmt(argv) {
|
|
|
4051
3644
|
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
4052
3645
|
return 2;
|
|
4053
3646
|
}
|
|
4054
|
-
const mark = fmtMarker(file, src, marker);
|
|
3647
|
+
const mark = fmtMarker(file, src, marker ?? (0, template_1.markerFromProfiles)(declared, file));
|
|
4055
3648
|
if (false === mark) {
|
|
4056
3649
|
process.stderr.write(`aontu: ${file} is not aontu source (.aon, .aontu) and carries no ` +
|
|
4057
3650
|
`${(0, template_1.markerFor)(file)} marker line, so there is no aontu in it to ` +
|
|
4058
|
-
'format; --marker names the marker for a language the table
|
|
4059
|
-
'not know\n');
|
|
3651
|
+
'format; --marker names the marker for a language the table ' +
|
|
3652
|
+
'does not know, and --profile reads one that declares it\n');
|
|
4060
3653
|
return 2;
|
|
4061
3654
|
}
|
|
4062
3655
|
worst = Math.max(worst, fmtOne(file, src, flags, mark));
|
|
4063
3656
|
}
|
|
4064
3657
|
return worst;
|
|
4065
3658
|
}
|
|
4066
|
-
// WHAT A FILE IS, BY ITS EXTENSION (ADR-012's rule, and the one
|
|
4067
|
-
// `render` reads an entry by): `.aon` and `.aontu` are aontu source,
|
|
4068
|
-
// and anything else is a GENERATOR written in the target's own syntax
|
|
4069
|
-
// (docs/design/TEMPLATE.0.md), whose marker lines carry the document
|
|
4070
|
-
// this formats and whose other lines are output. `undefined` is aontu,
|
|
4071
|
-
// a string is the generator's marker, and `false` is neither.
|
|
4072
|
-
//
|
|
4073
|
-
// A FILE WITH NO MARKER LINE IN IT IS NEITHER, and that is what keeps
|
|
4074
|
-
// FMT.0.md §9's boundary where it stood: a `.json`, `.yaml` or `.toml`
|
|
4075
|
-
// include is another language's file, and reading one as a generator
|
|
4076
|
-
// would answer it back unchanged having understood none of it. The
|
|
4077
|
-
// marker is the evidence that a file was written to carry aontu at
|
|
4078
|
-
// all. `--marker` says so outright, and then the file is a generator
|
|
4079
|
-
// whatever it is called.
|
|
4080
3659
|
function fmtMarker(file, src, marker) {
|
|
4081
3660
|
if (undefined !== marker) {
|
|
4082
3661
|
return marker;
|
|
@@ -4132,11 +3711,8 @@ function fmtOne(name, src, flags, marker) {
|
|
|
4132
3711
|
}
|
|
4133
3712
|
return flags.check ? 1 : strict;
|
|
4134
3713
|
}
|
|
4135
|
-
//
|
|
4136
|
-
//
|
|
4137
|
-
// cli.test.ts run each through a child process instead, so these two
|
|
4138
|
-
// lines are excluded from the in-process count, as the stdio wiring
|
|
4139
|
-
// of lsp-server.ts is.
|
|
3714
|
+
// Excluded: the real pair takes the process stdio, so ts/test/cli.test.ts
|
|
3715
|
+
// drives each server through a child process instead.
|
|
4140
3716
|
/* node:coverage ignore next 4 */
|
|
4141
3717
|
const SERVERS = {
|
|
4142
3718
|
lsp: () => void (0, lsp_server_1.main)(),
|
|
@@ -4176,19 +3752,6 @@ function parseTrustArg(value) {
|
|
|
4176
3752
|
}
|
|
4177
3753
|
return undefined;
|
|
4178
3754
|
}
|
|
4179
|
-
// THE TEACHING PACK, SERVED FROM THE COMMAND (G11 phase 1,
|
|
4180
|
-
// docs/capability-review/g11-agent-onramp.md; mirrors
|
|
4181
|
-
// go/cmd/aontu/help.go).
|
|
4182
|
-
//
|
|
4183
|
-
// HELP documents the TOOLCHAIN and says nothing about the LANGUAGE:
|
|
4184
|
-
// `&`, the map template and the one construct an ontology cannot be
|
|
4185
|
-
// written without, occurs zero times in it, while `template` occurs
|
|
4186
|
-
// fourteen times and names an unrelated verb every time. docs/skill/
|
|
4187
|
-
// was already the right content and already gated; the gap was
|
|
4188
|
-
// DELIVERY, since it reached an installation as
|
|
4189
|
-
// node_modules/aontu/skill/ where nothing looks. ts/src/helpdoc.ts is
|
|
4190
|
-
// generated from those sources by ts/scripts/helpdoc.cjs and asserted
|
|
4191
|
-
// byte-identical with them by ts/test/helpdoc.test.ts.
|
|
4192
3755
|
const HELP_VERB_HELP = 'aontu help [topic] (try `aontu help` for the topics)';
|
|
4193
3756
|
const EXPLAIN_HELP = 'aontu explain <code> (try `aontu explain --list`)';
|
|
4194
3757
|
function helpIndexText(index) {
|
|
@@ -4260,22 +3823,6 @@ function runHelp(argv) {
|
|
|
4260
3823
|
`aontu: topics are ${helpdoc_1.HELPDOC.map((t) => t.topic).join(', ')}\n`);
|
|
4261
3824
|
return 2;
|
|
4262
3825
|
}
|
|
4263
|
-
// `aontu explain <code>` (G11 phase 3; mirrors
|
|
4264
|
-
// go/cmd/aontu/explain.go).
|
|
4265
|
-
//
|
|
4266
|
-
// THE REGISTRY IS THE LIST, NOT THE HINT TABLE. test/spec/errcodes.tsv
|
|
4267
|
-
// registers 157 codes and the spec suite asserts set equality between
|
|
4268
|
-
// the file and codeClasses IN BOTH PORTS, so listing from codeClasses
|
|
4269
|
-
// is listing the shared contract. The hint tables are smaller and are
|
|
4270
|
-
// NOT in parity -- 130 entries here against 131 in Go, the extra being
|
|
4271
|
-
// decimal_syntax, which this port never raises -- so listing from them
|
|
4272
|
-
// would make `aontu explain --list` differ between ports over a
|
|
4273
|
-
// difference that is not about what either port can report.
|
|
4274
|
-
//
|
|
4275
|
-
// A REGISTERED CODE WITH NO HINT ANSWERS WITH ITS CLASS AND SAYS SO.
|
|
4276
|
-
// Twenty-seven registered codes carry no explanation text here; before
|
|
4277
|
-
// this verb their absence was invisible, because a hint is only ever
|
|
4278
|
-
// seen beside the error that raises it.
|
|
4279
3826
|
// The dynamic prefixes a generated code extends (`func:upper`,
|
|
4280
3827
|
// `op[+]`). Mirrors CODE_PREFIXES in ts/src/hints.ts, which is not
|
|
4281
3828
|
// exported; a code that extends one is registered through its prefix
|
|
@@ -4399,20 +3946,6 @@ function runExplain(argv) {
|
|
|
4399
3946
|
process.stdout.write(`code: ${code}\nclass: ${cls}\n\n${body}\n`);
|
|
4400
3947
|
return 0;
|
|
4401
3948
|
}
|
|
4402
|
-
// `aontu init` (G11 phase 6,
|
|
4403
|
-
// docs/capability-review/g11-agent-onramp.md).
|
|
4404
|
-
//
|
|
4405
|
-
// NOT SCAFFOLDING CONVENIENCE. The agent's most expensive failure is
|
|
4406
|
-
// writing a FIRST document at all: the measurement that opened G11
|
|
4407
|
-
// found one reaching for the wildcard its neighbours use and getting
|
|
4408
|
-
// `verdict: valid` over data that violates it. A known-good starting
|
|
4409
|
-
// document turns generation into editing, which is the operation a
|
|
4410
|
-
// model is reliably good at.
|
|
4411
|
-
//
|
|
4412
|
-
// The trio is real, runnable and tested where it lives
|
|
4413
|
-
// (docs/skill/init/, run by ts/test/helpdoc.test.ts), and staged into
|
|
4414
|
-
// both ports by the same generator that stages the teaching pack, so
|
|
4415
|
-
// the two write the same bytes.
|
|
4416
3949
|
const INIT_HELP = 'aontu init [dir] (try --help)';
|
|
4417
3950
|
function runInit(argv) {
|
|
4418
3951
|
const dirs = [];
|
|
@@ -4432,10 +3965,6 @@ function runInit(argv) {
|
|
|
4432
3965
|
return 2;
|
|
4433
3966
|
}
|
|
4434
3967
|
const dir = dirs[0] ?? '.';
|
|
4435
|
-
// REFUSES TO OVERWRITE, and checks every member BEFORE writing any of
|
|
4436
|
-
// them: a scaffold that wrote two files and then refused the third
|
|
4437
|
-
// would leave a directory in a state neither the caller nor a re-run
|
|
4438
|
-
// can reason about.
|
|
4439
3968
|
const standing = helpdoc_1.INITDOC.filter((f) => (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, f.name)));
|
|
4440
3969
|
if (0 < standing.length) {
|
|
4441
3970
|
process.stderr.write(`aontu: ${dir} already holds ${standing.map((f) => f.name).join(', ')}\n` +
|
|
@@ -4459,12 +3988,6 @@ function runInit(argv) {
|
|
|
4459
3988
|
'Learn the language: aontu help language\n');
|
|
4460
3989
|
return 0;
|
|
4461
3990
|
}
|
|
4462
|
-
// EVERY VERB THIS PORT DISPATCHES, for the nearest-verb suggestion
|
|
4463
|
-
// G11 phase 2 prints. A separate list from the if-chain in main()
|
|
4464
|
-
// because the chain's arms have three different shapes and cannot be
|
|
4465
|
-
// a table; ts/test/cli-help.test.ts keeps the two from drifting by
|
|
4466
|
-
// running each name and requiring it not to fall through to the bare
|
|
4467
|
-
// command.
|
|
4468
3991
|
const KNOWN_VERBS = [
|
|
4469
3992
|
'agentsmd', 'allow', 'breaking', 'explain', 'fmt', 'get', 'hash',
|
|
4470
3993
|
'help', 'init', 'jsonschema', 'lsp', 'mcp', 'mod', 'reaches',
|
|
@@ -4481,13 +4004,6 @@ function looksLikeVerb(arg) {
|
|
|
4481
4004
|
!/[/\\.]/.test(arg) &&
|
|
4482
4005
|
!arg.startsWith('-');
|
|
4483
4006
|
}
|
|
4484
|
-
// NEAREST-VERB SUGGESTION (G11 phase 2). Restricted
|
|
4485
|
-
// Damerau-Levenshtein with a cap that grows with the word and stops at
|
|
4486
|
-
// three: one edit is a convincing suggestion on any length, three is
|
|
4487
|
-
// the most that can be believed on a long one, and an UNCAPPED
|
|
4488
|
-
// nearest match on a three-letter typo names something unrelated with
|
|
4489
|
-
// confidence. Mirrors go/cmd/aontu/help.go, including the sort, so
|
|
4490
|
-
// the two ports suggest the same verb on a tie.
|
|
4491
4007
|
function nearestVerb(word, verbs) {
|
|
4492
4008
|
let best = '';
|
|
4493
4009
|
let bestDist = Infinity;
|
|
@@ -4501,8 +4017,6 @@ function nearestVerb(word, verbs) {
|
|
|
4501
4017
|
}
|
|
4502
4018
|
return bestDist > limit ? '' : best;
|
|
4503
4019
|
}
|
|
4504
|
-
// Levenshtein with a transposition, iterative over two rows. Mirrors
|
|
4505
|
-
// editDistance in go/cmd/aontu/help.go exactly.
|
|
4506
4020
|
function editDistance(a, b) {
|
|
4507
4021
|
const ar = [...a];
|
|
4508
4022
|
const br = [...b];
|
|
@@ -4527,25 +4041,12 @@ function editDistance(a, b) {
|
|
|
4527
4041
|
return prev[br.length];
|
|
4528
4042
|
}
|
|
4529
4043
|
function main(argv, servers = SERVERS) {
|
|
4530
|
-
// COLOUR OFF WHEN THE DESTINATION IS NOT A TERMINAL. Error frames
|
|
4531
|
-
// hardcoded their ANSI escapes, so a piped report and a `--jsonl`
|
|
4532
|
-
// answer carried terminal control codes into whatever read them (the
|
|
4533
|
-
// review's finding F). `NO_COLOR` is honoured by the library itself;
|
|
4534
|
-
// only the CLI can see whether its stderr is a terminal, so only the
|
|
4535
|
-
// CLI can make this call. `undefined` means "leave it to NO_COLOR".
|
|
4536
4044
|
(0, aontu_1.setColor)(true === process.stderr.isTTY ? undefined : false);
|
|
4537
4045
|
let mode = 'json';
|
|
4538
4046
|
// THE REPORT FORM (G11 phase 7), default text: every existing caller
|
|
4539
4047
|
// reads exactly what it always read, and a caller that asks for json
|
|
4540
4048
|
// gets the failure in the finding shape every other verb reports.
|
|
4541
4049
|
let format = 'text';
|
|
4542
|
-
// A LIST, though the bare command evaluates exactly one document.
|
|
4543
|
-
// It used to be one variable and the last argument won, which made a
|
|
4544
|
-
// MISTYPED VERB a silent success: `aontu vet2 schema.aon good.json`
|
|
4545
|
-
// printed good.json and exited 0, because `vet2` matched no
|
|
4546
|
-
// subcommand, fell through to this loop as a file name, and was
|
|
4547
|
-
// overwritten twice. In a tool loop that reads as a passing
|
|
4548
|
-
// validation. Counting them is what lets the refusal below happen.
|
|
4549
4050
|
const files = [];
|
|
4550
4051
|
let trust = { kind: 'system-warn', textExt: [] };
|
|
4551
4052
|
let textExt = [];
|
|
@@ -4554,15 +4055,6 @@ function main(argv, servers = SERVERS) {
|
|
|
4554
4055
|
// than the design's --json, which would read as the `:json` output
|
|
4555
4056
|
// mode the REPL already has.
|
|
4556
4057
|
let jsonl = false;
|
|
4557
|
-
// Subcommand dispatch, and deliberately only for a FIRST argument:
|
|
4558
|
-
// `aontu vet` is the verb, while `aontu somefile vet` keeps meaning
|
|
4559
|
-
// what it always did. A file named `vet` is still reachable as
|
|
4560
|
-
// `aontu ./vet`.
|
|
4561
|
-
//
|
|
4562
|
-
// Promise.resolve either way: a non-watch run returns its exit class
|
|
4563
|
-
// synchronously (and has already written its report), while `--watch`
|
|
4564
|
-
// resolves only when the watch ends — so one await-shaped line serves
|
|
4565
|
-
// both without a branch to keep covered.
|
|
4566
4058
|
if ('vet' === argv[2]) {
|
|
4567
4059
|
return void Promise.resolve(runVet(argv.slice(3))).then(finish);
|
|
4568
4060
|
}
|
|
@@ -4699,23 +4191,12 @@ function main(argv, servers = SERVERS) {
|
|
|
4699
4191
|
files.push(arg);
|
|
4700
4192
|
}
|
|
4701
4193
|
}
|
|
4702
|
-
// ONE DOCUMENT. The bare form has always been `aontu [options]
|
|
4703
|
-
// [file]`, singular, and anything past the first was silently
|
|
4704
|
-
// discarded rather than refused -- so every way of getting the verb
|
|
4705
|
-
// wrong (a typo, a verb this port does not have, a verb spelled for
|
|
4706
|
-
// another tool) ended in a plausible answer about the wrong file.
|
|
4707
|
-
// Exit 2, the usage class, and the message names the cause rather
|
|
4708
|
-
// than the symptom: nothing here can tell a mistyped verb from a
|
|
4709
|
-
// second file, but the reader can.
|
|
4710
4194
|
if (1 < files.length) {
|
|
4711
4195
|
process.stderr.write(`aontu: the bare command evaluates one document, and ${files.length}` +
|
|
4712
4196
|
' were given\naontu: a mistyped verb reads as a file name' +
|
|
4713
4197
|
' (try --help)\n');
|
|
4714
4198
|
return finish(2);
|
|
4715
4199
|
}
|
|
4716
|
-
// The extensions ride with the capability from here on, so the three
|
|
4717
|
-
// entry shapes below (file, REPL, stdin) each get them by threading
|
|
4718
|
-
// the one value they already thread.
|
|
4719
4200
|
trust = { ...trust, textExt };
|
|
4720
4201
|
const file = files[0];
|
|
4721
4202
|
if (null != file) {
|