@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,567 @@
1
+ /**
2
+ * The shared finding record, and G3/G4 — the gates that decide what may be
3
+ * called what.
4
+ *
5
+ * `documents/architecture/descry-ai-layer.md` §20 is canonical for the type:
6
+ * **fourteen fields, no more and no fewer.** §42 carries a fifteenth,
7
+ * `Hypotheses considered`, which belongs to the output a developer reads and
8
+ * not to the stored record; it is deliberately absent here. DEC-276's own prose
9
+ * says *"eleven fields are extended to thirteen"* — eleven plus three is
10
+ * fourteen, and §20 corrects the arithmetic while keeping the field list the
11
+ * decision actually produced.
12
+ *
13
+ * It lives in `@descryy/ir` because two repositories construct and assert
14
+ * against it — the pipeline that produces findings and the golden-report test
15
+ * that checks all fourteen render — and both plans put it here specifically so
16
+ * that a divergence is a compile error rather than a field quietly missing from
17
+ * a page.
18
+ *
19
+ * ## Five axes, and they are not interchangeable
20
+ *
21
+ * A finding says five separate things, and collapsing any pair of them loses a
22
+ * distinction the product exists to make:
23
+ *
24
+ * - **Confidence** — how sure we are (§19's five categories).
25
+ * - **Fault layer** — whose problem it is (DEC-273). A finding can be
26
+ * `confirmed` and `environment` at once: fully proven, and not the
27
+ * application's fault.
28
+ * - **Reliability class** — how certain the *category* of claim is (§15.2).
29
+ * - **Resolution level** — how well the *code was understood* (§11A.6).
30
+ * - **Environment level** — how faithful the environment that produced it was
31
+ * (architecture §16.3).
32
+ *
33
+ * **Coverage is a sixth thing and not a confidence value.** §19's adopted note
34
+ * moved untested scope out of the category list and into `Verification status`
35
+ * deliberately: *"we found nothing"* and *"we did not look"* are different
36
+ * statements, and the precision-over-recall rule is only defensible while the
37
+ * second one has an honest home.
38
+ */
39
+ import type { ReliabilityClass } from "./reliability.ts";
40
+ import type { ResolutionLevel } from "./ir.ts";
41
+ import type { EdgeType } from "./vocabulary.ts";
42
+ /**
43
+ * A value that may only be produced by the function that derives it.
44
+ *
45
+ * §20 says `Reliability class` and `Resolution level` are *"derived, never
46
+ * authored"*, and a doc comment saying so is not a mechanism. The brand makes
47
+ * the sentence hold in the type system: a bare `"A"` is not assignable to
48
+ * `Derived<ReliabilityClass>`, so the only way to fill either field is to call
49
+ * the function that computes it.
50
+ *
51
+ * A brand rather than an opaque class because these values still have to
52
+ * compare, switch and serialize as the plain `"A"` / `4` they are. Nothing at
53
+ * runtime carries the property — it exists only to make the assignment fail.
54
+ */
55
+ export interface DerivationBrand {
56
+ /**
57
+ * Never present at runtime, and typed `never` so it cannot be satisfied by
58
+ * writing it out. The only routes to a branded value are the derivations
59
+ * below and {@link rederive}, the read-path re-derivation from a stored
60
+ * {@link FindingRecord}.
61
+ */
62
+ readonly derivedNotAuthored: never;
63
+ }
64
+ export type Derived<T> = T & DerivationBrand;
65
+ /**
66
+ * §19's five, adopted as superseding the architecture's previous four.
67
+ *
68
+ * `not analysable` and `unsupported` are refusals rather than readings of
69
+ * evidence — *"we cannot establish this here"* and *"we do not do this at
70
+ * all"* — and G4 below does not produce them; they are inherited from the
71
+ * static case unchanged.
72
+ */
73
+ export declare const REPORT_CATEGORIES: readonly ["confirmed", "strongly supported", "unconfirmed", "not analysable", "unsupported"];
74
+ export type ReportCategory = (typeof REPORT_CATEGORIES)[number];
75
+ /**
76
+ * The three of the five that G4's step 2 can return, ordered strongest first.
77
+ *
78
+ * A narrower return type than {@link ReportCategory} on purpose: the gate reads
79
+ * evidence, and no amount of evidence turns into *"we cannot analyse this"*.
80
+ */
81
+ export declare const EVIDENCE_CATEGORIES: readonly ["confirmed", "strongly supported", "unconfirmed"];
82
+ export type EvidenceCategory = (typeof EVIDENCE_CATEGORIES)[number];
83
+ /**
84
+ * DEC-273 — a second axis beside confidence, never a sixth category.
85
+ *
86
+ * Confidence asks *how sure are we*; fault layer asks *whose problem is this*.
87
+ * They are independent, and a finding is not more or less true for being an
88
+ * environment fault — it is attributable to a different owner.
89
+ *
90
+ * **Classification heuristics remain deliberately unspecified for `product`,
91
+ * and for the no-comparison-available fallback on `environment`/`dependency`.**
92
+ * DEC-273 rests on three real classifications, and three is not enough to
93
+ * generalize a pattern-match rule from — `descry-ai-layer.md` §20's own
94
+ * caution, unchanged by the ruling below. **`automation`, `dependency` and
95
+ * `environment` are the three exceptions** — see {@link classifyFaultLayer}.
96
+ * None of the three is a heuristic in the sense being deferred: each is a
97
+ * structural comparison a tool either reports or does not (a harness
98
+ * self-failure flag, a declared-vs-resolved dependency version, a
99
+ * declared-vs-observed runner version), not a pattern inferred from few
100
+ * examples. `automation` was unblocked 2026-08-24 by `descry-runtime`'s
101
+ * RT-219 self-observability channel; `dependency`/`environment`'s structural
102
+ * comparison is ruled in
103
+ * `DEC-NEXT-fault-layer-empirical-confirmation.md`, which also requires every
104
+ * classification to carry its own confidence marker — see
105
+ * {@link faultLayerConfidence}.
106
+ */
107
+ export declare const FAULT_LAYERS: readonly ["product", "automation", "environment", "dependency", "unknown"];
108
+ export type FaultLayer = (typeof FAULT_LAYERS)[number];
109
+ /**
110
+ * `DEC-NEXT-fault-layer-empirical-confirmation.md` — whether a fault-layer
111
+ * value rests on a structural comparison/rerun or a pattern-match with no
112
+ * comparison available. See {@link faultLayerConfidence}.
113
+ */
114
+ export declare const FAULT_LAYER_CONFIDENCES: readonly ["structural", "heuristic"];
115
+ export type FaultLayerConfidence = (typeof FAULT_LAYER_CONFIDENCES)[number];
116
+ /**
117
+ * Architecture §16.3's fidelity levels — how real the environment that produced
118
+ * the finding was. Emitted on every finding as `Validated Against: Level N`.
119
+ *
120
+ * 1 stub · 2 real code + disposable seeded database (the preferred default) ·
121
+ * 3 real code + redacted production-shaped recordings · 4 real staging.
122
+ * Selection prefers the highest available, 4 → 1.
123
+ */
124
+ export declare const ENVIRONMENT_LEVELS: readonly [1, 2, 3, 4];
125
+ export type EnvironmentLevel = (typeof ENVIRONMENT_LEVELS)[number];
126
+ /**
127
+ * The six independent observation channels, closed list —
128
+ * `ai-governance-spec.md` §5.2, ruled 2026-08-24 in
129
+ * `DEC-NEXT-independent-signal-type-inventory.md`, superseding DEC-276's
130
+ * original four.
131
+ *
132
+ * *"Two log lines are one signal type."* `E` counts **channels**, not
133
+ * observations, which is why {@link independentSignalTypes} derives it rather
134
+ * than trusting a caller's count.
135
+ *
136
+ * **Not a raw count over `descry-runtime`'s twenty-two runtime event types.**
137
+ * Each channel folds in the event types that belong to it (the full mapping
138
+ * is the spec's own table). `TEST_FAILED` — one of the four previously-open
139
+ * types — is deliberately **not** a seventh channel: its evidentiary weight
140
+ * belongs to `M` alone (see {@link directMechanismEvidence}), and counting it
141
+ * as one more corroborating channel would route a reproduced failure through
142
+ * the strictly weaker `E >= 1` path when it already qualifies for `M`'s
143
+ * direct path. `COLLECTOR_ERROR` and every harness-action type
144
+ * (`PROCESS_STARTED`, `NAVIGATION`, `CLICK`, ...) are excluded by name — they
145
+ * record that the observer failed, or what Descry did, never what the system
146
+ * under test did.
147
+ *
148
+ * **This list is deliberately narrow, and widening it must stay a compile
149
+ * error.** A new collector arriving quietly and re-tuning every confidence
150
+ * boundary with nothing failing is the exact defect the result-state enum next
151
+ * door exists to prevent, one level up. Typing `E` as a bare `number` would
152
+ * "fix" the friction by removing the alarm. An unrecognised event type must
153
+ * fail closed — {@link RuntimeEvidence.signal} of `null` — until this table is
154
+ * extended by the same process that built it.
155
+ */
156
+ export declare const RUNTIME_SIGNAL_TYPES: readonly ["browser-visual", "browser-console", "network", "backend-log", "database", "external-service"];
157
+ export type RuntimeSignalType = (typeof RUNTIME_SIGNAL_TYPES)[number];
158
+ /**
159
+ * Legal values of `E`. Bounded by the six channels above, hence 0–6.
160
+ */
161
+ export declare const SIGNAL_TYPE_COUNTS: readonly [0, 1, 2, 3, 4, 5, 6];
162
+ export type SignalTypeCount = (typeof SIGNAL_TYPE_COUNTS)[number];
163
+ /**
164
+ * One runtime observation.
165
+ *
166
+ * `signal` names which of the six {@link RUNTIME_SIGNAL_TYPES} channels this
167
+ * belongs to, or `null` when the record is excluded from `E` by design — a
168
+ * reproduced test failure (whose evidentiary weight is
169
+ * {@link directMechanismEvidence}'s alone, never double-counted as a channel
170
+ * too), a collector error, a harness action, or any type this table has not
171
+ * ruled on yet. `nodeId`/`directMechanism` are what
172
+ * {@link directMechanismEvidence} reads to compute `M` — both optional and
173
+ * absent by default, so a record making no mechanism claim says nothing
174
+ * rather than false.
175
+ */
176
+ export interface RuntimeEvidence {
177
+ readonly signal: RuntimeSignalType | null;
178
+ /** What was observed, in the collector's own words. Never summarised here. */
179
+ readonly detail: string;
180
+ /**
181
+ * The graph node id this observation resolves to, if any — `hash(repo,
182
+ * kind, qualified symbol path)`, never a file path, so the match survives a
183
+ * rename the way a path comparison would not.
184
+ */
185
+ readonly nodeId?: string | null;
186
+ /**
187
+ * `true` when this record's own event type directly enacts the claimed
188
+ * failure mode at `nodeId` — not merely co-occurs with it in time.
189
+ * `ai-governance-spec.md` §5.3's three cases: a reproduced test failure
190
+ * whose assertion/stack frame resolves there, an exception or backend-log
191
+ * line whose stack frame resolves there, or a network response matching the
192
+ * predicted defect on the exact route the hypothesis names.
193
+ */
194
+ readonly directMechanism?: boolean;
195
+ /**
196
+ * `true` when this record is Descry's own harness observing itself fail —
197
+ * `descry-runtime` RT-219's `source: "harness"` channel — rather than an
198
+ * observation of the application under test. Independent of `signal`,
199
+ * which stays `null` here for the same reason it is `null` for
200
+ * `COLLECTOR_ERROR`/harness-action records: this is not one of the six
201
+ * domain channels and must not inflate `E`. Feeds {@link classifyFaultLayer}
202
+ * alone. Optional and absent by default, so an ordinary domain record says
203
+ * nothing.
204
+ */
205
+ readonly harnessFailure?: boolean;
206
+ /**
207
+ * `true` when this record is a structural comparison finding the lockfile's
208
+ * declared dependency version does not match the version actually resolved
209
+ * at runtime — `DEC-NEXT-fault-layer-empirical-confirmation.md`'s
210
+ * `dependency` mechanism. Same shape as `harnessFailure`: independent of
211
+ * `signal` (stays `null` here, not one of the six domain channels), never
212
+ * inflates `E`, feeds {@link classifyFaultLayer} alone. Optional and absent
213
+ * by default.
214
+ */
215
+ readonly dependencyVersionMismatch?: boolean;
216
+ /**
217
+ * `true` when this record is a structural comparison finding the declared
218
+ * (CI-configured) runner version does not match the version observed at
219
+ * execution — the same ruling's `environment` mechanism. Same shape and
220
+ * exclusions as `dependencyVersionMismatch`.
221
+ */
222
+ readonly environmentVersionMismatch?: boolean;
223
+ }
224
+ /**
225
+ * One hop of the structural path a finding rests on.
226
+ *
227
+ * Carries its own `resolution` because rule 3's cap is a property of the
228
+ * *weakest* hop, and a path that reports only an aggregate cannot be audited
229
+ * for which hop cost it the class.
230
+ */
231
+ export interface GraphPathHop {
232
+ /** Source node ID — `hash(repo, kind, qualified symbol path)`, never a path. */
233
+ readonly from: string;
234
+ /** Target node ID. */
235
+ readonly to: string;
236
+ readonly edgeType: EdgeType;
237
+ /** How well this one hop was resolved, R0–R4. */
238
+ readonly resolution: ResolutionLevel;
239
+ /**
240
+ * DEC-223 — this edge exists because a person confirmed a value for a
241
+ * refusal-ledger row, not because analysis resolved it. Optional and
242
+ * defaulting to absent, so an ordinary structural hop says nothing.
243
+ */
244
+ readonly humanAsserted?: boolean;
245
+ }
246
+ /** One thing in scope that was not exercised, and why. */
247
+ export interface UntestedScope {
248
+ readonly scope: string;
249
+ /**
250
+ * Named and verbatim. An untested item with no reason is the silence this
251
+ * whole field exists to prevent — rule 7 at the level of a single record.
252
+ */
253
+ readonly reason: string;
254
+ }
255
+ /**
256
+ * Coverage — a different axis from confidence, and the carrier of the
257
+ * untested-scope disclosure since §19's five categories dropped *not tested*.
258
+ *
259
+ * The documents name this field and describe what it must report — *what was in
260
+ * scope, what was actually exercised, and what was not, with a reason for each
261
+ * gap* — without enumerating a set of status values. Modelled as that
262
+ * structure rather than as an invented three-word vocabulary, because a label
263
+ * like *"partially verified"* answers none of the three questions.
264
+ */
265
+ export interface VerificationStatus {
266
+ /**
267
+ * What this finding's claim was actually exercised against. An empty list is
268
+ * a legal, meaningful answer — *nothing was exercised* — and is not the same
269
+ * as an unknown one.
270
+ */
271
+ readonly exercised: readonly string[];
272
+ /** Every part of the scope that was not exercised, each with its reason. */
273
+ readonly notExercised: readonly UntestedScope[];
274
+ }
275
+ /**
276
+ * §20's fourteen fields, in §20's order.
277
+ *
278
+ * Exported so the golden-report test can iterate the canonical list rather than
279
+ * restate it — the desktop plan's test previously asserted eleven fields and
280
+ * would have passed green while two axes vanished from the product. A list
281
+ * asserted against `Object.keys` of a real finding is what makes that a
282
+ * failure instead of a silence.
283
+ */
284
+ export declare const FINDING_FIELDS: readonly ["finding", "scope", "affectedComponents", "evidence", "graphPath", "runtimeEvidence", "relevantChange", "confidence", "faultLayer", "reliabilityClass", "resolutionLevel", "environmentLevel", "recommendedAction", "verificationStatus"];
285
+ export type FindingField = (typeof FINDING_FIELDS)[number];
286
+ /** §20's finding record. Fourteen fields; see the module doc for why not fifteen. */
287
+ export interface Finding {
288
+ /** The claim itself, one statement. */
289
+ readonly finding: string;
290
+ /** What was being checked when this surfaced. */
291
+ readonly scope: string;
292
+ /**
293
+ * Node IDs, not display names — identity is `hash(repo, kind, qualified
294
+ * symbol path)` and survives renames, which a display name does not. The
295
+ * renderer resolves them for presentation.
296
+ */
297
+ readonly affectedComponents: readonly string[];
298
+ /** The enumerated grounds for the claim, static and observed alike. */
299
+ readonly evidence: readonly string[];
300
+ /** The structural path, hop by hop. Feeds {@link minimumResolution}. */
301
+ readonly graphPath: readonly GraphPathHop[];
302
+ /**
303
+ * Observations from the six channels, plus any direct-mechanism-only
304
+ * records (e.g. a reproduced test failure). Feeds
305
+ * {@link independentSignalTypes} and {@link directMechanismEvidence}.
306
+ */
307
+ readonly runtimeEvidence: readonly RuntimeEvidence[];
308
+ /**
309
+ * The change implicated, if one is. `null` means *no change is implicated*,
310
+ * which is a finding about existing code — not *"we did not check"*, which
311
+ * belongs in {@link VerificationStatus}.
312
+ */
313
+ readonly relevantChange: string | null;
314
+ /** §19's category, computed at G4 and capped by `reliabilityClass`. */
315
+ readonly confidence: ReportCategory;
316
+ /** DEC-273's axis. Independent of `confidence`. */
317
+ readonly faultLayer: FaultLayer;
318
+ /** Derived — {@link reportCategory}, which calls `reliabilityCap()`. */
319
+ readonly reliabilityClass: Derived<ReliabilityClass>;
320
+ /** Derived — {@link minimumResolution} over `graphPath`. */
321
+ readonly resolutionLevel: Derived<ResolutionLevel>;
322
+ /** Architecture §16.3. Authored: it is a fact about the run, not the claim. */
323
+ readonly environmentLevel: EnvironmentLevel;
324
+ readonly recommendedAction: string;
325
+ /** Coverage. A separate axis; see {@link VerificationStatus}. */
326
+ readonly verificationStatus: VerificationStatus;
327
+ }
328
+ /**
329
+ * `E` — how many of the six channels named this finding, counting
330
+ * **channels** rather than observations, and ignoring any record whose
331
+ * `signal` is `null` (excluded by design — see {@link RuntimeEvidence}).
332
+ */
333
+ export declare function independentSignalTypes(evidence: readonly RuntimeEvidence[]): SignalTypeCount;
334
+ /**
335
+ * `M` — direct mechanism evidence, `ai-governance-spec.md` §5.3. `true` when
336
+ * at least one runtime evidence record's resolved graph node id equals
337
+ * `failurePoint` — the hypothesis's named failure site — and that record is
338
+ * itself marked {@link RuntimeEvidence.directMechanism}, not merely
339
+ * co-occurring with the failure in time.
340
+ *
341
+ * A plain node-id match, the same identity mechanism §10 already requires for
342
+ * graph/runtime contradiction detection — deterministic, never a model
343
+ * judgement, which is what makes it a gate input rather than a slot output.
344
+ */
345
+ export declare function directMechanismEvidence(evidence: readonly RuntimeEvidence[], failurePoint: string): boolean;
346
+ /**
347
+ * `G3` — the evidence precondition, `ai-governance-spec.md` §4. `true` iff at
348
+ * least one runtime evidence record exists at all for this hypothesis,
349
+ * however it classifies under `E`/`M`. Restated from `root-cause-score.ts`'s
350
+ * own module doc: `RuntimeEvidence > 0` is a precondition on promotion above
351
+ * `unconfirmed`, never an addend folded into {@link reportCategory}'s step 2
352
+ * arithmetic.
353
+ */
354
+ export declare function evidencePrecondition(evidence: readonly RuntimeEvidence[]): boolean;
355
+ /**
356
+ * P11 — `ai-layer-plan.md` §11, `ai-governance-spec.md` §7. DEC-273's fault
357
+ * layer, computed rather than authored, for the one value that is currently
358
+ * groundable: {@link RuntimeEvidence.harnessFailure} is a structural fact
359
+ * (`descry-runtime` RT-219's self-observability channel either reported the
360
+ * harness dying or it did not) rather than a pattern inferred from a small
361
+ * number of examples, so classifying `"automation"` from it is not the kind
362
+ * of heuristic {@link FAULT_LAYERS}'s doc defers.
363
+ *
364
+ * **`product` / `environment` / `dependency` are deliberately not
365
+ * classified here.** No mechanism this codebase has built yet can positively
366
+ * distinguish them from evidence alone, and DEC-273's own three real
367
+ * classifications are explicitly too few to generalize a rule from. Every
368
+ * finding that is not an `automation` case is `"unknown"` — the honest
369
+ * default, not a placeholder for a missing case.
370
+ *
371
+ * A harness failure classifies `"automation"` even when domain evidence is
372
+ * also present: a collector that died mid-run can leave partial application
373
+ * evidence behind, and that evidence does not make the underlying failure
374
+ * any less Descry's own.
375
+ */
376
+ export declare function classifyFaultLayer(evidence: readonly RuntimeEvidence[]): FaultLayer;
377
+ /**
378
+ * DEC-NEXT-fault-layer-empirical-confirmation.md — every fault-layer value
379
+ * carries its own confidence marker, independent of the finding's
380
+ * `Confidence`: `structural` (a comparison or rerun confirmed it) vs.
381
+ * `heuristic` (pattern-matched, no comparison run). *"A bare `environment` or
382
+ * `dependency` label must never be presented at the same visual weight as a
383
+ * `confirmed` finding unless it earned `structural`."*
384
+ *
385
+ * **Every path {@link classifyFaultLayer} can produce today is `structural`.**
386
+ * `product`'s heuristic and the no-comparison-available fallback for
387
+ * `dependency`/`environment` are the ones the ruling explicitly defers
388
+ * (`descry-ai-layer.md` §20's caution against generalizing from three
389
+ * classifications) and are not built — `heuristic` is reserved for whichever
390
+ * future function writes that fallback, not returned by anything here.
391
+ */
392
+ export declare function faultLayerConfidence(_layer: FaultLayer): FaultLayerConfidence;
393
+ /**
394
+ * `R` — the **minimum** resolution across the path.
395
+ *
396
+ * Minimum rather than average, first or last, and that single choice is what
397
+ * makes NOTE-4's control #6 (*a five-hop path inherits its worst hop's cap*)
398
+ * true by construction rather than by a second rule that could disagree.
399
+ *
400
+ * **An empty path derives R0**, the conservative floor: no hop resolved
401
+ * anything, so nothing above R0 has been established, and rule 2 says omit
402
+ * rather than overstate. Whether a purely runtime-observed finding should
403
+ * instead carry a synthetic R4 hop — so that a symptom confirmed on two
404
+ * channels is not capped to `unconfirmed` for having no traced cause — is a
405
+ * real question and is **not** decided here; filed as
406
+ * `documents/decisions-inbox/DEC-NEXT-empty-graph-path-resolution-floor.md`.
407
+ */
408
+ export declare function minimumResolution(path: readonly GraphPathHop[]): Derived<ResolutionLevel>;
409
+ /**
410
+ * `H` — testimony anywhere under the finding.
411
+ *
412
+ * Any load-bearing hop is enough: DEC-223's cap is not diluted by the number of
413
+ * honest hops beside it, because one unaudited assertion is one unaudited
414
+ * assertion however much resolved structure surrounds it.
415
+ */
416
+ export declare function humanAssertedOnPath(path: readonly GraphPathHop[]): boolean;
417
+ /**
418
+ * G3's precondition plus G4's four inputs — and, wrapped in
419
+ * {@link FindingRecord}, the derivation record a finding is stored with.
420
+ *
421
+ * Recording these beside the finding is what `documents/plans/ai-layer-plan.md`
422
+ * §12's *"replay must reproduce the finding exactly"* requires, and it is also
423
+ * what lets a stored finding's derived axes be re-derived through
424
+ * {@link rederive} rather than restored by cast.
425
+ */
426
+ export interface G4Inputs {
427
+ /**
428
+ * G3 — {@link evidencePrecondition} over the runtime evidence. `false`
429
+ * means step 2/3 below never run and the category is `unconfirmed`
430
+ * unconditionally, regardless of what `independentSignalTypes` or
431
+ * `directMechanismEvidence` claim.
432
+ */
433
+ readonly hasRuntimeEvidence: boolean;
434
+ /** `E` — {@link independentSignalTypes} over the runtime evidence, 0–6. */
435
+ readonly independentSignalTypes: SignalTypeCount;
436
+ /** `M` — {@link directMechanismEvidence} over the runtime evidence. */
437
+ readonly directMechanismEvidence: boolean;
438
+ /** `R` — {@link minimumResolution} over the graph path. */
439
+ readonly resolution: ResolutionLevel;
440
+ /** `N` — the claim is about a name, not a shape. See `reliabilityCap`. */
441
+ readonly nameLevel: boolean;
442
+ /** `H` — {@link humanAssertedOnPath} over the graph path. */
443
+ readonly humanAsserted: boolean;
444
+ }
445
+ /** G4's answer: both coupled values, from one call. */
446
+ export interface G4Result {
447
+ /** The category the finding may be reported as, after the cap. */
448
+ readonly category: EvidenceCategory;
449
+ /**
450
+ * The class that capped it. Returned rather than left to the caller to
451
+ * recompute — the defect DEC-276 named in the previous G4 was rule 3 living
452
+ * in two places with nothing tying them together, and two call sites is two
453
+ * places.
454
+ */
455
+ readonly reliabilityClass: Derived<ReliabilityClass>;
456
+ }
457
+ /**
458
+ * **G3 + G4 — the evidence precondition and the category gate.**
459
+ * `ai-governance-spec.md` §4–§5, stage 14 of the V1 loop. G3 fires first; G4
460
+ * is three steps.
461
+ *
462
+ * ```
463
+ * G3 no runtime evidence at all -> unconfirmed, steps 1-3 below never run
464
+ * step 1 class = reliabilityCap(R, N, H) -> "A" | "B" | "C"
465
+ * step 2 M -> confirmed | !M && E >= 1 -> strongly supported | E == 0 -> unconfirmed
466
+ * step 3 A -> stands | B -> at most strongly supported | C -> at most unconfirmed
467
+ * ```
468
+ *
469
+ * **Resolution is an input to step 1 and appears nowhere in step 2.** An
470
+ * earlier form of this gate granted `confirmed` on *"the structural path
471
+ * resolves R2+ throughout"*, which reads resolution directly as a category
472
+ * threshold — re-implementing rule 3 in a second place, at a different
473
+ * threshold, with nothing tying the two together. `reliabilityCap()` is the one
474
+ * function that turns a resolution into a class, so step 1 calls it and never
475
+ * restates its table.
476
+ *
477
+ * The step 3 mapping is corroborated rather than invented: DEC-223 reached the
478
+ * class-B row independently, in its own words — *"a finding resting on
479
+ * testimony is at most strongly supported, never confirmed."*
480
+ *
481
+ * **`M` dominates step 2, not channel count** — `ai-governance-spec.md` §5.1.
482
+ * One piece of direct mechanism evidence — a reproduced test failure, an
483
+ * exception whose stack frame resolves to the hypothesis's node, a network
484
+ * response matching the predicted defect on the exact route — reaches
485
+ * `confirmed` regardless of how many channels agree. Two channels that merely
486
+ * co-occur without naming the node (§5.3's own example: a console error and a
487
+ * failed network call, neither correlated to the hypothesis) are `E = 2,
488
+ * M = false`: `strongly supported`, never `confirmed`. This is what the
489
+ * earlier `E >= 2 -> confirmed` form left open — §41 rule 12 (correlation must
490
+ * not become causation) re-entering through the gate built to enforce it.
491
+ *
492
+ * Two consequences worth stating because they are the point: `confirmed` at
493
+ * class B is unreachable, so the two labels can never disagree about one
494
+ * finding; and G3's precondition survives even inside step 2 alone, because
495
+ * zero runtime evidence forces both `M = false` and `E = 0` by construction
496
+ * (both are computed from the same evidence array) — the explicit
497
+ * short-circuit below is a second, independent enforcement of that same
498
+ * invariant, not a case step 2 would otherwise get wrong.
499
+ *
500
+ * **Ruled 2026-08-24 — `ai-governance-spec.md` §5, closing
501
+ * `documents/decisions-inbox/DEC-NEXT-hypothesis-states-vs-g4.md` and
502
+ * `documents/decisions-inbox/DEC-NEXT-independent-signal-type-inventory.md`.**
503
+ * `documents/architecture/descry-ai-layer.md` §12's hypothesis-state
504
+ * thresholds and this gate now agree on identical evidence — there is only
505
+ * one function; §12's states are machine states, never a label directly
506
+ * (`ai-layer-plan.md` §6 rule 2).
507
+ *
508
+ * Takes an object rather than positionals because several of the fields are
509
+ * adjacent booleans, and a swapped pair is a silent wrong answer rather than a
510
+ * compile error.
511
+ */
512
+ export declare function reportCategory(inputs: G4Inputs): G4Result;
513
+ /**
514
+ * A G4-gated finding as it is stored: the `Finding` plus the inputs that
515
+ * produced its derived axes.
516
+ *
517
+ * **Scoped to the findings §19's evidence categories actually govern.** The
518
+ * other two categories — `not analysable`, `unsupported` — are refusals
519
+ * inherited from the static case (see {@link EVIDENCE_CATEGORIES}'s doc) and
520
+ * were never subject to `E`/`R`/`N`/`H` at all, so they have no G4 inputs to
521
+ * record. Storing those is a different, currently unbuilt, concern — see
522
+ * `documents/architecture/descry-ai-layer.md` §20.3's static-pipeline gate.
523
+ *
524
+ * **A wrapper, not an extension: `Finding` stays exactly §20's fourteen
525
+ * fields.** This is what gets stored; {@link rederive} is what a reader gets
526
+ * back. Storage itself is P2/P24 — `descry-desktop/packages/session` per
527
+ * DEC-265 — and is not built here. This package builds the shape and the
528
+ * re-derivation function; whoever writes the store consumes them.
529
+ */
530
+ export interface FindingRecord {
531
+ readonly finding: Finding;
532
+ readonly inputs: G4Inputs;
533
+ }
534
+ /**
535
+ * Thrown by {@link rederive} when a record cannot be trusted to re-derive
536
+ * from — a missing, mistyped or out-of-range G4 input, or a finding whose
537
+ * `confidence` was never G4-gated in the first place.
538
+ *
539
+ * A thrown error rather than a best-effort fallback, because the alternative
540
+ * is a *silently* wrong reliability class — the one field the whole cap in
541
+ * rule 3 rests on — which is worse than none at all.
542
+ */
543
+ export declare class RederivationError extends Error {
544
+ readonly name = "RederivationError";
545
+ }
546
+ /**
547
+ * Read a {@link FindingRecord} back as a `Finding` — the legitimate producer
548
+ * of `Derived<T>` on the read side of a storage boundary. The provisional
549
+ * escape hatch this module used to carry for the same purpose is gone; this
550
+ * is what made it deletable rather than permanent.
551
+ *
552
+ * Recomputes `reliabilityClass`, `resolutionLevel` and `confidence` from
553
+ * `record.inputs` by calling {@link reportCategory} — the one function that
554
+ * turns `E`/`R`/`N`/`H` into a class, never restated here. The recomputed
555
+ * values are authoritative; `record.finding`'s own copies of these three
556
+ * fields are not read at all, only overwritten, because the entire point is
557
+ * that this is a *re-derivation*, not a restoration of whatever the record
558
+ * happened to say.
559
+ *
560
+ * Throws {@link RederivationError} — rather than returning a plausible but
561
+ * wrong value — when `record.inputs` cannot be trusted (a missing, mistyped
562
+ * or out-of-range field) or when `record.finding.confidence` is not one of
563
+ * {@link EVIDENCE_CATEGORIES} (the finding was never G4-gated, so it has no
564
+ * G4 inputs to rederive from regardless of what `record.inputs` claims).
565
+ */
566
+ export declare function rederive(record: FindingRecord): Finding;
567
+ //# sourceMappingURL=finding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,KAAK,CAAC;CACpC;AAED,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC;AAY7C;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,8FAMpB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,6DAA8D,CAAC;AAE/F,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,YAAY,4EAWf,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,sCAAuC,CAAC;AAE5E,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,uBAAwB,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,oBAAoB,0GAOvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,kBAAkB,gCAAiC,CAAC;AAEjE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;;;;;;;;;OASG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC;;;;;;;;OAQG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sBAAsB;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,EAAE,SAAS,aAAa,EAAE,CAAC;CACjD;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,qPAejB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,qFAAqF;AACrF,MAAM,WAAW,OAAO;IACtB,uCAAuC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,SAAS,eAAe,EAAE,CAAC;IACrD;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrD,4DAA4D;IAC5D,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACnD,+EAA+E;IAC/E,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,iEAAiE;IACjE,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CACjD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,SAAS,eAAe,EAAE,GACnC,eAAe,CASjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,SAAS,eAAe,EAAE,EACpC,YAAY,EAAE,MAAM,GACnB,OAAO,CAET;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,OAAO,CAElF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,UAAU,CAUnF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,oBAAoB,CAE7E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAQzF;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAE1E;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,2EAA2E;IAC3E,QAAQ,CAAC,sBAAsB,EAAE,eAAe,CAAC;IACjD,uEAAuE;IACvE,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAC;IAC1C,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,6DAA6D;IAC7D,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,uDAAuD;AACvD,MAAM,WAAW,QAAQ;IACvB,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACtD;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAiCzD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,SAAkB,IAAI,uBAAuB;CAC9C;AAgDD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAiBvD"}