@descryy/ir 0.1.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/LICENSE +21 -0
- package/dist/capabilities.d.ts +83 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +91 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/conformance/bind.d.ts +82 -0
- package/dist/conformance/bind.d.ts.map +1 -0
- package/dist/conformance/bind.js +157 -0
- package/dist/conformance/bind.js.map +1 -0
- package/dist/conformance/cli.d.ts +25 -0
- package/dist/conformance/cli.d.ts.map +1 -0
- package/dist/conformance/cli.js +137 -0
- package/dist/conformance/cli.js.map +1 -0
- package/dist/conformance/compare.d.ts +74 -0
- package/dist/conformance/compare.d.ts.map +1 -0
- package/dist/conformance/compare.js +140 -0
- package/dist/conformance/compare.js.map +1 -0
- package/dist/conformance/compose.d.ts +79 -0
- package/dist/conformance/compose.d.ts.map +1 -0
- package/dist/conformance/compose.js +167 -0
- package/dist/conformance/compose.js.map +1 -0
- package/dist/conformance/golden.d.ts +110 -0
- package/dist/conformance/golden.d.ts.map +1 -0
- package/dist/conformance/golden.js +252 -0
- package/dist/conformance/golden.js.map +1 -0
- package/dist/conformance/index.d.ts +26 -0
- package/dist/conformance/index.d.ts.map +1 -0
- package/dist/conformance/index.js +18 -0
- package/dist/conformance/index.js.map +1 -0
- package/dist/conformance/manifest-check.d.ts +78 -0
- package/dist/conformance/manifest-check.d.ts.map +1 -0
- package/dist/conformance/manifest-check.js +149 -0
- package/dist/conformance/manifest-check.js.map +1 -0
- package/dist/conformance/manifest.d.ts +83 -0
- package/dist/conformance/manifest.d.ts.map +1 -0
- package/dist/conformance/manifest.js +158 -0
- package/dist/conformance/manifest.js.map +1 -0
- package/dist/conformance/report.d.ts +14 -0
- package/dist/conformance/report.d.ts.map +1 -0
- package/dist/conformance/report.js +87 -0
- package/dist/conformance/report.js.map +1 -0
- package/dist/conformance/run.d.ts +172 -0
- package/dist/conformance/run.d.ts.map +1 -0
- package/dist/conformance/run.js +626 -0
- package/dist/conformance/run.js.map +1 -0
- package/dist/contracts.d.ts +198 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +10 -0
- package/dist/contracts.js.map +1 -0
- package/dist/contradiction.d.ts +112 -0
- package/dist/contradiction.d.ts.map +1 -0
- package/dist/contradiction.js +97 -0
- package/dist/contradiction.js.map +1 -0
- package/dist/finding.d.ts +567 -0
- package/dist/finding.d.ts.map +1 -0
- package/dist/finding.js +491 -0
- package/dist/finding.js.map +1 -0
- package/dist/hypothesis.d.ts +130 -0
- package/dist/hypothesis.d.ts.map +1 -0
- package/dist/hypothesis.js +116 -0
- package/dist/hypothesis.js.map +1 -0
- package/dist/identity.d.ts +295 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +404 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/ir.d.ts +360 -0
- package/dist/ir.d.ts.map +1 -0
- package/dist/ir.js +76 -0
- package/dist/ir.js.map +1 -0
- package/dist/model-tables.d.ts +111 -0
- package/dist/model-tables.d.ts.map +1 -0
- package/dist/model-tables.js +103 -0
- package/dist/model-tables.js.map +1 -0
- package/dist/normalise.d.ts +114 -0
- package/dist/normalise.d.ts.map +1 -0
- package/dist/normalise.js +603 -0
- package/dist/normalise.js.map +1 -0
- package/dist/reliability.d.ts +89 -0
- package/dist/reliability.d.ts.map +1 -0
- package/dist/reliability.js +181 -0
- package/dist/reliability.js.map +1 -0
- package/dist/tool-surface.d.ts +131 -0
- package/dist/tool-surface.d.ts.map +1 -0
- package/dist/tool-surface.js +133 -0
- package/dist/tool-surface.js.map +1 -0
- package/dist/vocabulary.d.ts +73 -0
- package/dist/vocabulary.d.ts.map +1 -0
- package/dist/vocabulary.js +150 -0
- package/dist/vocabulary.js.map +1 -0
- package/package.json +27 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture principle 3, as a function.
|
|
3
|
+
*
|
|
4
|
+
* *A finding's reliability class is capped by the resolution level of the edges
|
|
5
|
+
* it rests on.* §11A.5 states the rule as a table and calls it "the single most
|
|
6
|
+
* consequential addition in v2.1"; until now nothing in the codebase evaluated
|
|
7
|
+
* it. The query layer computes a `resolutionFloor` for every answer and every
|
|
8
|
+
* consumer was free to ignore it, which is precisely the shape of a rule that
|
|
9
|
+
* holds in the document and not in the product.
|
|
10
|
+
*
|
|
11
|
+
* It lives in `@descryy/ir` rather than in the query layer because it is a
|
|
12
|
+
* property of the resolution scale itself. The MCP server is the first consumer;
|
|
13
|
+
* governance and the report layer are the next two, and all three must agree.
|
|
14
|
+
*
|
|
15
|
+
* ## The R2 row is not a typo
|
|
16
|
+
*
|
|
17
|
+
* §11A.5 gives R2 two answers: **B** in general, **A** for name-level facts only
|
|
18
|
+
* — a missing environment variable, a migration head, a route path that does not
|
|
19
|
+
* exist. The distinction is real. At R2 an LSP has resolved *which symbol a name
|
|
20
|
+
* refers to*, so a claim about the name is as good as it will get; a claim about
|
|
21
|
+
* the *shape* behind the name is not, because no type checker ran. Collapsing
|
|
22
|
+
* the row to "B" would silently downgrade the env-var check, which is the
|
|
23
|
+
* cheapest Class A check in the system (§1.10) and works at R0 in any language.
|
|
24
|
+
*
|
|
25
|
+
* So the caller states which kind of claim it is making. There is no default:
|
|
26
|
+
* `nameLevel` is a required argument, because a caller that has not thought
|
|
27
|
+
* about which kind of fact it is asserting is exactly the caller that would take
|
|
28
|
+
* the wrong one.
|
|
29
|
+
*
|
|
30
|
+
* ## `humanAsserted` — a second, independent cap, never a promotion
|
|
31
|
+
*
|
|
32
|
+
* DEC-223's answer half: an edge minted because a person confirmed a value
|
|
33
|
+
* for a refusal-ledger row (§3's `ConfirmedFact`) rests on exactly one
|
|
34
|
+
* unaudited assertion, corroborated by nothing. It is not R0-R4 at all —
|
|
35
|
+
* testimony is a different kind of evidence than "how much static or runtime
|
|
36
|
+
* tooling ran" — so it cannot be slotted into the resolution ladder honestly.
|
|
37
|
+
* Left unguarded, a `nameLevel: true` claim at R2 or better would reach class
|
|
38
|
+
* A the same way a genuinely independent name-level fact does, and a single
|
|
39
|
+
* person's typed string would silently defeat the one rule principle 3 exists
|
|
40
|
+
* to enforce.
|
|
41
|
+
*
|
|
42
|
+
* So `humanAsserted` is a **second, independent ceiling**, applied after the
|
|
43
|
+
* resolution/name-level table above, never a replacement for it and never a
|
|
44
|
+
* promotion: a structural C stays C (there is nothing to cap down from), a
|
|
45
|
+
* structural B stays B, and only a structural A is pulled down to B. Default
|
|
46
|
+
* `false` so every existing caller is unaffected.
|
|
47
|
+
*/
|
|
48
|
+
import type { ResolutionLevel } from "./ir.ts";
|
|
49
|
+
/**
|
|
50
|
+
* §15.2's classes.
|
|
51
|
+
*
|
|
52
|
+
* `A` provable · `B` reportable with explicit confidence labelling ·
|
|
53
|
+
* `C` behavioural prediction, which principle 4 forbids reporting as fact
|
|
54
|
+
* until a runtime run confirms it.
|
|
55
|
+
*/
|
|
56
|
+
export type ReliabilityClass = "A" | "B" | "C";
|
|
57
|
+
export declare const RELIABILITY_CLASSES: readonly ["A", "B", "C"];
|
|
58
|
+
/**
|
|
59
|
+
* What a claim resting on evidence at `resolution` may be classified as, at best.
|
|
60
|
+
*
|
|
61
|
+
* @param nameLevel `true` when the claim is about a *name* — a symbol that does
|
|
62
|
+
* or does not exist, a path, an identifier. `false` when it is about a *shape*:
|
|
63
|
+
* a field's type, a payload's structure, a signature. Only the name-level case
|
|
64
|
+
* can reach `A` at R2, and only shape-level claims are what R3 buys.
|
|
65
|
+
* @param humanAsserted `true` when the edge exists because a person confirmed a
|
|
66
|
+
* value for a refusal-ledger row (DEC-223), rather than because static or
|
|
67
|
+
* runtime analysis resolved it. Pulls a structural `A` down to `B`; never
|
|
68
|
+
* raises `B` or `C`, and never appears as a fourth resolution level — see the
|
|
69
|
+
* module doc. Defaults `false` so every pre-existing caller is unaffected.
|
|
70
|
+
*/
|
|
71
|
+
export declare function reliabilityCap(resolution: ResolutionLevel, nameLevel: boolean, humanAsserted?: boolean): ReliabilityClass;
|
|
72
|
+
/**
|
|
73
|
+
* The sentence a report puts next to a capped finding.
|
|
74
|
+
*
|
|
75
|
+
* Returned rather than logged, and returned even for `A`, so that a caller
|
|
76
|
+
* cannot produce an unlabelled finding by taking the class and discarding the
|
|
77
|
+
* disclosure. Rule 7 — honest degradation — is a property of what reaches the
|
|
78
|
+
* user, not of what the engine computed.
|
|
79
|
+
*
|
|
80
|
+
* @param emptyPath `true` when `resolution` is `0` because
|
|
81
|
+
* {@link minimumResolution} was given an empty graph path — no hop existed to
|
|
82
|
+
* take a minimum over — rather than because a hop actually resolved to R0.
|
|
83
|
+
* Both cap at class C (DEC-NEXT-empty-graph-path-resolution-floor.md kept
|
|
84
|
+
* the stored value unchanged); this flag only changes which sentence explains
|
|
85
|
+
* the cap, so a genuinely untraced path is not described as a poorly
|
|
86
|
+
* resolved one. Defaults `false` so every pre-existing caller is unaffected.
|
|
87
|
+
*/
|
|
88
|
+
export declare function reliabilityNote(resolution: ResolutionLevel, nameLevel: boolean, humanAsserted?: boolean, emptyPath?: boolean): string;
|
|
89
|
+
//# sourceMappingURL=reliability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reliability.d.ts","sourceRoot":"","sources":["../src/reliability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI/C;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE/C,eAAO,MAAM,mBAAmB,0BAA2B,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,OAAO,EAClB,aAAa,UAAQ,GACpB,gBAAgB,CAsBlB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,OAAO,EAClB,aAAa,UAAQ,EACrB,SAAS,UAAQ,GAChB,MAAM,CAwFR"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture principle 3, as a function.
|
|
3
|
+
*
|
|
4
|
+
* *A finding's reliability class is capped by the resolution level of the edges
|
|
5
|
+
* it rests on.* §11A.5 states the rule as a table and calls it "the single most
|
|
6
|
+
* consequential addition in v2.1"; until now nothing in the codebase evaluated
|
|
7
|
+
* it. The query layer computes a `resolutionFloor` for every answer and every
|
|
8
|
+
* consumer was free to ignore it, which is precisely the shape of a rule that
|
|
9
|
+
* holds in the document and not in the product.
|
|
10
|
+
*
|
|
11
|
+
* It lives in `@descryy/ir` rather than in the query layer because it is a
|
|
12
|
+
* property of the resolution scale itself. The MCP server is the first consumer;
|
|
13
|
+
* governance and the report layer are the next two, and all three must agree.
|
|
14
|
+
*
|
|
15
|
+
* ## The R2 row is not a typo
|
|
16
|
+
*
|
|
17
|
+
* §11A.5 gives R2 two answers: **B** in general, **A** for name-level facts only
|
|
18
|
+
* — a missing environment variable, a migration head, a route path that does not
|
|
19
|
+
* exist. The distinction is real. At R2 an LSP has resolved *which symbol a name
|
|
20
|
+
* refers to*, so a claim about the name is as good as it will get; a claim about
|
|
21
|
+
* the *shape* behind the name is not, because no type checker ran. Collapsing
|
|
22
|
+
* the row to "B" would silently downgrade the env-var check, which is the
|
|
23
|
+
* cheapest Class A check in the system (§1.10) and works at R0 in any language.
|
|
24
|
+
*
|
|
25
|
+
* So the caller states which kind of claim it is making. There is no default:
|
|
26
|
+
* `nameLevel` is a required argument, because a caller that has not thought
|
|
27
|
+
* about which kind of fact it is asserting is exactly the caller that would take
|
|
28
|
+
* the wrong one.
|
|
29
|
+
*
|
|
30
|
+
* ## `humanAsserted` — a second, independent cap, never a promotion
|
|
31
|
+
*
|
|
32
|
+
* DEC-223's answer half: an edge minted because a person confirmed a value
|
|
33
|
+
* for a refusal-ledger row (§3's `ConfirmedFact`) rests on exactly one
|
|
34
|
+
* unaudited assertion, corroborated by nothing. It is not R0-R4 at all —
|
|
35
|
+
* testimony is a different kind of evidence than "how much static or runtime
|
|
36
|
+
* tooling ran" — so it cannot be slotted into the resolution ladder honestly.
|
|
37
|
+
* Left unguarded, a `nameLevel: true` claim at R2 or better would reach class
|
|
38
|
+
* A the same way a genuinely independent name-level fact does, and a single
|
|
39
|
+
* person's typed string would silently defeat the one rule principle 3 exists
|
|
40
|
+
* to enforce.
|
|
41
|
+
*
|
|
42
|
+
* So `humanAsserted` is a **second, independent ceiling**, applied after the
|
|
43
|
+
* resolution/name-level table above, never a replacement for it and never a
|
|
44
|
+
* promotion: a structural C stays C (there is nothing to cap down from), a
|
|
45
|
+
* structural B stays B, and only a structural A is pulled down to B. Default
|
|
46
|
+
* `false` so every existing caller is unaffected.
|
|
47
|
+
*/
|
|
48
|
+
const RELIABILITY_ORDER = { A: 2, B: 1, C: 0 };
|
|
49
|
+
export const RELIABILITY_CLASSES = ["A", "B", "C"];
|
|
50
|
+
/**
|
|
51
|
+
* What a claim resting on evidence at `resolution` may be classified as, at best.
|
|
52
|
+
*
|
|
53
|
+
* @param nameLevel `true` when the claim is about a *name* — a symbol that does
|
|
54
|
+
* or does not exist, a path, an identifier. `false` when it is about a *shape*:
|
|
55
|
+
* a field's type, a payload's structure, a signature. Only the name-level case
|
|
56
|
+
* can reach `A` at R2, and only shape-level claims are what R3 buys.
|
|
57
|
+
* @param humanAsserted `true` when the edge exists because a person confirmed a
|
|
58
|
+
* value for a refusal-ledger row (DEC-223), rather than because static or
|
|
59
|
+
* runtime analysis resolved it. Pulls a structural `A` down to `B`; never
|
|
60
|
+
* raises `B` or `C`, and never appears as a fourth resolution level — see the
|
|
61
|
+
* module doc. Defaults `false` so every pre-existing caller is unaffected.
|
|
62
|
+
*/
|
|
63
|
+
export function reliabilityCap(resolution, nameLevel, humanAsserted = false) {
|
|
64
|
+
const structural = (() => {
|
|
65
|
+
switch (resolution) {
|
|
66
|
+
case 0:
|
|
67
|
+
return "C";
|
|
68
|
+
case 1:
|
|
69
|
+
return "B";
|
|
70
|
+
case 2:
|
|
71
|
+
return nameLevel ? "A" : "B";
|
|
72
|
+
default:
|
|
73
|
+
// R3 (type checker) and R4 (witnessed at runtime). R4 is unconditional —
|
|
74
|
+
// the edge was observed rather than inferred, so there is no kind of claim
|
|
75
|
+
// it fails to support.
|
|
76
|
+
return "A";
|
|
77
|
+
}
|
|
78
|
+
})();
|
|
79
|
+
if (!humanAsserted)
|
|
80
|
+
return structural;
|
|
81
|
+
// A cap, never a promotion: only pulls A down to B. C is already below B, so
|
|
82
|
+
// a human declaration cannot make an R0-grounded claim look stronger than it
|
|
83
|
+
// is — it can only ever cost reliability, never buy it.
|
|
84
|
+
return RELIABILITY_ORDER[structural] > RELIABILITY_ORDER.B ? "B" : structural;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The sentence a report puts next to a capped finding.
|
|
88
|
+
*
|
|
89
|
+
* Returned rather than logged, and returned even for `A`, so that a caller
|
|
90
|
+
* cannot produce an unlabelled finding by taking the class and discarding the
|
|
91
|
+
* disclosure. Rule 7 — honest degradation — is a property of what reaches the
|
|
92
|
+
* user, not of what the engine computed.
|
|
93
|
+
*
|
|
94
|
+
* @param emptyPath `true` when `resolution` is `0` because
|
|
95
|
+
* {@link minimumResolution} was given an empty graph path — no hop existed to
|
|
96
|
+
* take a minimum over — rather than because a hop actually resolved to R0.
|
|
97
|
+
* Both cap at class C (DEC-NEXT-empty-graph-path-resolution-floor.md kept
|
|
98
|
+
* the stored value unchanged); this flag only changes which sentence explains
|
|
99
|
+
* the cap, so a genuinely untraced path is not described as a poorly
|
|
100
|
+
* resolved one. Defaults `false` so every pre-existing caller is unaffected.
|
|
101
|
+
*/
|
|
102
|
+
export function reliabilityNote(resolution, nameLevel, humanAsserted = false, emptyPath = false) {
|
|
103
|
+
const cap = reliabilityCap(resolution, nameLevel, humanAsserted);
|
|
104
|
+
const structuralCap = reliabilityCap(resolution, nameLevel);
|
|
105
|
+
const basis = `The weakest evidence under this answer is R${resolution}`;
|
|
106
|
+
if (humanAsserted && RELIABILITY_ORDER[structuralCap] > RELIABILITY_ORDER.B) {
|
|
107
|
+
// The one case rule 7 exists for here: the structural evidence alone would
|
|
108
|
+
// have permitted A, and a person's declaration is the only reason it does
|
|
109
|
+
// not. Naming that plainly rather than folding it into the generic B
|
|
110
|
+
// sentence below, which would read as an ordinary resolution shortfall.
|
|
111
|
+
return (`${basis}, which on its own would permit reliability class A. This edge exists because a ` +
|
|
112
|
+
"person confirmed a value for a refusal-ledger row, not because analysis resolved it — one " +
|
|
113
|
+
"unaudited assertion, corroborated by nothing — so it is capped at class B regardless.");
|
|
114
|
+
}
|
|
115
|
+
switch (cap) {
|
|
116
|
+
case "C":
|
|
117
|
+
// DEC-NEXT-empty-graph-path-resolution-floor.md's ruling: a zero-hop
|
|
118
|
+
// graph path derives R0 by the same construction as a genuinely
|
|
119
|
+
// R0-resolved hop, and both cap at class C — but they are not the same
|
|
120
|
+
// claim, and describing an untraced path with the "syntax only, nothing
|
|
121
|
+
// resolved" wording below would suggest a bad trace where none was
|
|
122
|
+
// attempted at all. This branch is checked first, ahead of the
|
|
123
|
+
// name-level/shape-level split, because what's missing here is
|
|
124
|
+
// attribution, not a name-vs-shape distinction — the sentence is the
|
|
125
|
+
// same regardless of `nameLevel`. The strength of the underlying
|
|
126
|
+
// observation (if any) belongs in Runtime evidence, not here: rule 3's
|
|
127
|
+
// cap does not move, only the sentence explaining it stays honest about
|
|
128
|
+
// why (rule 7).
|
|
129
|
+
if (emptyPath) {
|
|
130
|
+
return (`${basis} — no graph path was traced at all, which caps this at reliability class C. ` +
|
|
131
|
+
"This is a different fact from a path that was traced and resolved poorly: nothing here " +
|
|
132
|
+
"suggests a weak trace, only that no causal path from evidence to code was ever asserted. " +
|
|
133
|
+
"Any runtime corroboration for the underlying observation is reported separately, under " +
|
|
134
|
+
"Runtime evidence, and does not raise this cap. Principle 4 forbids reporting this as a " +
|
|
135
|
+
"fact about the running system until a runtime run confirms it.");
|
|
136
|
+
}
|
|
137
|
+
// Described by what R0 *is* — syntax with nothing resolved — rather than
|
|
138
|
+
// by the parser that produces it. The boundary lint refuses the toolchain
|
|
139
|
+
// name here and is right to: this string reaches a user, and a user with a
|
|
140
|
+
// repository in a language whose R0 comes from somewhere else would be
|
|
141
|
+
// told something false about their own run.
|
|
142
|
+
//
|
|
143
|
+
// **The two R0 claims are not the same claim, and one sentence for both
|
|
144
|
+
// overstated one of them.** A name-level fact at R0 — *this file names
|
|
145
|
+
// this environment variable* — was read where it is written. What R0
|
|
146
|
+
// fails to establish is what the name refers to and whether the code runs
|
|
147
|
+
// at all. Calling that "a behavioural prediction" describes neither
|
|
148
|
+
// failure, and to a reader it suggests the finding was inferred rather
|
|
149
|
+
// than read, which is worse than saying nothing. A shape-level claim at
|
|
150
|
+
// R0 genuinely is a prediction: nothing resolved the type under it.
|
|
151
|
+
//
|
|
152
|
+
// The class is C either way. Principle 3's cap is not what changes here
|
|
153
|
+
// — only the sentence that explains it, and a disclosure that misstates
|
|
154
|
+
// its own basis is rule 7 failing in the one place rule 7 acts.
|
|
155
|
+
return nameLevel
|
|
156
|
+
? `${basis} (syntax only, with no references resolved), which caps this at reliability ` +
|
|
157
|
+
"class C. The name was read where it is written; what has not been established is what " +
|
|
158
|
+
"it refers to, or whether this code runs at all. Principle 4 forbids reporting it as a " +
|
|
159
|
+
"fact about the running system until a runtime run confirms it."
|
|
160
|
+
: `${basis} (syntax only, with no references resolved), which caps this at reliability ` +
|
|
161
|
+
"class C: a behavioural prediction, not an established fact — no type checker resolved " +
|
|
162
|
+
"the shapes it rests on. Principle 4 forbids reporting it as one until a runtime run " +
|
|
163
|
+
"confirms it.";
|
|
164
|
+
case "B":
|
|
165
|
+
return (`${basis}, which caps this at reliability class B: reportable, but with its confidence ` +
|
|
166
|
+
"stated. " +
|
|
167
|
+
(resolution === 2
|
|
168
|
+
? "R2 resolves which symbol a name refers to but runs no type checker, so a claim " +
|
|
169
|
+
"about the shape behind the name is not provable at this level."
|
|
170
|
+
: "Cross-file resolution at this level is name-matched rather than resolved."));
|
|
171
|
+
default:
|
|
172
|
+
return (`${basis}, which permits reliability class A` +
|
|
173
|
+
(resolution === 2
|
|
174
|
+
? " for this claim, because it is a name-level fact — R2 resolved the symbol the name " +
|
|
175
|
+
"refers to. A shape-level claim on the same evidence would be capped at B."
|
|
176
|
+
: resolution === 4
|
|
177
|
+
? ": the evidence was witnessed at runtime rather than inferred."
|
|
178
|
+
: ": a type checker resolved the shapes this rests on."));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=reliability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reliability.js","sourceRoot":"","sources":["../src/reliability.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two enumerations the AI layer's tool surface is built on, and nothing
|
|
3
|
+
* else.
|
|
4
|
+
*
|
|
5
|
+
* Neither is implemented here. `ResultState` is P2's work and `ToolClass` is
|
|
6
|
+
* P1's; what belongs at the IR boundary is the *vocabulary*, because three
|
|
7
|
+
* consumers — the MCP tool definitions, the pipeline that reads their results,
|
|
8
|
+
* and the desktop surface that renders them — must agree on it exactly. Three
|
|
9
|
+
* nearly-identical local copies of a five-member union is how two of them come
|
|
10
|
+
* to disagree about one member, which is the failure this file exists to make
|
|
11
|
+
* impossible rather than unlikely.
|
|
12
|
+
*
|
|
13
|
+
* Both follow `RELIABILITY_CLASSES`' shape: an `as const` array plus a derived
|
|
14
|
+
* union, never a TS enum — enums are not erasable syntax and Node's type
|
|
15
|
+
* stripping cannot run them (tsconfig `erasableSyntaxOnly` enforces this).
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* `documents/architecture/ai-tool-contract.md` §1 — the five result states, and
|
|
19
|
+
* `documents/plans/ai-layer-plan.md` §3's contract rule 1 beneath it.
|
|
20
|
+
*
|
|
21
|
+
* | State | The tool… | `data` | What the caller may read from it |
|
|
22
|
+
* | --- | --- | --- | --- |
|
|
23
|
+
* | `ok` | looked and found something | populated | a fact about the code |
|
|
24
|
+
* | `empty` | looked, completely, and there was nothing | empty collection | **a fact about the code** — the absence is real |
|
|
25
|
+
* | `refused` | could not look, and knows why | `null` | **a fact about Descry**, never about the code |
|
|
26
|
+
* | `failed` | tried, and something broke | `null` or partial | a fault; not a statement about the code either way |
|
|
27
|
+
* | `timed_out` | ran out of its declared budget | partial, marked so | a partial answer; absence within it means nothing |
|
|
28
|
+
*
|
|
29
|
+
* The rule is measured rather than derived — **this project has hit the same
|
|
30
|
+
* defect at three separate layers**, each time because one shape stood for two
|
|
31
|
+
* facts:
|
|
32
|
+
*
|
|
33
|
+
* - a scan reporting 0 framework route annotations in a repository that had
|
|
34
|
+
* 370, because a relative path did not resolve;
|
|
35
|
+
* - a repository reported as *"not on disk"* when it was in the other
|
|
36
|
+
* reference root all along;
|
|
37
|
+
* - a route extractor returning silently on an empty collection, with no
|
|
38
|
+
* refusal row, so *"none are registered"* and *"registration has not run"*
|
|
39
|
+
* arrived identically.
|
|
40
|
+
*
|
|
41
|
+
* A tool that answers `[]` for both *"nothing matched"* and *"I could not
|
|
42
|
+
* look"* teaches a model a false fact **it has no way to detect** — it cannot
|
|
43
|
+
* tell an empty answer from an absent one, so it reasons from the empty
|
|
44
|
+
* denominator as though it were a measurement. Rule 3 of §3 is the other half:
|
|
45
|
+
* a refusal carries its named reason verbatim, because `refused` alone is a
|
|
46
|
+
* state and not an explanation.
|
|
47
|
+
*
|
|
48
|
+
* ## `refused` is not `not analysable` — §1.2
|
|
49
|
+
*
|
|
50
|
+
* They are different axes on different objects. The five here describe **one
|
|
51
|
+
* tool call's outcome**; §19's five report categories — one of which is spelled
|
|
52
|
+
* `not analysable` — describe **a finding's confidence**. A `refused` result is
|
|
53
|
+
* one *input* a governance gate may use when it later assigns the `not
|
|
54
|
+
* analysable` category to a finding, but a tool assigns no category and no tool
|
|
55
|
+
* result carries one.
|
|
56
|
+
*
|
|
57
|
+
* So the two unions deliberately share no member name, and there is a test
|
|
58
|
+
* asserting it. The near-collision is exactly the conflation this project
|
|
59
|
+
* caught at three layers and would otherwise reintroduce at a fourth; a
|
|
60
|
+
* `not_analysable` spelled into this list is how one becomes assignable where
|
|
61
|
+
* the other belongs.
|
|
62
|
+
*
|
|
63
|
+
* ## `empty` is not permission to stop disclosing — §1.3
|
|
64
|
+
*
|
|
65
|
+
* `empty` is a claim that an absence is **real**, and an absence is only as
|
|
66
|
+
* real as the reach of the thing that looked. A tool answering `empty` still
|
|
67
|
+
* states what it searched, so a caller can tell *"there are no callers"* from
|
|
68
|
+
* *"there are no callers among the things this producer emits."*
|
|
69
|
+
*
|
|
70
|
+
* ## A zero population is `refused`, never `empty` — §1.3a
|
|
71
|
+
*
|
|
72
|
+
* **The test is §1's own table, and it is about the denominator, not the
|
|
73
|
+
* result.** `empty` says the tool looked completely and there was nothing to
|
|
74
|
+
* find — a fact about the code. `refused` says it could not look — a fact about
|
|
75
|
+
* Descry. So the question a producer must answer before choosing between them
|
|
76
|
+
* is *whose* absence this is:
|
|
77
|
+
*
|
|
78
|
+
* | | State |
|
|
79
|
+
* | --- | --- |
|
|
80
|
+
* | The population exists; nothing in it matched this query | `empty` |
|
|
81
|
+
* | The population is itself **zero** | **`refused`** |
|
|
82
|
+
*
|
|
83
|
+
* A count over an empty population is not a finding of zero — it is the
|
|
84
|
+
* absence of a measurement. **This project has now paid for that confusion at
|
|
85
|
+
* four layers**, the fourth being incident search, where the first revision of
|
|
86
|
+
* §1.3 used this very endpoint as its worked example of an honest `empty`: with
|
|
87
|
+
* no `INCIDENT` nodes in the graph, answering `empty` says *"this code has no
|
|
88
|
+
* similar incidents"* when the true statement is *"Descry cannot see most
|
|
89
|
+
* incidents in any codebase"* — only a revert mints one, and fix-forward, the
|
|
90
|
+
* commoner pattern by far, mints nothing. The empty-denominator defect, inside
|
|
91
|
+
* the endpoint written to demonstrate the rule against it.
|
|
92
|
+
*
|
|
93
|
+
* The disclosure obligation rides on **both** states, not only on `empty`.
|
|
94
|
+
*
|
|
95
|
+
* `timed_out` is spelled with an underscore, deliberately and once: it crosses
|
|
96
|
+
* a wire protocol as a literal, so the spelling is contract rather than style.
|
|
97
|
+
*/
|
|
98
|
+
export declare const RESULT_STATES: readonly ["ok", "empty", "refused", "failed", "timed_out"];
|
|
99
|
+
export type ResultState = (typeof RESULT_STATES)[number];
|
|
100
|
+
export declare function isResultState(value: string): value is ResultState;
|
|
101
|
+
/**
|
|
102
|
+
* DEC-278 — the three-way split that replaced §3's rule 4 (*"read tools are
|
|
103
|
+
* pure and retryable; action tools are neither"*).
|
|
104
|
+
*
|
|
105
|
+
* | Class | Handshake |
|
|
106
|
+
* | --- | --- |
|
|
107
|
+
* | `read` | No. Pure, retryable. |
|
|
108
|
+
* | `stateful-read` | No. Mutates Descry's own derived state only; idempotent in effect. |
|
|
109
|
+
* | `action` | **Yes** — the two-call confirmation-token handshake. |
|
|
110
|
+
*
|
|
111
|
+
* **The line is not "does it write bytes."** It is *"can its effect change a
|
|
112
|
+
* later finding without the developer having said so."* Re-deriving a graph
|
|
113
|
+
* from code already on disk, or recording where that code is, cannot introduce
|
|
114
|
+
* a claim the repository does not already contain — both write, and neither
|
|
115
|
+
* can move a finding. Recording a person's confirmed value for a
|
|
116
|
+
* refusal-ledger row can: it becomes a graph input, it feeds `humanAsserted`,
|
|
117
|
+
* and DEC-223 caps it at reliability class B precisely because it rests on one
|
|
118
|
+
* unaudited assertion. Only that third kind takes the handshake.
|
|
119
|
+
*
|
|
120
|
+
* Gating all three was considered and rejected as consistent-but-unusable: a
|
|
121
|
+
* client that must confirm before it may build a graph cannot answer the first
|
|
122
|
+
* question asked of it.
|
|
123
|
+
*
|
|
124
|
+
* `stateful-read` needs its own contract test wherever these are enforced —
|
|
125
|
+
* pure-retryable assertions do not apply to it and action-gate assertions must
|
|
126
|
+
* not.
|
|
127
|
+
*/
|
|
128
|
+
export declare const TOOL_CLASSES: readonly ["read", "stateful-read", "action"];
|
|
129
|
+
export type ToolClass = (typeof TOOL_CLASSES)[number];
|
|
130
|
+
export declare function isToolClass(value: string): value is ToolClass;
|
|
131
|
+
//# sourceMappingURL=tool-surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-surface.d.ts","sourceRoot":"","sources":["../src/tool-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,eAAO,MAAM,aAAa,4DAA6D,CAAC;AAExF,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,WAAW,CAEjE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,YAAY,8CAA+C,CAAC;AAEzE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,SAAS,CAE7D"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two enumerations the AI layer's tool surface is built on, and nothing
|
|
3
|
+
* else.
|
|
4
|
+
*
|
|
5
|
+
* Neither is implemented here. `ResultState` is P2's work and `ToolClass` is
|
|
6
|
+
* P1's; what belongs at the IR boundary is the *vocabulary*, because three
|
|
7
|
+
* consumers — the MCP tool definitions, the pipeline that reads their results,
|
|
8
|
+
* and the desktop surface that renders them — must agree on it exactly. Three
|
|
9
|
+
* nearly-identical local copies of a five-member union is how two of them come
|
|
10
|
+
* to disagree about one member, which is the failure this file exists to make
|
|
11
|
+
* impossible rather than unlikely.
|
|
12
|
+
*
|
|
13
|
+
* Both follow `RELIABILITY_CLASSES`' shape: an `as const` array plus a derived
|
|
14
|
+
* union, never a TS enum — enums are not erasable syntax and Node's type
|
|
15
|
+
* stripping cannot run them (tsconfig `erasableSyntaxOnly` enforces this).
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* `documents/architecture/ai-tool-contract.md` §1 — the five result states, and
|
|
19
|
+
* `documents/plans/ai-layer-plan.md` §3's contract rule 1 beneath it.
|
|
20
|
+
*
|
|
21
|
+
* | State | The tool… | `data` | What the caller may read from it |
|
|
22
|
+
* | --- | --- | --- | --- |
|
|
23
|
+
* | `ok` | looked and found something | populated | a fact about the code |
|
|
24
|
+
* | `empty` | looked, completely, and there was nothing | empty collection | **a fact about the code** — the absence is real |
|
|
25
|
+
* | `refused` | could not look, and knows why | `null` | **a fact about Descry**, never about the code |
|
|
26
|
+
* | `failed` | tried, and something broke | `null` or partial | a fault; not a statement about the code either way |
|
|
27
|
+
* | `timed_out` | ran out of its declared budget | partial, marked so | a partial answer; absence within it means nothing |
|
|
28
|
+
*
|
|
29
|
+
* The rule is measured rather than derived — **this project has hit the same
|
|
30
|
+
* defect at three separate layers**, each time because one shape stood for two
|
|
31
|
+
* facts:
|
|
32
|
+
*
|
|
33
|
+
* - a scan reporting 0 framework route annotations in a repository that had
|
|
34
|
+
* 370, because a relative path did not resolve;
|
|
35
|
+
* - a repository reported as *"not on disk"* when it was in the other
|
|
36
|
+
* reference root all along;
|
|
37
|
+
* - a route extractor returning silently on an empty collection, with no
|
|
38
|
+
* refusal row, so *"none are registered"* and *"registration has not run"*
|
|
39
|
+
* arrived identically.
|
|
40
|
+
*
|
|
41
|
+
* A tool that answers `[]` for both *"nothing matched"* and *"I could not
|
|
42
|
+
* look"* teaches a model a false fact **it has no way to detect** — it cannot
|
|
43
|
+
* tell an empty answer from an absent one, so it reasons from the empty
|
|
44
|
+
* denominator as though it were a measurement. Rule 3 of §3 is the other half:
|
|
45
|
+
* a refusal carries its named reason verbatim, because `refused` alone is a
|
|
46
|
+
* state and not an explanation.
|
|
47
|
+
*
|
|
48
|
+
* ## `refused` is not `not analysable` — §1.2
|
|
49
|
+
*
|
|
50
|
+
* They are different axes on different objects. The five here describe **one
|
|
51
|
+
* tool call's outcome**; §19's five report categories — one of which is spelled
|
|
52
|
+
* `not analysable` — describe **a finding's confidence**. A `refused` result is
|
|
53
|
+
* one *input* a governance gate may use when it later assigns the `not
|
|
54
|
+
* analysable` category to a finding, but a tool assigns no category and no tool
|
|
55
|
+
* result carries one.
|
|
56
|
+
*
|
|
57
|
+
* So the two unions deliberately share no member name, and there is a test
|
|
58
|
+
* asserting it. The near-collision is exactly the conflation this project
|
|
59
|
+
* caught at three layers and would otherwise reintroduce at a fourth; a
|
|
60
|
+
* `not_analysable` spelled into this list is how one becomes assignable where
|
|
61
|
+
* the other belongs.
|
|
62
|
+
*
|
|
63
|
+
* ## `empty` is not permission to stop disclosing — §1.3
|
|
64
|
+
*
|
|
65
|
+
* `empty` is a claim that an absence is **real**, and an absence is only as
|
|
66
|
+
* real as the reach of the thing that looked. A tool answering `empty` still
|
|
67
|
+
* states what it searched, so a caller can tell *"there are no callers"* from
|
|
68
|
+
* *"there are no callers among the things this producer emits."*
|
|
69
|
+
*
|
|
70
|
+
* ## A zero population is `refused`, never `empty` — §1.3a
|
|
71
|
+
*
|
|
72
|
+
* **The test is §1's own table, and it is about the denominator, not the
|
|
73
|
+
* result.** `empty` says the tool looked completely and there was nothing to
|
|
74
|
+
* find — a fact about the code. `refused` says it could not look — a fact about
|
|
75
|
+
* Descry. So the question a producer must answer before choosing between them
|
|
76
|
+
* is *whose* absence this is:
|
|
77
|
+
*
|
|
78
|
+
* | | State |
|
|
79
|
+
* | --- | --- |
|
|
80
|
+
* | The population exists; nothing in it matched this query | `empty` |
|
|
81
|
+
* | The population is itself **zero** | **`refused`** |
|
|
82
|
+
*
|
|
83
|
+
* A count over an empty population is not a finding of zero — it is the
|
|
84
|
+
* absence of a measurement. **This project has now paid for that confusion at
|
|
85
|
+
* four layers**, the fourth being incident search, where the first revision of
|
|
86
|
+
* §1.3 used this very endpoint as its worked example of an honest `empty`: with
|
|
87
|
+
* no `INCIDENT` nodes in the graph, answering `empty` says *"this code has no
|
|
88
|
+
* similar incidents"* when the true statement is *"Descry cannot see most
|
|
89
|
+
* incidents in any codebase"* — only a revert mints one, and fix-forward, the
|
|
90
|
+
* commoner pattern by far, mints nothing. The empty-denominator defect, inside
|
|
91
|
+
* the endpoint written to demonstrate the rule against it.
|
|
92
|
+
*
|
|
93
|
+
* The disclosure obligation rides on **both** states, not only on `empty`.
|
|
94
|
+
*
|
|
95
|
+
* `timed_out` is spelled with an underscore, deliberately and once: it crosses
|
|
96
|
+
* a wire protocol as a literal, so the spelling is contract rather than style.
|
|
97
|
+
*/
|
|
98
|
+
export const RESULT_STATES = ["ok", "empty", "refused", "failed", "timed_out"];
|
|
99
|
+
export function isResultState(value) {
|
|
100
|
+
return RESULT_STATES.includes(value);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* DEC-278 — the three-way split that replaced §3's rule 4 (*"read tools are
|
|
104
|
+
* pure and retryable; action tools are neither"*).
|
|
105
|
+
*
|
|
106
|
+
* | Class | Handshake |
|
|
107
|
+
* | --- | --- |
|
|
108
|
+
* | `read` | No. Pure, retryable. |
|
|
109
|
+
* | `stateful-read` | No. Mutates Descry's own derived state only; idempotent in effect. |
|
|
110
|
+
* | `action` | **Yes** — the two-call confirmation-token handshake. |
|
|
111
|
+
*
|
|
112
|
+
* **The line is not "does it write bytes."** It is *"can its effect change a
|
|
113
|
+
* later finding without the developer having said so."* Re-deriving a graph
|
|
114
|
+
* from code already on disk, or recording where that code is, cannot introduce
|
|
115
|
+
* a claim the repository does not already contain — both write, and neither
|
|
116
|
+
* can move a finding. Recording a person's confirmed value for a
|
|
117
|
+
* refusal-ledger row can: it becomes a graph input, it feeds `humanAsserted`,
|
|
118
|
+
* and DEC-223 caps it at reliability class B precisely because it rests on one
|
|
119
|
+
* unaudited assertion. Only that third kind takes the handshake.
|
|
120
|
+
*
|
|
121
|
+
* Gating all three was considered and rejected as consistent-but-unusable: a
|
|
122
|
+
* client that must confirm before it may build a graph cannot answer the first
|
|
123
|
+
* question asked of it.
|
|
124
|
+
*
|
|
125
|
+
* `stateful-read` needs its own contract test wherever these are enforced —
|
|
126
|
+
* pure-retryable assertions do not apply to it and action-gate assertions must
|
|
127
|
+
* not.
|
|
128
|
+
*/
|
|
129
|
+
export const TOOL_CLASSES = ["read", "stateful-read", "action"];
|
|
130
|
+
export function isToolClass(value) {
|
|
131
|
+
return TOOL_CLASSES.includes(value);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=tool-surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-surface.js","sourceRoot":"","sources":["../src/tool-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAU,CAAC;AAIxF,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAQ,aAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,QAAQ,CAAU,CAAC;AAIzE,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAQ,YAAkC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The canonical graph vocabulary: 15 node types, 15 edge types.
|
|
3
|
+
*
|
|
4
|
+
* FROZEN. See DEC-003. Adding a type multiplies traversal, ranking, storage and
|
|
5
|
+
* governance work — new capabilities are new *queries* over these edges, not new
|
|
6
|
+
* types. Extending either list requires a decision entry in DECISIONS.md, and the
|
|
7
|
+
* arity tests in test/vocabulary.test.ts will fail until the counts there are
|
|
8
|
+
* deliberately updated, which makes the change visible in review.
|
|
9
|
+
*
|
|
10
|
+
* Declared as `as const` arrays with derived unions rather than TS enums:
|
|
11
|
+
* enums are not erasable syntax and Node's type stripping cannot run them
|
|
12
|
+
* (tsconfig `erasableSyntaxOnly` enforces this).
|
|
13
|
+
*/
|
|
14
|
+
export declare const NODE_TYPES: readonly ["FILE", "FUNCTION", "CLASS", "MODULE", "API_ENDPOINT", "API_ROUTE", "DATABASE_TABLE", "DATABASE_COLUMN", "MODEL", "DTO", "COMPONENT", "PAGE", "TEST_CASE", "INCIDENT", "FIX_PATTERN"];
|
|
15
|
+
export declare const EDGE_TYPES: readonly ["CALLS", "IMPORTS", "READS", "WRITES", "RETURNS", "IMPLEMENTS", "INHERITS", "USES_API", "SERVES_API", "USES_TYPE", "PROPAGATES_TO", "TESTS", "FIXED_BY", "CHANGES_WITH", "INCIDENT_CORRELATED"];
|
|
16
|
+
export type NodeType = (typeof NODE_TYPES)[number];
|
|
17
|
+
export type EdgeType = (typeof EDGE_TYPES)[number];
|
|
18
|
+
export declare function isNodeType(value: string): value is NodeType;
|
|
19
|
+
export declare function isEdgeType(value: string): value is EdgeType;
|
|
20
|
+
/**
|
|
21
|
+
* Node types that have no source file and no line range.
|
|
22
|
+
*
|
|
23
|
+
* `API_ENDPOINT` is the cross-language join node — it is written by two adapters
|
|
24
|
+
* that never share a line of code, so it belongs to neither file. `INCIDENT` and
|
|
25
|
+
* `FIX_PATTERN` come from git history rather than from source.
|
|
26
|
+
*
|
|
27
|
+
* See DEC-014: architecture §11A.4 typed `file` and `range` as required, which
|
|
28
|
+
* made the join node unrepresentable.
|
|
29
|
+
*/
|
|
30
|
+
export declare const FILELESS_NODE_TYPES: readonly ["API_ENDPOINT", "INCIDENT", "FIX_PATTERN"];
|
|
31
|
+
export declare function isFilelessNodeType(type: NodeType): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Node types that are a **declared type** — something a reference can name and a
|
|
34
|
+
* value can be an instance of.
|
|
35
|
+
*
|
|
36
|
+
* `MODEL` and `DTO` are not alternatives to `CLASS`; they are a `CLASS` that a
|
|
37
|
+
* framework extractor found extra evidence about. An ORM model is still a type:
|
|
38
|
+
* it is still imported, still named in annotations, still inherited from, still
|
|
39
|
+
* returned. The extra evidence is a persistence mapping or a transport boundary,
|
|
40
|
+
* and it changes what the node *means*, not what it *is*.
|
|
41
|
+
*
|
|
42
|
+
* This predicate exists because every adapter writes `type === "CLASS"` to ask
|
|
43
|
+
* "is this a type?", and there were twenty-one such sites across two adapters
|
|
44
|
+
* before the first framework extractor landed. Promoting one class to `MODEL`
|
|
45
|
+
* silently withdrew its `USES_TYPE`, `INHERITS` and `RETURNS` edges at every one
|
|
46
|
+
* of them — a recall collapse with no error, no rejection and no ledger row,
|
|
47
|
+
* which is the failure mode rule 7 exists to forbid.
|
|
48
|
+
*
|
|
49
|
+
* It is a query over the frozen vocabulary, not an extension of it. See DEC-093.
|
|
50
|
+
*/
|
|
51
|
+
export declare const TYPE_LIKE_NODE_TYPES: readonly ["CLASS", "MODEL", "DTO"];
|
|
52
|
+
export declare function isTypeLikeNodeType(type: NodeType): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Node types that are a **callable declaration** — something a call site can
|
|
55
|
+
* reach and a call graph can traverse.
|
|
56
|
+
*
|
|
57
|
+
* The same relationship `TYPE_LIKE_NODE_TYPES` describes, one row down. A React
|
|
58
|
+
* component is a function that a framework calls; `<OrderPage />` is a call in
|
|
59
|
+
* every sense a call graph cares about, which is the argument this codebase
|
|
60
|
+
* already made when it decided `post = (…) => …` is a method. `PAGE` is a
|
|
61
|
+
* component with a route attached and is callable for the same reason.
|
|
62
|
+
*
|
|
63
|
+
* `TEST_CASE` is deliberately absent. It is callable, but every site that
|
|
64
|
+
* distinguishes it does so because a call *inside* a test is coverage rather
|
|
65
|
+
* than a call-graph edge — folding it in here would erase that distinction at
|
|
66
|
+
* exactly the sites that exist to make it.
|
|
67
|
+
*
|
|
68
|
+
* See DEC-093, and the note there about what promotion costs when a kind check
|
|
69
|
+
* is written as an equality.
|
|
70
|
+
*/
|
|
71
|
+
export declare const CALLABLE_NODE_TYPES: readonly ["FUNCTION", "COMPONENT", "PAGE"];
|
|
72
|
+
export declare function isCallableNodeType(type: NodeType): boolean;
|
|
73
|
+
//# sourceMappingURL=vocabulary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vocabulary.d.ts","sourceRoot":"","sources":["../src/vocabulary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,UAAU,iMAgBb,CAAC;AAEX,eAAO,MAAM,UAAU,2MA4Cb,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AACnD,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAKnD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,sDAIQ,CAAC;AAIzC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAE1D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,oBAAoB,oCAAmE,CAAC;AAIrG,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAE1D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,mBAAmB,4CAA2E,CAAC;AAI5G,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAE1D"}
|