@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.
Files changed (94) hide show
  1. package/LICENSE +21 -0
  2. package/dist/capabilities.d.ts +83 -0
  3. package/dist/capabilities.d.ts.map +1 -0
  4. package/dist/capabilities.js +91 -0
  5. package/dist/capabilities.js.map +1 -0
  6. package/dist/conformance/bind.d.ts +82 -0
  7. package/dist/conformance/bind.d.ts.map +1 -0
  8. package/dist/conformance/bind.js +157 -0
  9. package/dist/conformance/bind.js.map +1 -0
  10. package/dist/conformance/cli.d.ts +25 -0
  11. package/dist/conformance/cli.d.ts.map +1 -0
  12. package/dist/conformance/cli.js +137 -0
  13. package/dist/conformance/cli.js.map +1 -0
  14. package/dist/conformance/compare.d.ts +74 -0
  15. package/dist/conformance/compare.d.ts.map +1 -0
  16. package/dist/conformance/compare.js +140 -0
  17. package/dist/conformance/compare.js.map +1 -0
  18. package/dist/conformance/compose.d.ts +79 -0
  19. package/dist/conformance/compose.d.ts.map +1 -0
  20. package/dist/conformance/compose.js +167 -0
  21. package/dist/conformance/compose.js.map +1 -0
  22. package/dist/conformance/golden.d.ts +110 -0
  23. package/dist/conformance/golden.d.ts.map +1 -0
  24. package/dist/conformance/golden.js +252 -0
  25. package/dist/conformance/golden.js.map +1 -0
  26. package/dist/conformance/index.d.ts +26 -0
  27. package/dist/conformance/index.d.ts.map +1 -0
  28. package/dist/conformance/index.js +18 -0
  29. package/dist/conformance/index.js.map +1 -0
  30. package/dist/conformance/manifest-check.d.ts +78 -0
  31. package/dist/conformance/manifest-check.d.ts.map +1 -0
  32. package/dist/conformance/manifest-check.js +149 -0
  33. package/dist/conformance/manifest-check.js.map +1 -0
  34. package/dist/conformance/manifest.d.ts +83 -0
  35. package/dist/conformance/manifest.d.ts.map +1 -0
  36. package/dist/conformance/manifest.js +158 -0
  37. package/dist/conformance/manifest.js.map +1 -0
  38. package/dist/conformance/report.d.ts +14 -0
  39. package/dist/conformance/report.d.ts.map +1 -0
  40. package/dist/conformance/report.js +87 -0
  41. package/dist/conformance/report.js.map +1 -0
  42. package/dist/conformance/run.d.ts +172 -0
  43. package/dist/conformance/run.d.ts.map +1 -0
  44. package/dist/conformance/run.js +626 -0
  45. package/dist/conformance/run.js.map +1 -0
  46. package/dist/contracts.d.ts +198 -0
  47. package/dist/contracts.d.ts.map +1 -0
  48. package/dist/contracts.js +10 -0
  49. package/dist/contracts.js.map +1 -0
  50. package/dist/contradiction.d.ts +112 -0
  51. package/dist/contradiction.d.ts.map +1 -0
  52. package/dist/contradiction.js +97 -0
  53. package/dist/contradiction.js.map +1 -0
  54. package/dist/finding.d.ts +567 -0
  55. package/dist/finding.d.ts.map +1 -0
  56. package/dist/finding.js +491 -0
  57. package/dist/finding.js.map +1 -0
  58. package/dist/hypothesis.d.ts +130 -0
  59. package/dist/hypothesis.d.ts.map +1 -0
  60. package/dist/hypothesis.js +116 -0
  61. package/dist/hypothesis.js.map +1 -0
  62. package/dist/identity.d.ts +295 -0
  63. package/dist/identity.d.ts.map +1 -0
  64. package/dist/identity.js +404 -0
  65. package/dist/identity.js.map +1 -0
  66. package/dist/index.d.ts +34 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +21 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/ir.d.ts +360 -0
  71. package/dist/ir.d.ts.map +1 -0
  72. package/dist/ir.js +76 -0
  73. package/dist/ir.js.map +1 -0
  74. package/dist/model-tables.d.ts +111 -0
  75. package/dist/model-tables.d.ts.map +1 -0
  76. package/dist/model-tables.js +103 -0
  77. package/dist/model-tables.js.map +1 -0
  78. package/dist/normalise.d.ts +114 -0
  79. package/dist/normalise.d.ts.map +1 -0
  80. package/dist/normalise.js +603 -0
  81. package/dist/normalise.js.map +1 -0
  82. package/dist/reliability.d.ts +89 -0
  83. package/dist/reliability.d.ts.map +1 -0
  84. package/dist/reliability.js +181 -0
  85. package/dist/reliability.js.map +1 -0
  86. package/dist/tool-surface.d.ts +131 -0
  87. package/dist/tool-surface.d.ts.map +1 -0
  88. package/dist/tool-surface.js +133 -0
  89. package/dist/tool-surface.js.map +1 -0
  90. package/dist/vocabulary.d.ts +73 -0
  91. package/dist/vocabulary.d.ts.map +1 -0
  92. package/dist/vocabulary.js +150 -0
  93. package/dist/vocabulary.js.map +1 -0
  94. 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"}