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/trim.ts
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
2
|
import { includeOpts } from './utility'
|
|
3
3
|
|
|
4
|
-
// The trim reporter (G3 phase 6,
|
|
5
|
-
// docs/capability-review/g3-subsumption-evolution.md): report REDUNDANT
|
|
6
|
-
// map entries — entries whose removal leaves the evaluated result
|
|
7
|
-
// unchanged, the spread-implied case included — as paths. Report-only,
|
|
8
|
-
// deliberately: canon discards comments and layout, so REWRITING the
|
|
9
|
-
// file needs G7's format-preserving patch surface; trim ships as a
|
|
10
|
-
// reporter here and becomes an editor there.
|
|
11
|
-
//
|
|
12
|
-
// The test is EVALUATE-AND-COMPARE: for each candidate entry, re-parse
|
|
13
|
-
// the source, delete the entry from the parsed tree, evaluate, and
|
|
14
|
-
// compare canons. This subsumes the design's spread case — an entry a
|
|
15
|
-
// spread template re-supplies evaluates to the same canon without its
|
|
16
|
-
// explicit spelling — and is honest about everything the fixpoint can
|
|
17
|
-
// see (references, templates, duplicate-key merges), where a purely
|
|
18
|
-
// structural test would guess. A removal that ERRORS is not redundant:
|
|
19
|
-
// the entry is load-bearing.
|
|
20
|
-
//
|
|
21
|
-
// Parsed trees are single-use (docs/reference-api.md), so every probe
|
|
22
|
-
// is its own parse: one evaluation per candidate plus one for the
|
|
23
|
-
// baseline. A reporter can afford that; an editor loop belongs to G7.
|
|
24
4
|
|
|
25
5
|
import { Aontu } from './aontu'
|
|
26
6
|
import { failureFinding } from './vet'
|
|
@@ -34,12 +14,6 @@ export type TrimReport = {
|
|
|
34
14
|
verdict: TrimVerdict
|
|
35
15
|
redundant: string[]
|
|
36
16
|
|
|
37
|
-
// WHY the run could not be made, in the same finding shape vet
|
|
38
|
-
// reports in (the review's finding F). An `error` verdict used to
|
|
39
|
-
// arrive with an empty report -- something is wrong with the
|
|
40
|
-
// document, and nothing about what -- which is the one answer a
|
|
41
|
-
// repair loop cannot act on. Present ONLY on an `error` verdict, so
|
|
42
|
-
// a clean report stays exactly the two fields it always was.
|
|
43
17
|
errors?: VetFinding[]
|
|
44
18
|
}
|
|
45
19
|
|
|
@@ -47,14 +21,8 @@ export type TrimOptions = {
|
|
|
47
21
|
// Where the document CAME FROM, so a relative `@"file"` load inside
|
|
48
22
|
// it resolves from its own directory (vet's schemaPath precedent).
|
|
49
23
|
path?: string
|
|
50
|
-
// The include capability this document evaluates under (G5,
|
|
51
|
-
// docs/trust.md). vet's precedent: the verb passes the profile the
|
|
52
|
-
// caller asked for, and an absent option means today's default.
|
|
53
24
|
trust?: TrustOptions
|
|
54
25
|
|
|
55
|
-
// Extensions additionally read as text (the CLI's `--text-ext`).
|
|
56
|
-
// Rides beside `trust` because it is the other half of what an
|
|
57
|
-
// include may read.
|
|
58
26
|
textExt?: string[]
|
|
59
27
|
}
|
|
60
28
|
|
|
@@ -64,14 +32,6 @@ function pathText(path: string[]): string {
|
|
|
64
32
|
}
|
|
65
33
|
|
|
66
34
|
|
|
67
|
-
// Every (map, key) pair in a PARSED tree, parent-first. Candidates come
|
|
68
|
-
// from the parse rather than the evaluation: an entry the fixpoint
|
|
69
|
-
// erases or rewrites still has to be addressable for deletion. The
|
|
70
|
-
// non-Val guard is for a bag's raw peg entries, which degenerate
|
|
71
|
-
// parses can leave behind. Exported (with deleteAt and evalCanon) for
|
|
72
|
-
// the direct unit tests (ADR-002, ts/test/coverage3.test.ts): the
|
|
73
|
-
// defensive arms are unreachable through trimCheck, whose candidates
|
|
74
|
-
// come from an identical parse.
|
|
75
35
|
export function candidates(v: any, path: string[], out: string[][]): void {
|
|
76
36
|
if (null == v || true !== v.isVal) {
|
|
77
37
|
return
|
|
@@ -118,21 +78,12 @@ export function deleteAt(root: any, path: string[]): boolean {
|
|
|
118
78
|
}
|
|
119
79
|
|
|
120
80
|
|
|
121
|
-
// One evaluation: parse (deleting the entry at delPath, when given),
|
|
122
|
-
// unify under collect, and answer the canon — or undefined when the
|
|
123
|
-
// source does not stand up, which for the baseline is the caller's
|
|
124
|
-
// error verdict and for a probe means "load-bearing".
|
|
125
81
|
export function evalCanon(
|
|
126
82
|
src: string, opts: TrimOptions, delPath?: string[],
|
|
127
83
|
sink?: { ctx?: any, failed?: any }): string | undefined {
|
|
128
84
|
const aontu = new Aontu(includeOpts(opts))
|
|
129
85
|
const ctx = aontu.ctx({ collect: true })
|
|
130
86
|
const parseOpts = null == opts.path ? undefined : { path: opts.path }
|
|
131
|
-
// WHY the run failed, for the one caller that reports it. The
|
|
132
|
-
// BASELINE run passes a sink and a probe does not: a probe's failure
|
|
133
|
-
// means "load-bearing", which is an answer rather than a fault, and
|
|
134
|
-
// reporting it would bury the one real finding under one entry's
|
|
135
|
-
// worth of noise per candidate.
|
|
136
87
|
const fail = (failed?: any): undefined => {
|
|
137
88
|
if (null != sink) {
|
|
138
89
|
sink.ctx = ctx
|
|
@@ -158,10 +109,6 @@ export function evalCanon(
|
|
|
158
109
|
}
|
|
159
110
|
|
|
160
111
|
|
|
161
|
-
// The whole reporter: the baseline canon, then one probe per candidate
|
|
162
|
-
// entry, parent-first — and a child of a redundant parent is SKIPPED,
|
|
163
|
-
// because "remove the whole entry" already covers it and reporting
|
|
164
|
-
// both would tell the author to delete the same text twice.
|
|
165
112
|
export function trimCheck(src: string, opts?: TrimOptions): TrimReport {
|
|
166
113
|
const options = opts ?? {}
|
|
167
114
|
|
package/src/type.ts
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Fs from 'node:fs'
|
|
4
4
|
|
|
5
|
-
// TODO: refactor these out
|
|
6
5
|
|
|
7
6
|
import { Resolver } from '@tabnas/multisource'
|
|
8
7
|
|
|
@@ -13,35 +12,12 @@ import type { ValMark, ValSpec } from './val/Val'
|
|
|
13
12
|
type FST = typeof Fs
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
// The trust profile (G5, docs/trust.md): what an evaluation may read,
|
|
18
|
-
// and how much work it may do. Trust is a property of the EVALUATION,
|
|
19
|
-
// not the document -- a .aon file cannot request more capability -- and
|
|
20
|
-
// the profile adds zero language syntax.
|
|
21
|
-
//
|
|
22
|
-
// The include capability:
|
|
23
|
-
// 'none' @"..." is always denied
|
|
24
|
-
// { mem: {...} } a virtual file set only; nothing else resolves
|
|
25
|
-
// { root: '/dir' } real files, realpath-confined below root;
|
|
26
|
-
// no package resolution
|
|
27
|
-
// 'system' the full memory -> file -> package chain
|
|
28
|
-
// (today's default, and the unconfined posture)
|
|
29
|
-
//
|
|
30
|
-
// Budgets are integer counts of engine events -- never wall-clock, which
|
|
31
|
-
// would make identical inputs fail differently across machines (the
|
|
32
|
-
// exact nondeterminism docs/trust.md forbids). The defaults are the
|
|
33
|
-
// shared spec-visible constants pinned by test/spec/budget.tsv.
|
|
34
15
|
type TrustInclude =
|
|
35
16
|
| 'none'
|
|
36
17
|
| 'system'
|
|
37
18
|
| { mem: Record<string, string> }
|
|
38
19
|
| { root: string }
|
|
39
20
|
|
|
40
|
-
// Only the budgets BOTH ports can honour are profile surface: passes
|
|
41
|
-
// and depth. The per-pair revisit bound (999) stays a TS-internal
|
|
42
|
-
// constant — the Go dispatcher has no revisit counter (it is
|
|
43
|
-
// depth-guarded), and a knob one port cannot implement would break the
|
|
44
|
-
// parity contract (ADR-001) by construction.
|
|
45
21
|
type TrustBudget = {
|
|
46
22
|
passes?: number // fixpoint passes (default 9)
|
|
47
23
|
depth?: number // structural recursion depth (default 1000)
|
|
@@ -53,21 +29,14 @@ type TrustOptions = {
|
|
|
53
29
|
}
|
|
54
30
|
|
|
55
31
|
type AontuOptions = {
|
|
56
|
-
src?: string
|
|
32
|
+
src?: string
|
|
57
33
|
print?: number // Print debug verbosity
|
|
58
|
-
resolver?: Resolver
|
|
34
|
+
resolver?: Resolver
|
|
59
35
|
base?: string // Base path for resolver
|
|
60
36
|
path?: string // Path of entry file
|
|
61
37
|
debug?: boolean
|
|
62
38
|
trace?: boolean
|
|
63
39
|
fs?: FST
|
|
64
|
-
// errfs READS FOR THE ERROR RENDERER ONLY, never for resolution.
|
|
65
|
-
// A frame excerpts the file its arrow names, which means reading
|
|
66
|
-
// that file -- but handing the same reader to `fs` would change
|
|
67
|
-
// which leg the include RESOLVER takes (its file leg reads through
|
|
68
|
-
// the host filesystem when one is given, so a package hit can
|
|
69
|
-
// become a file hit), and a diagnostic must not move the boundary
|
|
70
|
-
// it is describing.
|
|
71
40
|
errfs?: FST
|
|
72
41
|
deps?: any
|
|
73
42
|
log?: any
|
|
@@ -77,19 +46,8 @@ type AontuOptions = {
|
|
|
77
46
|
explain?: any[]
|
|
78
47
|
trust?: TrustOptions // Trust profile (G5, docs/trust.md)
|
|
79
48
|
|
|
80
|
-
// EXTENSIONS ADDITIONALLY READ AS TEXT, without their dots. `.txt`
|
|
81
|
-
// is read as text with no option at all; this widens that set for a
|
|
82
|
-
// host that keeps its prose in `.md`, its queries in `.sql`, or its
|
|
83
|
-
// templates under some name only it knows. The file's bytes become
|
|
84
|
-
// one string scalar -- no parser is chosen for it, which is what
|
|
85
|
-
// makes widening the set safe to offer.
|
|
86
49
|
textExt?: string[]
|
|
87
50
|
|
|
88
|
-
// The staged-flip warning window (G5 phase 6, CLI only): under the
|
|
89
|
-
// default 'system' capability the CLI supplies these, and the
|
|
90
|
-
// resolver calls trustWarn for every resolution that escapes
|
|
91
|
-
// trustWarnRoot or goes through package resolution — naming the flag
|
|
92
|
-
// a future default will require. Not a stable embedding API.
|
|
93
51
|
trustWarn?: (kind: 'escape' | 'pkg', path: string) => void
|
|
94
52
|
trustWarnRoot?: string
|
|
95
53
|
}
|
|
@@ -108,7 +66,6 @@ type ValMap = { [key: string]: Val }
|
|
|
108
66
|
type ValList = Val[]
|
|
109
67
|
|
|
110
68
|
|
|
111
|
-
|
|
112
69
|
type ErrContext = {
|
|
113
70
|
src?: string,
|
|
114
71
|
fs?: FST,
|
package/src/unify.ts
CHANGED
|
@@ -29,36 +29,6 @@ import {
|
|
|
29
29
|
} from './val/top'
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
// The evaluation budgets live on the context (ctx.budget: passes,
|
|
33
|
-
// revisits, depth), defaulted there to the shared spec-visible
|
|
34
|
-
// constants test/spec/budget.tsv pins in both ports (9 / 999 / 1000)
|
|
35
|
-
// and configurable through the trust profile (G5, docs/trust.md) —
|
|
36
|
-
// deterministically: a budget is an integer count of engine events,
|
|
37
|
-
// never wall-clock.
|
|
38
|
-
//
|
|
39
|
-
// Why the revisit default is 999: how many times one (Val, path) pair
|
|
40
|
-
// may be re-unified within a single fixpoint pass before the evaluator
|
|
41
|
-
// calls it non-convergence (`unify_cycle`). The old false positive here
|
|
42
|
-
// -- a legal model with many sibling conjunct terms at one path, each
|
|
43
|
-
// re-running the TOP self-unify -- is fixed by the per-pass memo below
|
|
44
|
-
// (_tcc/_tpi); test/spec/budget.tsv drives 1200 sibling terms through
|
|
45
|
-
// both engines as the regression guard.
|
|
46
|
-
//
|
|
47
|
-
// Why the depth default is 1000: the whole shared suite peaks at 603
|
|
48
|
-
// (the deliberately extreme 1200-sibling-term fixture; ordinary
|
|
49
|
-
// documents are two orders below), and V8 exhausts its call stack
|
|
50
|
-
// somewhere past depth ~1500 in this evaluator. 1000 sits above every
|
|
51
|
-
// real document and below the host limit, so the budget -- not the
|
|
52
|
-
// host -- decides the verdict.
|
|
53
|
-
|
|
54
|
-
// Charge a DIRECT `Val.unify` recursion to the same depth budget that
|
|
55
|
-
// `unite` enforces. Function and operator arguments evaluate through
|
|
56
|
-
// `arg.unify(top(), ...)` rather than through the dispatcher, so without
|
|
57
|
-
// this the counter stays flat while the JavaScript stack keeps growing:
|
|
58
|
-
// a 1500-deep `upper(upper(...))` resolved in TypeScript while Go — which
|
|
59
|
-
// routes its arguments through the counted dispatcher — reported
|
|
60
|
-
// `unify_cycle`. Returns the budget nil instead of running when the
|
|
61
|
-
// budget is spent.
|
|
62
32
|
const withDepth = (
|
|
63
33
|
ctx: AontuContext, a: any, b: any, run: () => any
|
|
64
34
|
): any => {
|
|
@@ -78,27 +48,10 @@ const withDepth = (
|
|
|
78
48
|
// Vals should only have to unify downwards (in .unify) over Vals they understand.
|
|
79
49
|
// and for complex Vals, TOP, which means self unify if not yet done
|
|
80
50
|
const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
81
|
-
// Fast paths that don't recurse and so don't need cycle-detection:
|
|
82
|
-
// short-circuit before the saw-key build and seen-map lookup (which
|
|
83
|
-
// together cost ~2.5µs per call). Only return early when the result
|
|
84
|
-
// is already `done` — a non-done result would need the trailing
|
|
85
|
-
// top() unify below.
|
|
86
|
-
//
|
|
87
|
-
// A6a: same ref, already done
|
|
88
|
-
// A6b: different ref but same id + both done
|
|
89
|
-
// P1: exact-equal scalars that are already done (14% of calls
|
|
90
|
-
// in foo-sdk, ~100% with a.done=true)
|
|
91
51
|
if (a !== undefined && a !== null) {
|
|
92
52
|
if (a === b) {
|
|
93
53
|
if (a.done) return a
|
|
94
54
|
}
|
|
95
|
-
// ... and NOT on an instrumented run (G7 provenance). Both arms
|
|
96
|
-
// below answer with one operand and never reach the recorder at
|
|
97
|
-
// the tail, so an equal pair — two positions of one entity that
|
|
98
|
-
// agree, a clone meeting its source — contributed silently and
|
|
99
|
-
// `why` named one site where the Go port, whose recorder wraps the
|
|
100
|
-
// whole dispatcher, named both. Instrumented runs pay the slow
|
|
101
|
-
// path knowingly; uninstrumented ones pay one undefined check.
|
|
102
55
|
else if (b !== undefined && b !== null && undefined === ctx.prov) {
|
|
103
56
|
if (a.done && b.done) {
|
|
104
57
|
if (a.id === b.id) {
|
|
@@ -113,19 +66,7 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
113
66
|
&& !a.isMap && !a.isList
|
|
114
67
|
&& !a.isConjunct && !a.isDisjunct
|
|
115
68
|
&& !a.isRef && !a.isPref && !a.isFunc && !a.isExpect
|
|
116
|
-
// NOT two TOPs: every top has the same (absent) peg, so
|
|
117
|
-
// this path would treat any two as the same value and
|
|
118
|
-
// return one of them whole — dropping a rider the other
|
|
119
|
-
// carries. The slow path answers the same thing for two
|
|
120
|
-
// plain tops, so nothing is lost by declining the shortcut.
|
|
121
69
|
&& !a.isTop && !b.isTop
|
|
122
|
-
// NOT two rel residuals (RELATIONS P1) for the same
|
|
123
|
-
// reason: a settled rel is DONE with an absent peg, so
|
|
124
|
-
// any two matched here — dropping one side's type and
|
|
125
|
-
// held constraints. RelVal.unify merges them instead.
|
|
126
|
-
// NOT two graph atoms (P2) either: acyclic() and
|
|
127
|
-
// inverse(x) share a constructor and an absent peg
|
|
128
|
-
// without being the same declaration.
|
|
129
70
|
&& !a.isRel && !a.isGraphAtom && !a.isRecurse) {
|
|
130
71
|
// The deprecation record survives the fast path too (G3):
|
|
131
72
|
// `deprecate(5) & 5` short-circuits here.
|
|
@@ -138,6 +79,17 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
138
79
|
}
|
|
139
80
|
}
|
|
140
81
|
|
|
82
|
+
// ABSENCE IS THE UNIT OF THE MEET (ADR-034). The dispatch below is
|
|
83
|
+
// the LEFT operand's, so `&` commutes only if it is answered here.
|
|
84
|
+
if (null != a && null != b) {
|
|
85
|
+
if (true === a.isAbsent) {
|
|
86
|
+
return a.unify(b, ctx)
|
|
87
|
+
}
|
|
88
|
+
if (true === b.isAbsent) {
|
|
89
|
+
return b.unify(a, ctx)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
141
93
|
const te = ctx.explain && explainOpen(ctx, ctx.explain, 'unite', a, b)
|
|
142
94
|
|
|
143
95
|
let out = a
|
|
@@ -155,16 +107,9 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
155
107
|
// See for example PrefVal peg.id equality inspection.
|
|
156
108
|
const sawCount = ctx.seen[saw] ?? 0
|
|
157
109
|
if (ctx.budget.depth <= ctx._depth.n) {
|
|
158
|
-
// Structural recursion budget. Without it, deep nesting exhausts the
|
|
159
|
-
// V8 call stack and the catch-all below reports a RangeError as
|
|
160
|
-
// `internal` — a verdict that depends on the host's stack size
|
|
161
|
-
// rather than on the document, which is exactly what the
|
|
162
|
-
// determinism clause forbids (docs/trust.md). Tripping here instead
|
|
163
|
-
// makes it a stated budget error, like the pass budget.
|
|
164
110
|
out = makeNilErr(ctx, 'unify_cycle', a, b)
|
|
165
111
|
}
|
|
166
112
|
else if (ctx.budget.revisits < sawCount) {
|
|
167
|
-
// console.log('SAW', sawCount, saw, a?.id, a?.canon, b?.id, b?.canon, ctx.cc)
|
|
168
113
|
out = makeNilErr(ctx, 'unify_cycle', a, b)
|
|
169
114
|
}
|
|
170
115
|
else {
|
|
@@ -174,18 +119,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
174
119
|
try {
|
|
175
120
|
let unified = false
|
|
176
121
|
|
|
177
|
-
// Dispatch ladder. Structure note:
|
|
178
|
-
// - `a == null` is degenerate (shouldn't happen in practice:
|
|
179
|
-
// the top-level call seeds with a real Val). Kept for safety.
|
|
180
|
-
// - TOP is the unit element: unifying with it returns the
|
|
181
|
-
// other side. Handle both sides.
|
|
182
|
-
// - Otherwise route by Val type. Complex Vals (Conjunct,
|
|
183
|
-
// Disjunct, Ref, Pref, Func, Expect) have their own unify
|
|
184
|
-
// that knows how to absorb the peer; prefer `a.unify` when
|
|
185
|
-
// `a` is complex, else `b.unify` when `b` is complex. If
|
|
186
|
-
// neither is complex and it's not a plain-scalar match, fall
|
|
187
|
-
// through to the generic `a.unify` (concrete Val classes
|
|
188
|
-
// each handle their own peer case).
|
|
189
122
|
if (a == null) {
|
|
190
123
|
out = b
|
|
191
124
|
why = 'b'
|
|
@@ -219,18 +152,9 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
219
152
|
|| b.isVar
|
|
220
153
|
|| b.isFunc
|
|
221
154
|
|| b.isExpect
|
|
222
|
-
// The refer residual (G4 phase 2) DRIVES, like the other
|
|
223
|
-
// residuals here: its peer is a plain string, which knows
|
|
224
|
-
// nothing about entity addresses, so letting the string drive
|
|
225
|
-
// dropped the address and left the constraint standing.
|
|
226
155
|
|| b.isRefer
|
|
227
|
-
// An
|
|
228
|
-
|
|
229
|
-
// unify with `_ + 2` sees an operator rather than a hole and
|
|
230
|
-
// refuses it on kind. Narrow to placeheld operators on
|
|
231
|
-
// purpose -- every other operator meets its peer the way it
|
|
232
|
-
// always has, through the conjunct fold that drives it.
|
|
233
|
-
|| (b.isOp && hasPlace(b))
|
|
156
|
+
// An op DRIVES while an operand has not decided (ADR-037).
|
|
157
|
+
|| (b.isOp && (hasPlace(b) || b.holdsStaged))
|
|
234
158
|
// A graph atom DRIVES (RELATIONS P2): its peer is the value
|
|
235
159
|
// it rides beside -- a container, a rel, a scalar -- and none
|
|
236
160
|
// of them know the atom; the atom knows to residuate.
|
|
@@ -243,10 +167,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
243
167
|
unified = true
|
|
244
168
|
why = 'bv'
|
|
245
169
|
}
|
|
246
|
-
// Exactly equal scalars (not caught by early fast-path — e.g.
|
|
247
|
-
// because a or b isn't .done yet). Rel residuals are excluded
|
|
248
|
-
// exactly as in the fast path: their pegs are equally absent
|
|
249
|
-
// without the values being the same relation.
|
|
250
170
|
else if (a.constructor === b.constructor && a.peg === b.peg
|
|
251
171
|
&& !a.isRel && !a.isGraphAtom && !a.isRecurse) {
|
|
252
172
|
out = update(a, b)
|
|
@@ -263,18 +183,7 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
263
183
|
why += 'N'
|
|
264
184
|
}
|
|
265
185
|
|
|
266
|
-
// Any non-done top-level result self-unifies with TOP to ensure
|
|
267
|
-
// its children finish converging. Skipped when `unified` is true
|
|
268
|
-
// because the branch that set `out = X.unify(Y, ctx)` already
|
|
269
|
-
// ran that Val's own unify logic.
|
|
270
186
|
if (!out.done && !unified) {
|
|
271
|
-
// Once per pass per (Val, path): within a single fixpoint pass
|
|
272
|
-
// nothing external to the subtree changes, so repeating the TOP
|
|
273
|
-
// self-unify — which conjunct folds otherwise trigger once per
|
|
274
|
-
// fold term — is pure re-work, and on large models (hundreds of
|
|
275
|
-
// sibling terms) the repeats trip the MAXCYCLE guard as a false
|
|
276
|
-
// positive. The path is part of the key: a shared Val can
|
|
277
|
-
// resolve path-dependent content differently per location.
|
|
278
187
|
if (undefined !== ctx.cc
|
|
279
188
|
&& (out as any)._tcc === ctx.cc && (out as any)._tpi === ctx.pathidx) {
|
|
280
189
|
why += 't'
|
|
@@ -290,12 +199,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
290
199
|
}
|
|
291
200
|
}
|
|
292
201
|
catch (err: any) {
|
|
293
|
-
// This catch-all converts an unexpected exception into an 'internal'
|
|
294
|
-
// Nil so one bad node doesn't crash a whole unify. To avoid fully
|
|
295
|
-
// masking regressions, preserve the original error message (and a
|
|
296
|
-
// RangeError flag — i.e. stack overflow from runaway recursion) on
|
|
297
|
-
// the Nil's details so it surfaces in the formatted error rather
|
|
298
|
-
// than vanishing. See err.ts (descErr) for how details render.
|
|
299
202
|
out = makeNilErr(ctx, 'internal', a, b, undefined, {
|
|
300
203
|
error: String(err?.message ?? err),
|
|
301
204
|
...(err instanceof RangeError ? { overflow: true } : {}),
|
|
@@ -308,20 +211,10 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
308
211
|
|
|
309
212
|
ctx.explain && explainClose(te, out)
|
|
310
213
|
|
|
311
|
-
// The provenance record (G7 phase 3), at the one place every meet
|
|
312
|
-
// passes through — the same reason the deprecation rider below lives
|
|
313
|
-
// here. Off by default: an uninstrumented run pays this one property
|
|
314
|
-
// load, and an instrumented one pays site materialisation knowingly.
|
|
315
214
|
if (undefined !== ctx.prov) {
|
|
316
215
|
ctx.prov.record(ctx.path, a, b, out)
|
|
317
216
|
}
|
|
318
217
|
|
|
319
|
-
// The deprecation record survives EVERY meet (G3 phase 4): the
|
|
320
|
-
// boolean marks have their own sweeps (ConjunctVal, the bag walks),
|
|
321
|
-
// but a record lost in one meet shape is a use the tooling never
|
|
322
|
-
// warns about, so it rides here, at the one place all meets pass
|
|
323
|
-
// through. First record wins; TOP and nil stay clean (TOP is the
|
|
324
|
-
// unit, and an error needs no deprecation).
|
|
325
218
|
if (null != out && true === (out as any).isVal &&
|
|
326
219
|
!out.isTop && !out.isNil && null == out.deprecation) {
|
|
327
220
|
const dep = (null != a ? a.deprecation : undefined) ??
|
|
@@ -331,12 +224,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
331
224
|
}
|
|
332
225
|
}
|
|
333
226
|
|
|
334
|
-
// THE RENDER RIDERS SURVIVE EVERY MEET (RENDER.0.md P7), and here
|
|
335
|
-
// for the deprecation record's reason: a reference resolves by
|
|
336
|
-
// MEETING its target with the peer at the referring position, and an
|
|
337
|
-
// emitted piece meets the vocabulary's alternative before the fold
|
|
338
|
-
// ever sees it, so a record lost in one meet shape is a line the
|
|
339
|
-
// trace cannot name. Both are absent unless the run is instrumented.
|
|
340
227
|
if (undefined !== ctx.reads &&
|
|
341
228
|
null != out && true === (out as any).isVal && !out.isTop && !out.isNil) {
|
|
342
229
|
riders(a, b, out)
|
|
@@ -346,18 +233,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
|
|
|
346
233
|
}
|
|
347
234
|
|
|
348
235
|
|
|
349
|
-
// The two P7 riders, carried from the operands to the result: the read
|
|
350
|
-
// address a value was found at, and the dispatch that emitted it.
|
|
351
|
-
// First record wins, as the deprecation record's does. Reached only
|
|
352
|
-
// from an instrumented run (AontuContext.reads), so an ordinary meet
|
|
353
|
-
// pays the one property load its call site makes and nothing else.
|
|
354
|
-
//
|
|
355
|
-
// AN OPERAND MAY BE ABSENT and reading through it is not a decision:
|
|
356
|
-
// `unite` is called with no peer wherever a bag holds a key its peer
|
|
357
|
-
// does not, and `Object(undefined)` is an empty object, so both riders
|
|
358
|
-
// are read the same way whether the operand is there or not. Written
|
|
359
|
-
// with a test first, that test had an arm no instrumented document
|
|
360
|
-
// reached -- true of the reading, not of the engine.
|
|
361
236
|
function riders(a: any, b: any, to: any): void {
|
|
362
237
|
const av = Object(a)
|
|
363
238
|
const bv = Object(b)
|
|
@@ -377,7 +252,6 @@ function riders(a: any, b: any, to: any): void {
|
|
|
377
252
|
|
|
378
253
|
|
|
379
254
|
function update(x: Val, _y: Val) {
|
|
380
|
-
// TODO: update x with y.site
|
|
381
255
|
return x
|
|
382
256
|
}
|
|
383
257
|
|
|
@@ -406,26 +280,6 @@ function residuePaths(v: Val, max: number): string[] {
|
|
|
406
280
|
}
|
|
407
281
|
|
|
408
282
|
|
|
409
|
-
// THE TYPE FLOW, APPLIED (G4 phase 2). `refer(t)` unifies `t` INTO the
|
|
410
|
-
// node it addresses, which is a write at a position the meet is not
|
|
411
|
-
// currently at -- the one non-local effect in the evaluator.
|
|
412
|
-
//
|
|
413
|
-
// It cannot be only a write made during the pass. A pass BUILDS a new
|
|
414
|
-
// tree from the old one, and `ctx.root` during pass N is pass N-1's
|
|
415
|
-
// result; a subtree rebuilt by pass N (which is exactly what happens
|
|
416
|
-
// when the link sits inside its own target, or when two nodes link at
|
|
417
|
-
// each other) drops a write made into the previous one. So each flow is
|
|
418
|
-
// also RECORDED, keyed by the target's path, and re-applied to the
|
|
419
|
-
// pass's own result here.
|
|
420
|
-
//
|
|
421
|
-
// Keyed by PATH, so there is no registry of names to collide in
|
|
422
|
-
// (ADR-014) -- the key is the position the address resolved to, and
|
|
423
|
-
// re-uniting the same type at the same position is idempotent, which is
|
|
424
|
-
// what makes replaying every recorded flow every pass correct rather
|
|
425
|
-
// than merely cheap.
|
|
426
|
-
//
|
|
427
|
-
// The pass loop is its only caller; it is EXPORTED for the test that
|
|
428
|
-
// pins the unresolved-path guard below (see there).
|
|
429
283
|
function applyFlows(ctx: AontuContext, root: Val): Val {
|
|
430
284
|
const flows: Map<string, Val> | undefined = (ctx as any).referflows
|
|
431
285
|
// NOTHING TO APPLY is the common case -- a document with no links
|
|
@@ -433,32 +287,8 @@ function applyFlows(ctx: AontuContext, root: Val): Val {
|
|
|
433
287
|
if (null == flows || 0 === flows.size) {
|
|
434
288
|
return root
|
|
435
289
|
}
|
|
436
|
-
// Sorted, so two flows landing at overlapping positions arrive in the
|
|
437
|
-
// same order in both ports.
|
|
438
290
|
for (const key of [...flows.keys()].sort()) {
|
|
439
291
|
const path = key.split('\x00')
|
|
440
|
-
// The SHARED resolver, the one `refer` itself uses: a second
|
|
441
|
-
// descent written here would be a second answer to "what does this
|
|
442
|
-
// path name", and the two would drift (the Go twin calls the same
|
|
443
|
-
// findAt, arm for arm -- ADR-001).
|
|
444
|
-
//
|
|
445
|
-
// A RECORDED PATH THAT NO LONGER RESOLVES is skipped rather than
|
|
446
|
-
// refused: the record outliving its position is a question about
|
|
447
|
-
// the tree, and the link that named it answers it
|
|
448
|
-
// (test/spec/refer.tsv, `flow-target-moved-away`).
|
|
449
|
-
//
|
|
450
|
-
// NO DOCUMENT REACHES IT: a record is written only for a path that
|
|
451
|
-
// HAD resolved, and unification never takes a node back out of the
|
|
452
|
-
// tree — `move` copies and hides its source rather than removing
|
|
453
|
-
// it, which is the one rearrangement that looked like it would
|
|
454
|
-
// (probed in both ports: the flow still resolves on every pass,
|
|
455
|
-
// `flow-lands-then-its-parent-moves`). The guard is the contract
|
|
456
|
-
// for a rearrangement that does, and it is pinned by a direct call
|
|
457
|
-
// (`apply-flows-skips-a-record-that-stops-resolving` in
|
|
458
|
-
// ts/test/coverage3.test.ts) rather than by an ignore marker: node's
|
|
459
|
-
// `coverage ignore` drops LINES, and the gate reads BRANCH records,
|
|
460
|
-
// which survive it. The Go twin in go/unify.go can use the marker
|
|
461
|
-
// because that gate counts statements.
|
|
462
292
|
const found = findAt(root, path)
|
|
463
293
|
if (undefined === found) {
|
|
464
294
|
continue
|
|
@@ -517,8 +347,6 @@ class Unify {
|
|
|
517
347
|
})
|
|
518
348
|
}
|
|
519
349
|
|
|
520
|
-
// TODO: messy
|
|
521
|
-
// uctx.seterr(this.err)
|
|
522
350
|
uctx.err = this.err
|
|
523
351
|
uctx.explain = this.explain
|
|
524
352
|
|
|
@@ -526,12 +354,6 @@ class Unify {
|
|
|
526
354
|
// keyed by ref canon + source site, shared across all passes.
|
|
527
355
|
; (uctx as any).snapmap = new Map()
|
|
528
356
|
|
|
529
|
-
// The RECORDED TYPE FLOWS (G4 phase 2): target path -> the type
|
|
530
|
-
// `refer(t)` unified into it, replayed onto each pass's result by
|
|
531
|
-
// applyFlows. Seeded HERE, on the unify root, for the reason the
|
|
532
|
-
// snapshot map above is: a descended context is Object.create'd
|
|
533
|
-
// from its parent, so a `??=` in the descendant would make its
|
|
534
|
-
// OWN map and the root would never see what was recorded.
|
|
535
357
|
; (uctx as any).referflows = new Map()
|
|
536
358
|
|
|
537
359
|
// The re-entrancy guard for those flows: the set of target paths
|
|
@@ -547,71 +369,23 @@ class Unify {
|
|
|
547
369
|
let lastCanon: string | undefined = undefined
|
|
548
370
|
let settle = false
|
|
549
371
|
for (; this.cc < maxcc && DONE !== res.dc; this.cc++) {
|
|
550
|
-
// console.log('CC', this.cc, res.canon)
|
|
551
372
|
uctx.cc = this.cc
|
|
552
373
|
uctx.seen = {}
|
|
553
374
|
|
|
554
|
-
// THE STAGING RULE (G8 phase 0,
|
|
555
|
-
// docs/capability-review/g8-generation.md), stated once, here,
|
|
556
|
-
// for every value whose answer depends on WHERE IT IS. Such a
|
|
557
|
-
// value residuates while the model is still moving and fires on
|
|
558
|
-
// the first pass whose input is IDENTICAL to the previous
|
|
559
|
-
// pass's input: nothing moved, so nothing will move it again,
|
|
560
|
-
// and the position it reports is the position it ends at.
|
|
561
|
-
//
|
|
562
|
-
// Why the whole model and not the value's own path. A spread, a
|
|
563
|
-
// reference or a `move` can place a value under a path it has
|
|
564
|
-
// already been driven at and THEN change what encloses it --
|
|
565
|
-
// `move` hides its source one pass AFTER it copies it, and a
|
|
566
|
-
// `key()` that answered on the strength of its path alone would
|
|
567
|
-
// answer for the ghost. Stability of the model is the only
|
|
568
|
-
// signal that says every such rearrangement is finished.
|
|
569
375
|
uctx.settle = settle
|
|
570
376
|
|
|
571
|
-
// Snapshot BEFORE the final pass (the loop condition has
|
|
572
|
-
// already established the tree is not done), so exhaustion can
|
|
573
|
-
// tell "still refining" from "stable residue" below. Taken at
|
|
574
|
-
// the final pass's ENTRY rather than the previous pass's exit
|
|
575
|
-
// — the same value when the budget allows two passes, and the
|
|
576
|
-
// only possible value when the trust profile sets passes to 1,
|
|
577
|
-
// where the old placement (cc === maxcc - 2, never true) made
|
|
578
|
-
// exhaustion silent, exactly the truncation docs/trust.md
|
|
579
|
-
// forbids. `lastCanon` IS that entry canon whenever a previous
|
|
580
|
-
// pass rendered one, so this costs nothing extra.
|
|
581
377
|
if (this.cc === maxcc - 1) {
|
|
582
378
|
prevCanon = lastCanon ?? res.canon
|
|
583
379
|
}
|
|
584
380
|
|
|
585
381
|
res = unite(te ? uctx.clone({ explain: ec(te, 'run') }) : uctx, res, top(), 'unify')
|
|
586
382
|
|
|
587
|
-
// MULTI-ERROR COLLECTION (G2 phase 6): the pass loop CONTINUES
|
|
588
|
-
// past an erroring pass, so independent failures a later pass
|
|
589
|
-
// would reach are collected in the same run — the break that
|
|
590
|
-
// stood here made every multi-error report truncated at the
|
|
591
|
-
// first erroring pass.
|
|
592
|
-
//
|
|
593
|
-
// What controls the cascade the design feared: a nil is
|
|
594
|
-
// ABSORBING (unite's isNil arms return the existing nil, no new
|
|
595
|
-
// error), so one failure stays ONE NilVal however many later
|
|
596
|
-
// meets touch it — a reference resolving to a failed target
|
|
597
|
-
// takes the same nil identity, which is exactly what lets the
|
|
598
|
-
// report layer dedup by identity. The probes that established
|
|
599
|
-
// this (fan-in refs, spread templates, disjunct trials, nested
|
|
600
|
-
// conjuncts) are pinned as vet.tsv's multi-* rows in both
|
|
601
|
-
// ports.
|
|
602
383
|
|
|
603
384
|
// The recorded type flows, re-applied to the tree THIS pass
|
|
604
385
|
// built: a pass rebuilds subtrees, and a flow written into the
|
|
605
386
|
// previous pass's tree does not survive that.
|
|
606
387
|
res = applyFlows(uctx, res)
|
|
607
388
|
|
|
608
|
-
// The staging signal for the NEXT pass, rendered here rather
|
|
609
|
-
// than at the top of the loop so a model that is FINISHED is
|
|
610
|
-
// never rendered at all: canon walks references, and the only
|
|
611
|
-
// trees that close a cycle are hand-built ones (the pass loop
|
|
612
|
-
// is what a test drives them through), which converge in one
|
|
613
|
-
// pass and must not be walked to decide a question that no
|
|
614
|
-
// longer arises.
|
|
615
389
|
if (DONE !== res.dc) {
|
|
616
390
|
const nowCanon = res.canon
|
|
617
391
|
settle = undefined !== lastCanon && lastCanon === nowCanon
|
|
@@ -621,16 +395,6 @@ class Unify {
|
|
|
621
395
|
uctx = uctx.clone({ root: res })
|
|
622
396
|
}
|
|
623
397
|
|
|
624
|
-
// The pass budget is spent AND the final pass still made
|
|
625
|
-
// progress: the model was cut off while converging, and no other
|
|
626
|
-
// error explains why. Silent truncation would surface later as
|
|
627
|
-
// ordinary incompleteness, so exhaustion is a semantic error of
|
|
628
|
-
// its own (class budget, docs/trust.md clause 2) -- retrying with
|
|
629
|
-
// a larger budget is a valid response to THIS code and useless
|
|
630
|
-
// for path_cycle or no_path. A STABLE residue (the final pass
|
|
631
|
-
// changed nothing -- e.g. a stuck `1+true`) is not a budget
|
|
632
|
-
// failure: it is ordinary incompleteness and stays silent here,
|
|
633
|
-
// surfacing at generate exactly as before.
|
|
634
398
|
if (maxcc <= this.cc && DONE !== res.dc && 0 === uctx.err.length
|
|
635
399
|
&& undefined !== prevCanon && prevCanon !== res.canon) {
|
|
636
400
|
makeNilErr(uctx, 'budget_passes', undefined, undefined, 'resolve', {
|
|
@@ -653,8 +417,6 @@ class Unify {
|
|
|
653
417
|
} /* node:coverage ignore next 10 */
|
|
654
418
|
|
|
655
419
|
|
|
656
|
-
|
|
657
|
-
|
|
658
420
|
export {
|
|
659
421
|
Unify,
|
|
660
422
|
unite,
|