aontu 0.61.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 +4 -4
- package/dist/agentsmd.d.ts +1 -0
- package/dist/agentsmd.js +7 -28
- package/dist/agentsmd.js.map +1 -1
- package/dist/alias.js.map +1 -1
- package/dist/allow.d.ts +23 -0
- package/dist/allow.js +138 -0
- package/dist/allow.js.map +1 -0
- package/dist/aontu.d.ts +4 -2
- package/dist/aontu.js +4 -80
- 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.d.ts +10 -1
- package/dist/cli.js +877 -479
- 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 +55 -189
- 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.d.ts +16 -0
- package/dist/helpdoc.js +59 -0
- package/dist/helpdoc.js.map +1 -0
- package/dist/hints.d.ts +0 -6
- package/dist/hints.js +59 -47
- 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 +32 -877
- package/dist/lang.js.map +1 -1
- package/dist/lower.d.ts +3 -0
- package/dist/lower.js +14 -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.d.ts +2 -0
- package/dist/relation.js +3 -58
- package/dist/relation.js.map +1 -1
- package/dist/render.js +33 -143
- 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.d.ts +20 -0
- package/dist/val/CmpFuncVal.js +188 -0
- package/dist/val/CmpFuncVal.js.map +1 -0
- 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.d.ts +1 -2
- package/dist/val/EachFuncVal.js +12 -29
- 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 +11 -6
- 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 +2 -36
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/NomFuncVal.d.ts +12 -0
- package/dist/val/NomFuncVal.js +153 -0
- package/dist/val/NomFuncVal.js.map +1 -0
- 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.d.ts +12 -0
- package/dist/val/TranslateFuncVal.js +99 -0
- package/dist/val/TranslateFuncVal.js.map +1 -0
- package/dist/val/UpperFuncVal.js +11 -6
- 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.d.ts +3 -0
- package/dist/val/caserange.js +49 -0
- package/dist/val/caserange.js.map +1 -0
- 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.d.ts +12 -0
- package/dist/vet.js +159 -412
- 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 +9 -7
- package/grammar/aontu.gbnf +5 -5
- package/grammar/aontu.lark +5 -5
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +4 -2
- package/skill/SKILL.md +8 -0
- package/skill/init/check.sh +28 -0
- package/skill/init/data.aon +12 -0
- package/skill/init/model.aon +19 -0
- package/skill/tasks.md +151 -0
- package/src/agentsmd.ts +8 -32
- package/src/alias.ts +0 -39
- package/src/allow.ts +221 -0
- package/src/aontu.ts +10 -108
- package/src/aontumodel.ts +32 -0
- package/src/cli.ts +1009 -540
- 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 +63 -234
- package/src/grammar.ts +72 -0
- package/src/graph.ts +0 -61
- package/src/hcanon.ts +0 -82
- package/src/helpdoc.ts +77 -0
- package/src/hints.ts +72 -49
- package/src/jsonschema.ts +0 -123
- package/src/keyorder.ts +0 -42
- package/src/lang.ts +39 -895
- package/src/lower.ts +15 -65
- 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 +7 -71
- package/src/render.ts +33 -180
- 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 +249 -0
- 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 +12 -53
- 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 +12 -7
- 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 +2 -36
- package/src/val/NomFuncVal.ts +200 -0
- 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 +132 -0
- package/src/val/UpperFuncVal.ts +12 -7
- 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 +53 -0
- 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 +209 -504
- package/src/view.ts +0 -507
- package/src/walk.ts +0 -41
- package/dist/std.d.ts +0 -3
- package/dist/std.js +0 -637
- package/dist/std.js.map +0 -1
- package/dist/val/FormFuncVal.js +0 -55
- package/dist/val/FormFuncVal.js.map +0 -1
- package/src/std.ts +0 -648
- package/src/val/FormFuncVal.ts +0 -119
package/src/mcp.ts
CHANGED
|
@@ -1,29 +1,5 @@
|
|
|
1
1
|
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
|
-
// THE MCP TOOL LIBRARY (G7 phase 6,
|
|
4
|
-
// docs/capability-review/g7-machine-access.md; completed to the full
|
|
5
|
-
// CLI verb surface by the use-case review's MCP recommendation,
|
|
6
|
-
// use-cases/SUPPORT.md): the verbs an agent calls, over the Model
|
|
7
|
-
// Context Protocol, as a transport-free library. The split follows
|
|
8
|
-
// the LSP's (docs/lsp.md): this file is the protocol and the tools,
|
|
9
|
-
// ts/src/mcp-server.ts is stdio and nothing else, and the whole thing
|
|
10
|
-
// is testable without a socket.
|
|
11
|
-
//
|
|
12
|
-
// Every tool returns THE SAME JSON CONTRACT THE CLI PRINTS. That is
|
|
13
|
-
// the point of the surface: an agent that has read `aontu vet
|
|
14
|
-
// --format json` output knows what the `vet` tool answers, and a
|
|
15
|
-
// report copied from one to the other is the same object. The tools
|
|
16
|
-
// add no vocabulary of their own.
|
|
17
|
-
//
|
|
18
|
-
// The server evaluates under a CONFINED resolver (G5, docs/trust.md):
|
|
19
|
-
// a caller hands source text, and text that could reach out through
|
|
20
|
-
// `@"..."` is exactly what a server must not run unconfined. By
|
|
21
|
-
// default every include is denied; a server started with
|
|
22
|
-
// `--root <dir>` (ts/src/mcp-server.ts) resolves includes confined
|
|
23
|
-
// below that root instead — the CLI's `--trust root:<dir>` posture —
|
|
24
|
-
// and lets every document argument arrive as a `<name>Path` file
|
|
25
|
-
// under the same root. The package-resolver leg is never enabled
|
|
26
|
-
// here.
|
|
27
3
|
|
|
28
4
|
import { readFileSync, realpathSync } from 'node:fs'
|
|
29
5
|
import {
|
|
@@ -71,7 +47,6 @@ export type McpResponse = {
|
|
|
71
47
|
}
|
|
72
48
|
|
|
73
49
|
|
|
74
|
-
// JSON-RPC's own codes, the three a server this small can raise.
|
|
75
50
|
const PARSE_ERROR = -32700
|
|
76
51
|
const METHOD_NOT_FOUND = -32601
|
|
77
52
|
const INVALID_PARAMS = -32602
|
|
@@ -91,13 +66,6 @@ export type ToolDef = {
|
|
|
91
66
|
// Argument validation beyond "required and a string": the message
|
|
92
67
|
// for a call that could not be made, or undefined for a good call.
|
|
93
68
|
check?: (a: any) => string | undefined
|
|
94
|
-
// ENGINES THAT TAKE NO TRUST PROFILE (subsume, trimCheck,
|
|
95
|
-
// relationCheck, patch) build their own evaluators, so the served
|
|
96
|
-
// profile cannot ride into them as an argument the way it rides
|
|
97
|
-
// into vet or get. Their documents are PRE-PARSED under the profile
|
|
98
|
-
// by callTool instead (confinedParseFailure below), and `refuse` is
|
|
99
|
-
// the tool's own error report for a document that fails it. A tool
|
|
100
|
-
// whose engine takes `trust` directly declares no `refuse`.
|
|
101
69
|
refuse?: (
|
|
102
70
|
a: any, finding: VetFinding, trust: TrustOptions,
|
|
103
71
|
paths: Record<string, string>) => any
|
|
@@ -106,22 +74,6 @@ export type ToolDef = {
|
|
|
106
74
|
}
|
|
107
75
|
|
|
108
76
|
|
|
109
|
-
// The trust profile a served evaluation runs under: no includes at
|
|
110
|
-
// all — or, when the server was started with --root, includes
|
|
111
|
-
// realpath-confined below that root (the CLI's `--trust root:<dir>`
|
|
112
|
-
// semantics; docs/trust.md). The package-resolver leg is enabled by
|
|
113
|
-
// neither.
|
|
114
|
-
//
|
|
115
|
-
// The profile is INJECTED into every tool by callTool rather than
|
|
116
|
-
// applied by each tool for itself. That is deliberate: four of the six
|
|
117
|
-
// original tools once called the library with no profile at all, so a
|
|
118
|
-
// served `@"x.js"` was require()d in the server process, while the
|
|
119
|
-
// module header claimed confinement. (That particular include is
|
|
120
|
-
// refused outright now -- ADR-012 -- but a served document could still
|
|
121
|
-
// read every file the server can.) A tool that must remember to
|
|
122
|
-
// confine itself is a tool that eventually forgets, and the forgetting
|
|
123
|
-
// is silent. With the profile arriving as an argument, a tool cannot
|
|
124
|
-
// run unconfined without visibly discarding it.
|
|
125
77
|
export function servedTrust(root?: string): TrustOptions {
|
|
126
78
|
return null == root
|
|
127
79
|
? { include: 'none' }
|
|
@@ -133,17 +85,6 @@ function served(trust: TrustOptions): Aontu {
|
|
|
133
85
|
}
|
|
134
86
|
|
|
135
87
|
|
|
136
|
-
// DOES THIS DOCUMENT STAND UP UNDER THE SERVED PROFILE — or the
|
|
137
|
-
// finding that says why not. This is the confinement gate for the
|
|
138
|
-
// engines that take no trust profile, and parse is the whole include
|
|
139
|
-
// story: `@"..."` resolves at parse time (ts/src/lang.ts), so a
|
|
140
|
-
// document whose confined parse is clean either has no includes at
|
|
141
|
-
// all (capability 'none') or resolves every one below the root — and
|
|
142
|
-
// an engine that then re-resolves the same closure under the default
|
|
143
|
-
// profile reads exactly the files the confined parse proved in
|
|
144
|
-
// bounds. A parse that fails for any reason refuses the call: an
|
|
145
|
-
// engine's own answer for a document this profile cannot read is not
|
|
146
|
-
// an answer this server may compute.
|
|
147
88
|
export function confinedParseFailure(
|
|
148
89
|
src: string, trust: TrustOptions, path?: string
|
|
149
90
|
): VetFinding | undefined {
|
|
@@ -154,18 +95,6 @@ export function confinedParseFailure(
|
|
|
154
95
|
}
|
|
155
96
|
|
|
156
97
|
|
|
157
|
-
// Confinement is realpath-then-prefix-check, mirroring the include
|
|
158
|
-
// resolver's own rule (ts/src/lang.ts, docs/trust.md): the file's
|
|
159
|
-
// real path must sit below the root's real path, so a symlink inside
|
|
160
|
-
// the root pointing outside it is an escape, not a loophole.
|
|
161
|
-
//
|
|
162
|
-
// A path that does not (fully) exist cannot be realpath'd whole, and
|
|
163
|
-
// falling back to the LEXICAL form compares apples to oranges when the
|
|
164
|
-
// root itself sits behind a symlink -- on macOS a root under /var
|
|
165
|
-
// realpaths to /private/var, so a merely-missing file inside it read
|
|
166
|
-
// as an escape instead of "cannot read" (the CI failure that bought
|
|
167
|
-
// this comment). Realpath the deepest EXISTING ancestor and re-attach
|
|
168
|
-
// the rest, so both sides of the prefix check are in real coordinates.
|
|
169
98
|
function realpathOf(p: string): string {
|
|
170
99
|
try {
|
|
171
100
|
return realpathSync(p)
|
|
@@ -301,8 +230,6 @@ const TOOLS: ToolDef[] = [
|
|
|
301
230
|
run: (a, trust, paths) => summaryOf(str(a.src), trust, paths.src),
|
|
302
231
|
},
|
|
303
232
|
|
|
304
|
-
// The evolution and change verbs (the use-case review's "MCP is a
|
|
305
|
-
// read-only subset" gap, use-cases/09-agent-tools/README.md gap 11).
|
|
306
233
|
|
|
307
234
|
{
|
|
308
235
|
name: 'subsume',
|
|
@@ -419,11 +346,6 @@ const TOOLS: ToolDef[] = [
|
|
|
419
346
|
},
|
|
420
347
|
required: ['source'],
|
|
421
348
|
docs: ['source'],
|
|
422
|
-
// The pre-parse finding rides `errors`, exactly where the engine
|
|
423
|
-
// puts its own reason for a document that does not stand up
|
|
424
|
-
// (ts/src/relation.ts, the review's finding F). NOT `findings`:
|
|
425
|
-
// RelationFinding is its own vocabulary (code, relation, at,
|
|
426
|
-
// detail) and a document with no graph has no graph findings.
|
|
427
349
|
refuse: (_a, finding) =>
|
|
428
350
|
({ verdict: 'error', findings: [], errors: [finding] }),
|
|
429
351
|
run: (a, _trust, paths) =>
|
|
@@ -644,9 +566,6 @@ const TOOLS: ToolDef[] = [
|
|
|
644
566
|
},
|
|
645
567
|
required: ['source'],
|
|
646
568
|
docs: ['source'],
|
|
647
|
-
// The pre-parse finding rides `errors`, exactly where the engine
|
|
648
|
-
// puts its own reason for a document that does not stand up
|
|
649
|
-
// (ts/src/trim.ts, the review's finding F).
|
|
650
569
|
refuse: (_a, finding) =>
|
|
651
570
|
({ verdict: 'error', redundant: [], errors: [finding] }),
|
|
652
571
|
run: (a, _trust, paths) =>
|
|
@@ -784,15 +703,6 @@ function hashOf(
|
|
|
784
703
|
}
|
|
785
704
|
|
|
786
705
|
|
|
787
|
-
// ---------------------------------------------------------------------
|
|
788
|
-
// THE BREAKING POLICY WRAPPER. Re-implemented from ts/src/cli.ts
|
|
789
|
-
// (runBreaking and policyCompat) rather than extracted from it: cli.ts
|
|
790
|
-
// owns the process-facing halves — files, git revisions, exit codes,
|
|
791
|
-
// rendering — that a served tool must not import, and the policy
|
|
792
|
-
// itself (which mode applies, which side is general, how verdicts
|
|
793
|
-
// aggregate) is small enough that a shared home would be all seam.
|
|
794
|
-
// cli.ts is the reference; a change there is a change here.
|
|
795
|
-
|
|
796
706
|
type BreakingMode = 'backward' | 'forward' | 'full' | 'none'
|
|
797
707
|
|
|
798
708
|
// Verdict aggregation: an error anywhere makes the run an error;
|
|
@@ -844,8 +754,6 @@ function policyCompatOf(
|
|
|
844
754
|
}
|
|
845
755
|
|
|
846
756
|
|
|
847
|
-
// The declared mode: the mode argument overrides the document's own
|
|
848
|
-
// policy; neither means backward (v1-valid documents stay valid).
|
|
849
757
|
function breakingMode(
|
|
850
758
|
a: any, trust: TrustOptions, paths: Record<string, string>
|
|
851
759
|
): BreakingMode {
|
|
@@ -867,8 +775,6 @@ function breakingOf(
|
|
|
867
775
|
new: { src: str(a.new), url: paths.new ?? 'new', path: paths.new },
|
|
868
776
|
}
|
|
869
777
|
|
|
870
|
-
// backward: the NEW document is the general side — every old
|
|
871
|
-
// instance must still be admitted. forward: the old one is.
|
|
872
778
|
const checks: Array<{
|
|
873
779
|
general: typeof sides.old, specific: typeof sides.old
|
|
874
780
|
}> = []
|
|
@@ -898,11 +804,6 @@ function breakingOf(
|
|
|
898
804
|
}
|
|
899
805
|
|
|
900
806
|
|
|
901
|
-
// ---------------------------------------------------------------------
|
|
902
|
-
// The set tool: the CLI's `set` verb minus the filesystem — the patch
|
|
903
|
-
// engine (ts/src/patch.ts) already answers with the new overlay text,
|
|
904
|
-
// and the caller owns the write.
|
|
905
|
-
|
|
906
807
|
// The assignments arrive structured ({path, value}) rather than as the
|
|
907
808
|
// CLI's `<path>=<value>` spelling, and are re-joined for the engine's
|
|
908
809
|
// parseAssignment — so the path must not smuggle a `=` that would move
|
|
@@ -937,12 +838,6 @@ function setError(overlay: string, finding: VetFinding): any {
|
|
|
937
838
|
|
|
938
839
|
function setOf(
|
|
939
840
|
a: any, trust: TrustOptions, paths: Record<string, string>): any {
|
|
940
|
-
// THE ASSIGNMENT VALUES ARE DOCUMENTS TOO: each one is appended (or
|
|
941
|
-
// spliced) into the overlay and evaluated there by the engine's
|
|
942
|
-
// final vet, so a value that smuggles an include — or a newline and
|
|
943
|
-
// then an include — gets the same confined pre-parse as the
|
|
944
|
-
// documents themselves, wrapped exactly as the engine's own
|
|
945
|
-
// spanValue wraps a fragment (ts/src/patch.ts).
|
|
946
841
|
for (const x of a.assignments) {
|
|
947
842
|
const denied = confinedParseFailure('v: ' + x.value, trust, paths.overlay)
|
|
948
843
|
if (null != denied) {
|
|
@@ -960,13 +855,6 @@ function setOf(
|
|
|
960
855
|
}
|
|
961
856
|
|
|
962
857
|
|
|
963
|
-
// ---------------------------------------------------------------------
|
|
964
|
-
// The tool list as MCP spells it: a name, a description, and a JSON
|
|
965
|
-
// Schema for the arguments. With a served root, every document
|
|
966
|
-
// property gains its `<name>Path` file alternative — and comes OFF the
|
|
967
|
-
// `required` list, because JSON Schema's `required` cannot say "one of
|
|
968
|
-
// the two"; callTool's own argument check still refuses a call that
|
|
969
|
-
// carries neither.
|
|
970
858
|
export function toolList(root?: string): any[] {
|
|
971
859
|
return TOOLS.map((t) => {
|
|
972
860
|
const properties: Record<string, any> = { ...t.properties }
|
|
@@ -1000,17 +888,6 @@ function refusal(text: string): any {
|
|
|
1000
888
|
}
|
|
1001
889
|
|
|
1002
890
|
|
|
1003
|
-
// One tool call. A tool that REFUSES (an invalid document, a path that
|
|
1004
|
-
// names nothing, a document the served profile cannot read) is not a
|
|
1005
|
-
// protocol error: it answers with its own report and `isError` false,
|
|
1006
|
-
// because the report IS the answer the agent asked for. `isError` is
|
|
1007
|
-
// reserved for a call that could not be made at all — an unknown tool,
|
|
1008
|
-
// a missing or malformed argument, a file argument the server cannot
|
|
1009
|
-
// serve.
|
|
1010
|
-
// `opts.tools` is injectable for the same reason the watch loop's
|
|
1011
|
-
// waiter is: the catch below is defensive code no document reaches --
|
|
1012
|
-
// every verb answers with a report rather than throwing -- and code
|
|
1013
|
-
// the suite cannot execute is code the ADR-002 floor cannot hold.
|
|
1014
891
|
export function callTool(
|
|
1015
892
|
name: string, args: any,
|
|
1016
893
|
opts?: { root?: string, tools?: ToolDef[] }): any {
|
|
@@ -1024,13 +901,6 @@ export function callTool(
|
|
|
1024
901
|
const a: any = { ...(args ?? {}) }
|
|
1025
902
|
const paths: Record<string, string> = {}
|
|
1026
903
|
|
|
1027
|
-
// THE FILE ALTERNATIVES (--root). A document that did not arrive as
|
|
1028
|
-
// inline text may arrive as a `<name>Path` file — served only when
|
|
1029
|
-
// the operator granted a root at startup, confined below it by the
|
|
1030
|
-
// same realpath rule the include resolver applies, and recorded in
|
|
1031
|
-
// `paths` so the engine resolves the file's own relative includes
|
|
1032
|
-
// from its directory (the CLI's rule for a named file). Inline text
|
|
1033
|
-
// wins when a caller sends both.
|
|
1034
904
|
for (const doc of tool.docs ?? []) {
|
|
1035
905
|
if ('string' === typeof a[doc]) {
|
|
1036
906
|
continue
|
package/src/mod-tool.ts
CHANGED
|
@@ -1,22 +1,5 @@
|
|
|
1
1
|
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
|
-
// MODULE TOOLING (G6 phase 3, docs/capability-review/g6-distribution.md):
|
|
4
|
-
// the LOCAL half — `aontu mod tidy`, `verify`, `vendor` and
|
|
5
|
-
// `manifest`.
|
|
6
|
-
//
|
|
7
|
-
// Evaluation never touches the network, and neither does this: `tidy`
|
|
8
|
-
// resolves versions and rewrites the lockfile from what is already in
|
|
9
|
-
// the local stores, `verify` asks whether the stores still MEAN what
|
|
10
|
-
// the lockfile pins and changes nothing, and `vendor` materialises the
|
|
11
|
-
// locked closure into the project. Fetching and publishing are the
|
|
12
|
-
// network half, and are not in this build (see the register).
|
|
13
|
-
//
|
|
14
|
-
// MINIMUM VERSION SELECTION, not a solver: each module declares the
|
|
15
|
-
// MINIMUM version of each dependency it needs, and the selected version
|
|
16
|
-
// is the maximum of those minima over the closure. Deterministic, and
|
|
17
|
-
// deterministic without backtracking — the lockfile CONFIRMS the
|
|
18
|
-
// resolution rather than determining it, which is why a tidy run can be
|
|
19
|
-
// re-run to the same bytes.
|
|
20
3
|
|
|
21
4
|
import {
|
|
22
5
|
readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync,
|
|
@@ -37,11 +20,7 @@ export type ModLock = {
|
|
|
37
20
|
mod: string
|
|
38
21
|
// The selected version.
|
|
39
22
|
v: string
|
|
40
|
-
// The canon-hash of the module as it is in the local store.
|
|
41
23
|
canon: string
|
|
42
|
-
// The registry digest, carried over from a previous lockfile. Empty
|
|
43
|
-
// when nothing has ever fetched this module: the OCI pin is the
|
|
44
|
-
// registry's word, and only a fetch can hear it.
|
|
45
24
|
oci: string
|
|
46
25
|
}
|
|
47
26
|
|
|
@@ -49,22 +28,12 @@ export type ModTidyReport = {
|
|
|
49
28
|
verdict: 'ok' | 'missing' | 'error'
|
|
50
29
|
// The resolved closure, sorted by module.
|
|
51
30
|
lock: ModLock[]
|
|
52
|
-
// Modules named by a dependency but present in no local store, sorted.
|
|
53
31
|
missing: string[]
|
|
54
|
-
// Modules present in a store but which DO NOT EVALUATE standalone,
|
|
55
|
-
// sorted. A pin is what a module MEANS, so there is nothing to pin
|
|
56
|
-
// here and the lockfile is left alone.
|
|
57
32
|
unevaluable: string[]
|
|
58
33
|
}
|
|
59
34
|
|
|
60
35
|
export type ModVerifyReport = {
|
|
61
|
-
// `ok` the lockfile covers what the project declares and every
|
|
62
|
-
// locked module still means what it pins; `mismatch` at least one
|
|
63
|
-
// does not; `unlocked` the lockfile does not cover the project's own
|
|
64
|
-
// dependencies; `missing` at least one locked module is not in any
|
|
65
|
-
// store. In that order of precedence, most specific first.
|
|
66
36
|
verdict: 'ok' | 'mismatch' | 'unlocked' | 'missing'
|
|
67
|
-
// The locked modules that verified, sorted.
|
|
68
37
|
verified: string[]
|
|
69
38
|
// What the lockfile pins against what the store now means, for each
|
|
70
39
|
// module that does not match, sorted by module.
|
|
@@ -85,19 +54,9 @@ export type ModVendorReport = {
|
|
|
85
54
|
}
|
|
86
55
|
|
|
87
56
|
|
|
88
|
-
// What the tooling needs from the engine, injected for the reason
|
|
89
|
-
// ts/src/mod.ts's ModuleEval is: evaluating a module is what the
|
|
90
|
-
// evaluator does, and the tooling is a caller of it rather than a
|
|
91
|
-
// second implementation.
|
|
92
57
|
export type ModToolEval = (src: string, path: string) =>
|
|
93
58
|
{
|
|
94
59
|
gen: any, hash: string, canon: string,
|
|
95
|
-
// DID IT STAND UP ON ITS OWN? A module that does not evaluate has
|
|
96
|
-
// no meaning to pin, and `canonHash` of the nil it collapses to is
|
|
97
|
-
// the SAME string for every such module -- so a lockfile written
|
|
98
|
-
// from one carries no information while looking exactly like one
|
|
99
|
-
// that does (use-cases/BUGS.md §31). `aontu hash` already refuses
|
|
100
|
-
// that file; `tidy` refuses it too, and this is what tells it.
|
|
101
60
|
ok: boolean,
|
|
102
61
|
}
|
|
103
62
|
|
|
@@ -134,10 +93,6 @@ function declaredDeps(file: string, options: ModToolOptions):
|
|
|
134
93
|
}
|
|
135
94
|
|
|
136
95
|
|
|
137
|
-
// Numeric-dotted version order: `1.10.0` is above `1.9.0`, which
|
|
138
|
-
// STRING order gets wrong, and that is the whole reason this is not a
|
|
139
|
-
// `<` on the text. A part that is not a number compares as text, after
|
|
140
|
-
// every number — a pre-release tag is below no version and above none.
|
|
141
96
|
export function versionCompare(a: string, b: string): number {
|
|
142
97
|
const ap = a.split('.')
|
|
143
98
|
const bp = b.split('.')
|
|
@@ -164,21 +119,6 @@ export function versionCompare(a: string, b: string): number {
|
|
|
164
119
|
}
|
|
165
120
|
|
|
166
121
|
|
|
167
|
-
// A dependency or lockfile key as a module ref this tooling may ACT
|
|
168
|
-
// on, or undefined.
|
|
169
|
-
//
|
|
170
|
-
// Two ways to be unusable, one answer. A key that is not module-shaped
|
|
171
|
-
// names nothing the resolver can find; a key that is shaped but whose
|
|
172
|
-
// path cannot legally be a directory (`..` in it, a reserved device
|
|
173
|
-
// name) must not be turned into one, which is the whole of the
|
|
174
|
-
// traversal fix on this side. Both land in the caller's `missing`
|
|
175
|
-
// bucket, because from the report's point of view they are the same
|
|
176
|
-
// fact: the lockfile names something that cannot be resolved here.
|
|
177
|
-
//
|
|
178
|
-
// A STALE LOCKFILE IS THE REASON THIS EXISTS AT ALL. `resolveModule`
|
|
179
|
-
// gates the evaluator, but `tidy`, `verify` and `vendor` read a
|
|
180
|
-
// lockfile straight off disk -- one that may have been committed
|
|
181
|
-
// before the gate existed -- so the gate has to be here too.
|
|
182
122
|
function usableRef(mod: string): ModuleRef | undefined {
|
|
183
123
|
const ref = parseModuleRef(mod)
|
|
184
124
|
if (undefined === ref || undefined !== validateModulePath(ref.path)) {
|
|
@@ -230,21 +170,12 @@ function readLock(root: string): Record<string, ModLock> {
|
|
|
230
170
|
}
|
|
231
171
|
|
|
232
172
|
|
|
233
|
-
// The lockfile TEXT: canonical Aontu, one line, keys sorted. Built as
|
|
234
|
-
// source and canonicalised by the engine rather than printed by hand,
|
|
235
|
-
// so "canonical form" means what the language means by it and cannot
|
|
236
|
-
// drift from it.
|
|
237
173
|
export function lockText(entries: ModLock[], options: ModToolOptions): string {
|
|
238
174
|
const parts = entries.map((e) =>
|
|
239
175
|
JSON.stringify(e.mod) + ':{' +
|
|
240
176
|
'"canon":' + JSON.stringify(e.canon) + ',' +
|
|
241
177
|
'"oci":' + JSON.stringify(e.oci) + ',' +
|
|
242
178
|
'"v":' + JSON.stringify(e.v) + '}')
|
|
243
|
-
// Canonicalised by the ENGINE rather than printed by hand, so
|
|
244
|
-
// "canonical form" means what the language means by it and cannot
|
|
245
|
-
// drift from it. For a map of scalars that canon is also JSON, which
|
|
246
|
-
// is what lets the resolver read a pin back without an evaluator
|
|
247
|
-
// (ts/src/mod.ts lockHash).
|
|
248
179
|
return options.eval('{"lock":{' + parts.join(',') + '}}', 'mod-lock.aon').canon
|
|
249
180
|
}
|
|
250
181
|
|
|
@@ -255,10 +186,6 @@ export function modTidy(root: string, options: ModToolOptions): ModTidyReport {
|
|
|
255
186
|
const selected: Record<string, string> = {}
|
|
256
187
|
const missing: string[] = []
|
|
257
188
|
|
|
258
|
-
// The closure, breadth-first from the project's own declarations. A
|
|
259
|
-
// module already selected at a version at least as high contributes
|
|
260
|
-
// nothing new, which is what makes this terminate without a cycle
|
|
261
|
-
// check: the selected version only ever rises.
|
|
262
189
|
let frontier = declaredDeps(pathJoin(root, 'mod.aon'), options)
|
|
263
190
|
for (; 0 < Object.keys(frontier).length;) {
|
|
264
191
|
const next: Record<string, string> = {}
|
|
@@ -307,16 +234,8 @@ export function modTidy(root: string, options: ModToolOptions): ModTidyReport {
|
|
|
307
234
|
const ref = usableRef(mod) as ModuleRef
|
|
308
235
|
const dir = storeDir(root, ref, previous[mod]?.canon ?? '', options) as string
|
|
309
236
|
const main = pathJoin(dir, mainOf(dir, options))
|
|
310
|
-
// RECOMPUTED, never carried over: the pin is what the module in
|
|
311
|
-
// this store MEANS, and a tidy that copied the old hash forward
|
|
312
|
-
// would pin what it used to mean.
|
|
313
237
|
const got = existsSync(main) ?
|
|
314
238
|
options.eval(readFileSync(main, 'utf8'), main) : undefined
|
|
315
|
-
// A NIL PIN IS WORSE THAN NO PIN. A module that does not stand up
|
|
316
|
-
// hashes to canonHash(nil) -- the same string for every broken
|
|
317
|
-
// module -- so writing it would put a plausible, uninformative
|
|
318
|
-
// pin in the lockfile and silently void the "breaks on any
|
|
319
|
-
// semantic change in the closure" contract (BUGS.md §31).
|
|
320
239
|
if (null != got && !got.ok) {
|
|
321
240
|
unevaluable.push(mod)
|
|
322
241
|
continue
|
|
@@ -367,17 +286,6 @@ function mainOf(dir: string, options: ModToolOptions): string {
|
|
|
367
286
|
}
|
|
368
287
|
|
|
369
288
|
|
|
370
|
-
// `aontu mod verify`: does every locked module still MEAN what the
|
|
371
|
-
// lockfile pins? Recompute and compare, and CHANGE NOTHING.
|
|
372
|
-
//
|
|
373
|
-
// The verb exists because `tidy` cannot answer this question. Tidy
|
|
374
|
-
// recomputes and REWRITES by design -- a pin is what a module means
|
|
375
|
-
// now -- so tampering with a vendored module and running tidy makes
|
|
376
|
-
// the lockfile agree with the tampering, `verdict: ok`, and the next
|
|
377
|
-
// evaluation passes. That is correct for the job tidy does and useless
|
|
378
|
-
// as a gate, which left a CI job that tidies before evaluating with no
|
|
379
|
-
// integrity protection at all (use-cases/BUGS.md §32). Verification is
|
|
380
|
-
// a question; answering it must not be an edit.
|
|
381
289
|
export function modVerify(root: string, options: ModToolOptions):
|
|
382
290
|
ModVerifyReport {
|
|
383
291
|
const locked = readLock(root)
|
|
@@ -385,17 +293,6 @@ export function modVerify(root: string, options: ModToolOptions):
|
|
|
385
293
|
const mismatched: { mod: string, want: string, got: string }[] = []
|
|
386
294
|
const missing: string[] = []
|
|
387
295
|
|
|
388
|
-
// NOTHING TO CHECK IS NOT A PASS. A project with no lockfile at all
|
|
389
|
-
// -- or one whose lockfile predates a dependency someone added --
|
|
390
|
-
// would otherwise verify clean, because the loop below walks what is
|
|
391
|
-
// LOCKED and there is nothing locked to walk. That is the same shape
|
|
392
|
-
// as the defect this verb exists to close: absence reading as
|
|
393
|
-
// agreement. Every dependency the project itself declares must be in
|
|
394
|
-
// the lockfile before the pins mean anything, and the repair is a
|
|
395
|
-
// tidy rather than a fetch. Transitive dependencies need no separate
|
|
396
|
-
// check: a locked module's own imports are resolved when its pin is
|
|
397
|
-
// recomputed, so one that is unreachable makes its DEPENDANT fail to
|
|
398
|
-
// evaluate and lands in `mismatched` below.
|
|
399
296
|
const declared = declaredDeps(pathJoin(root, 'mod.aon'), options)
|
|
400
297
|
const unlocked = Object.keys(declared)
|
|
401
298
|
.filter((mod) => null == locked[mod]).sort()
|
|
@@ -417,10 +314,6 @@ export function modVerify(root: string, options: ModToolOptions):
|
|
|
417
314
|
continue
|
|
418
315
|
}
|
|
419
316
|
|
|
420
|
-
// A module that no longer stands up is not a match: it has no
|
|
421
|
-
// meaning to compare, and reporting `got: <hash of nil>` would
|
|
422
|
-
// print the same string for every broken module. The empty `got`
|
|
423
|
-
// says the store holds something that does not evaluate.
|
|
424
317
|
const got = options.eval(readFileSync(main, 'utf8'), main)
|
|
425
318
|
const want = locked[mod].canon
|
|
426
319
|
if (got.ok && want === got.hash) {
|
|
@@ -464,17 +357,6 @@ export function modVendor(root: string, options: ModToolOptions):
|
|
|
464
357
|
continue
|
|
465
358
|
}
|
|
466
359
|
|
|
467
|
-
// WHY THERE IS NO CONTAINMENT CHECK ON `to`, at the one write site
|
|
468
|
-
// that copied a tree outside the project: `usableRef` above is the
|
|
469
|
-
// gate, and after it a store path CANNOT escape. Every element is
|
|
470
|
-
// non-empty and neither begins nor ends with `.`, so none is `.`
|
|
471
|
-
// or `..`; MODULE_RE's element class admits no `/`, no `\` and no
|
|
472
|
-
// leading slash, so no element can re-root the join. A second
|
|
473
|
-
// lexical check here would be unreachable code, which ADR-002 asks
|
|
474
|
-
// to be deleted rather than excluded -- so the invariant is pinned
|
|
475
|
-
// by a test that drives the escape through this verb instead.
|
|
476
|
-
// ANY NEW CALLER of moduleDir must go through usableRef too;
|
|
477
|
-
// `mod get` is the next one.
|
|
478
360
|
const to = moduleDir(vendorRoot, ref)
|
|
479
361
|
if (from !== to) {
|
|
480
362
|
copyTree(from, to)
|
|
@@ -508,33 +390,10 @@ function copyTree(from: string, to: string): void {
|
|
|
508
390
|
}
|
|
509
391
|
|
|
510
392
|
|
|
511
|
-
// THE PUBLISH BOUNDARY (G6 phase 4,
|
|
512
|
-
// docs/capability-review/g6-distribution.md). A module is an OCI
|
|
513
|
-
// artifact, and what a publish PUSHES is a manifest: a config media
|
|
514
|
-
// type, one layer holding the module's source tree, and annotations
|
|
515
|
-
// carrying the module path, its version and its canon-hash.
|
|
516
|
-
//
|
|
517
|
-
// The push needs a registry, which this build does not have. Everything
|
|
518
|
-
// the push would ASSERT is local, and that is what `aontu mod manifest`
|
|
519
|
-
// answers: the exact artifact description, computed the way the
|
|
520
|
-
// registry would be told it, plus the gate that decides whether it may
|
|
521
|
-
// be minted at all.
|
|
522
|
-
//
|
|
523
|
-
// WHY THE ANNOTATION MATTERS MORE THAN THE BYTES. "Has the truth
|
|
524
|
-
// changed?" is one annotation read and a string compare -- no download,
|
|
525
|
-
// no parse -- because the canon-hash pins MEANING rather than text. A
|
|
526
|
-
// consumer holding `aon1-oQs6…` can ask a registry index whether the
|
|
527
|
-
// module still hashes to it, and a reformat, a comment or a file split
|
|
528
|
-
// will not move it.
|
|
529
|
-
|
|
530
393
|
// The config media type the design fixes: an Aontu module is not an
|
|
531
394
|
// image, and the type is what tells a registry so.
|
|
532
395
|
export const MODULE_CONFIG_MEDIA_TYPE = 'application/vnd.aontu.module.v1+json'
|
|
533
396
|
|
|
534
|
-
// The canon-hash annotation. OCI asks a custom key to be the reverse
|
|
535
|
-
// DNS of a domain its author controls, and the project's own home is
|
|
536
|
-
// the only domain it has -- inventing an `aontu.dev` would be a claim
|
|
537
|
-
// it cannot back. The two facts OCI already has keys for use those.
|
|
538
397
|
export const MODULE_ANNOTATION_CANON = 'com.github.rjrodger.aontu.canon'
|
|
539
398
|
export const MODULE_ANNOTATION_MAJOR = 'com.github.rjrodger.aontu.major'
|
|
540
399
|
|
|
@@ -549,9 +408,6 @@ export type ModManifestReport = {
|
|
|
549
408
|
// The canon-hash of the module's entry file, evaluated standalone.
|
|
550
409
|
canon: string
|
|
551
410
|
config: string
|
|
552
|
-
// The layer's contents: every file of the source tree, relative,
|
|
553
|
-
// forward-slashed and sorted, so two implementations on two platforms
|
|
554
|
-
// describe the same layer.
|
|
555
411
|
files: string[]
|
|
556
412
|
annotations: Record<string, string>
|
|
557
413
|
// What the module does not declare, sorted. A manifest cannot be
|
|
@@ -583,20 +439,12 @@ function modSelf(dir: string, options: ModToolOptions): ModSelf {
|
|
|
583
439
|
}
|
|
584
440
|
|
|
585
441
|
|
|
586
|
-
// The leading numeric component of a version, which is the major an
|
|
587
|
-
// import spells. Empty when the version does not start with one: a
|
|
588
|
-
// version whose major cannot be read cannot be published under a
|
|
589
|
-
// module path, because the path is where the major lives.
|
|
590
442
|
function majorOf(version: string): string {
|
|
591
443
|
const m = /^(\d+)/.exec(version)
|
|
592
444
|
return null == m ? '' : m[1]
|
|
593
445
|
}
|
|
594
446
|
|
|
595
447
|
|
|
596
|
-
// Every file of a module's source tree, relative and forward-slashed.
|
|
597
|
-
// `aontu_meta/vendor/` is excluded: a published module carries its own
|
|
598
|
-
// sources, not a copy of everyone else's -- a consumer resolves the
|
|
599
|
-
// closure itself, and a nested vendor tree would publish the world.
|
|
600
448
|
function layerFiles(dir: string, prefix = ''): string[] {
|
|
601
449
|
const out: string[] = []
|
|
602
450
|
for (const name of readdirSync(dir).sort()) {
|
|
@@ -688,16 +536,10 @@ export function modManifest(
|
|
|
688
536
|
return report
|
|
689
537
|
}
|
|
690
538
|
|
|
691
|
-
// A MAJOR BUMP IS WHERE BREAKING IS ALLOWED. The major lives in the
|
|
692
|
-
// module path, so a consumer of `@1` never sees `@2` unless it asks:
|
|
693
|
-
// checking compatibility across majors would forbid the one change
|
|
694
|
-
// the version scheme exists to express.
|
|
695
539
|
if (majorOf(prior.version) !== major) {
|
|
696
540
|
return report
|
|
697
541
|
}
|
|
698
542
|
|
|
699
|
-
// Backward compatibility: the NEW version is the general side, so
|
|
700
|
-
// every instance the old one admitted must still be admitted.
|
|
701
543
|
const gate = subsume(newSrc, readFileSync(priorMain, 'utf8'), {
|
|
702
544
|
generalUrl: main,
|
|
703
545
|
specificUrl: priorMain,
|