@descryy/runtime-contracts 0.0.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/dist/capability.d.ts +118 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +30 -0
- package/dist/capability.js.map +1 -0
- package/dist/collector.d.ts +124 -0
- package/dist/collector.d.ts.map +1 -0
- package/dist/collector.js +42 -0
- package/dist/collector.js.map +1 -0
- package/dist/correlation.d.ts +61 -0
- package/dist/correlation.d.ts.map +1 -0
- package/dist/correlation.js +62 -0
- package/dist/correlation.js.map +1 -0
- package/dist/evidence.d.ts +296 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +204 -0
- package/dist/evidence.js.map +1 -0
- package/dist/execution.d.ts +329 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +55 -0
- package/dist/execution.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime-event.d.ts +20 -0
- package/dist/runtime-event.d.ts.map +1 -0
- package/dist/runtime-event.js +252 -0
- package/dist/runtime-event.js.map +1 -0
- package/dist/source-root.d.ts +97 -0
- package/dist/source-root.d.ts.map +1 -0
- package/dist/source-root.js +107 -0
- package/dist/source-root.js.map +1 -0
- package/package.json +26 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence contract.
|
|
3
|
+
*
|
|
4
|
+
* Field list is verbatim from `documents/descry-runtime-plan.md` §13
|
|
5
|
+
* (Evidence model), plus `evidenceId` (needed for the ID-reference pattern
|
|
6
|
+
* Execution uses) and `stackTrace` (structured detail for the plan's
|
|
7
|
+
* STACK_TRACE event type, per Agent 3's stack-fidelity finding below). Also
|
|
8
|
+
* grounded in the architecture doc's §18.2 (evidence bundling —
|
|
9
|
+
* screenshot/console/network/backend log, "none of these individually
|
|
10
|
+
* would have been enough"), §17.2 (the observe stream), §9 (the three
|
|
11
|
+
* confidence axes — this file's `confidence` field is the resolution-
|
|
12
|
+
* honesty axis, never conflated with environment fidelity, which lives on
|
|
13
|
+
* Execution/Capability instead) and §25 (redaction before storage).
|
|
14
|
+
*
|
|
15
|
+
* Static facts and runtime observations stay separate. Evidence never
|
|
16
|
+
* embeds a graph node's data — `graphNodeId` is a reference into
|
|
17
|
+
* @descryy/ir's identity scheme, resolved by whoever reads it. This file
|
|
18
|
+
* does not, and must not, redefine graph identity or storage.
|
|
19
|
+
*/
|
|
20
|
+
import type { RuntimeEventType } from "./runtime-event.ts";
|
|
21
|
+
export declare const EVIDENCE_SOURCES: readonly ["browser-dom", "browser-console", "browser-network", "backend-log", "backend-process", "process-exit", "http-response-payload", "test-runner", "harness", "dependency-check", "environment-check"];
|
|
22
|
+
export type EvidenceSource = (typeof EVIDENCE_SOURCES)[number];
|
|
23
|
+
export declare const REDACTION_STATUSES: readonly ["not-required", "redacted", "pending-redaction"];
|
|
24
|
+
export type RedactionStatus = (typeof REDACTION_STATUSES)[number];
|
|
25
|
+
/**
|
|
26
|
+
* Source-location reliability is not one axis with a probabilistic middle —
|
|
27
|
+
* it is three structurally different classes (Agent 3's finding), and
|
|
28
|
+
* conflating them into a single confidence number loses exactly the
|
|
29
|
+
* information a reader needs to judge a location claim:
|
|
30
|
+
*
|
|
31
|
+
* - self-contained: the location came from the process's own captured
|
|
32
|
+
* state (a Python traceback, a Ruby backtrace, a Go `recover()` frame).
|
|
33
|
+
* Accurate when captured; the risk is *capture completeness*, not
|
|
34
|
+
* correctness.
|
|
35
|
+
* - debug-info-present / debug-info-stripped: a binary's own line-number
|
|
36
|
+
* table (Java/Kotlin). A binary outcome — there is no partial case.
|
|
37
|
+
* - side-artifact-resolved / side-artifact-stale / side-artifact-missing:
|
|
38
|
+
* resolution went through a separate file that can drift or vanish
|
|
39
|
+
* (a Node source map, a C# PDB, a Swift dSYM). "We mapped it and it's
|
|
40
|
+
* right" and "we mapped it through an artifact that may be stale" are
|
|
41
|
+
* different confidence claims, and this type is what lets Evidence say
|
|
42
|
+
* which one it is instead of reporting both identically.
|
|
43
|
+
* - self-contained-eval-line: same mechanism as self-contained — the
|
|
44
|
+
* process's own captured backtrace, nothing translated through a side
|
|
45
|
+
* artifact — but the *line* does not index the named file. Ruby's
|
|
46
|
+
* `instance_eval`/`eval` frames print a synthetic path,
|
|
47
|
+
* `(eval at file.rb:12):1`, where `12` is where `eval` was called from
|
|
48
|
+
* but `1` counts lines within the evaluated string, not within
|
|
49
|
+
* `file.rb`. Opening `file.rb` at line `1` shows unrelated code, so this
|
|
50
|
+
* is not a plain self-contained claim; it is not a side-artifact claim
|
|
51
|
+
* either, since nothing was resolved through a separate file. See
|
|
52
|
+
* `packages/adapter-ruby/src/ruby-source-location-resolver.ts` for the
|
|
53
|
+
* one producer of this value.
|
|
54
|
+
*/
|
|
55
|
+
export declare const SOURCE_LOCATION_RELIABILITIES: readonly ["self-contained", "debug-info-present", "debug-info-stripped", "side-artifact-resolved", "side-artifact-stale", "side-artifact-missing", "self-contained-eval-line"];
|
|
56
|
+
export type SourceLocationReliability = (typeof SOURCE_LOCATION_RELIABILITIES)[number];
|
|
57
|
+
export interface SourceLocation {
|
|
58
|
+
/**
|
|
59
|
+
* **Null when the runtime named no source file**, for the same reason
|
|
60
|
+
* `line` can be null and discovered by the same adapter.
|
|
61
|
+
*
|
|
62
|
+
* A stripped JVM frame is `at com.example.Thrower.handler(Unknown Source)`
|
|
63
|
+
* and a native one is `(Native Method)`: neither carries a filename. The
|
|
64
|
+
* method name is still real evidence and still resolves against the graph
|
|
65
|
+
* by symbol, so dropping such frames would delete an entire stack for a
|
|
66
|
+
* release build.
|
|
67
|
+
*
|
|
68
|
+
* The filename is **not** derived from the class name, though the JVM
|
|
69
|
+
* convention makes that look safe. Kotlin breaks it outright — a class
|
|
70
|
+
* `Foo` may be declared in `Bar.kt` — and this parser serves both
|
|
71
|
+
* languages, so the derivation would be right for one and wrong for the
|
|
72
|
+
* other. Null is the honest answer.
|
|
73
|
+
*/
|
|
74
|
+
readonly file: string | null;
|
|
75
|
+
/**
|
|
76
|
+
* **Null when the runtime genuinely captured no line**, which is a real
|
|
77
|
+
* state rather than a failure to look — and one this type could not
|
|
78
|
+
* express until a JVM adapter existed to need it.
|
|
79
|
+
*
|
|
80
|
+
* A JVM class compiled without a `LineNumberTable` (`javac -g:none`, and
|
|
81
|
+
* the default for many release builds) prints
|
|
82
|
+
* `at com.example.Thrower.handler(Unknown Source)`: the class is real,
|
|
83
|
+
* the method is real, and there is no line. So is a `(Native Method)`
|
|
84
|
+
* frame. `reliability: "debug-info-stripped"` describes exactly that
|
|
85
|
+
* situation — meaning that while this field was required, that enum value
|
|
86
|
+
* could only ever be attached to a **fabricated** number. The type and
|
|
87
|
+
* the enum contradicted each other, and the type was wrong.
|
|
88
|
+
*
|
|
89
|
+
* A frame with no line is still real evidence: the symbol name alone
|
|
90
|
+
* resolves against the graph. Dropping such frames would discard an
|
|
91
|
+
* entire stack for a stripped build, which is the "we could not read it"
|
|
92
|
+
* case that must degrade honestly rather than vanish.
|
|
93
|
+
*/
|
|
94
|
+
readonly line: number | null;
|
|
95
|
+
readonly column: number | null;
|
|
96
|
+
readonly functionName: string | null;
|
|
97
|
+
readonly reliability: SourceLocationReliability;
|
|
98
|
+
/** Set only for the side-artifact-* reliabilities — names the specific map/PDB/dSYM, so a stale-artifact finding is traceable to the file that drifted. Null otherwise. */
|
|
99
|
+
readonly resolvedVia: string | null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Whether a captured stack reflects the actual logical call chain is a
|
|
103
|
+
* third, orthogonal axis (Agent 3's finding): concurrency models
|
|
104
|
+
* (coroutines, goroutines, async/await, tokio tasks) can capture a stack
|
|
105
|
+
* successfully while structurally breaking the "reflects the logical
|
|
106
|
+
* caller" guarantee. That is not a low-confidence stack — it is a
|
|
107
|
+
* different kind of evidence, and gets its own field rather than a lower
|
|
108
|
+
* number folded into `confidence`.
|
|
109
|
+
*/
|
|
110
|
+
export declare const STACK_FIDELITIES: readonly ["synchronous", "concurrency-fragmented", "unavailable"];
|
|
111
|
+
export type StackFidelity = (typeof STACK_FIDELITIES)[number];
|
|
112
|
+
export interface StackFrame {
|
|
113
|
+
readonly location: SourceLocation;
|
|
114
|
+
/** The frame's original, unparsed text — kept for audit even after structured parsing. */
|
|
115
|
+
readonly raw: string;
|
|
116
|
+
}
|
|
117
|
+
export interface StackTrace {
|
|
118
|
+
readonly fidelity: StackFidelity;
|
|
119
|
+
/**
|
|
120
|
+
* **Most-recent call first**, always — `frames[0]` is the innermost frame,
|
|
121
|
+
* the one where execution actually was. Every parser normalises to this;
|
|
122
|
+
* callers may rely on it.
|
|
123
|
+
*
|
|
124
|
+
* This was unstated while TypeScript was the only language, because V8
|
|
125
|
+
* emits this order natively and nothing had to convert. It is not a
|
|
126
|
+
* universal convention: a CPython traceback prints **oldest call first**,
|
|
127
|
+
* with the failing frame last, and so does a Java `printStackTrace` cause
|
|
128
|
+
* chain read naively. An adapter for such a runtime reverses during
|
|
129
|
+
* parsing — the ordering decision belongs in the language adapter, which
|
|
130
|
+
* knows its own runtime's convention, never in a consumer that would have
|
|
131
|
+
* to ask which language produced the trace to know which end to read.
|
|
132
|
+
*
|
|
133
|
+
* Getting this wrong is quiet rather than loud: the trace still has the
|
|
134
|
+
* right frames and the right count, and root-cause traversal simply
|
|
135
|
+
* points at whichever end of the call chain happens to be first —
|
|
136
|
+
* typically the process entry point instead of the failing line.
|
|
137
|
+
*/
|
|
138
|
+
readonly frames: readonly StackFrame[];
|
|
139
|
+
/**
|
|
140
|
+
* Which frame is the **failure site** — the one a developer should be sent
|
|
141
|
+
* to. Usually `0`; not always, and the exceptions are not exotic.
|
|
142
|
+
*
|
|
143
|
+
* ## Why an index and not `frames[0]`
|
|
144
|
+
*
|
|
145
|
+
* `frames[0]` is reliably the *innermost* frame. On several runtimes the
|
|
146
|
+
* innermost frame is the runtime's own, sitting above the application's,
|
|
147
|
+
* and is therefore innermost and useless. Measured on live still-running
|
|
148
|
+
* servers (Lane C, RT-120/121):
|
|
149
|
+
*
|
|
150
|
+
* | runtime | `frames[0]` | the failure site |
|
|
151
|
+
* | --- | --- | --- |
|
|
152
|
+
* | Go, recovered `net/http` handler panic | `net/http.(*conn).serve.func1` at `server.go:1897` | several frames down |
|
|
153
|
+
* | Rust, threaded server | `__rustc::rust_begin_unwind` at `panicking.rs:698` | after five `std`/`core` frames |
|
|
154
|
+
*
|
|
155
|
+
* The JVM's `Caused by:` chains, C#'s `--- End of stack trace from previous
|
|
156
|
+
* location ---` and Kotlin's coroutine frames are the same shape.
|
|
157
|
+
*
|
|
158
|
+
* ## Why this is not a heuristic
|
|
159
|
+
*
|
|
160
|
+
* **Each runtime marks the boundary itself**, which is the entire reason
|
|
161
|
+
* this is expressible as an index rather than as a filter:
|
|
162
|
+
*
|
|
163
|
+
* - Go prints a `panic(` frame **only** when the stack was walked through a
|
|
164
|
+
* recover — an unrecovered panic has none. Measured both ways.
|
|
165
|
+
* - Rust's header names the panic site with line *and column*, and exactly
|
|
166
|
+
* one frame matches it.
|
|
167
|
+
*
|
|
168
|
+
* So the adapter that knows its runtime reads that runtime's own marker.
|
|
169
|
+
* Nothing above the IR boundary names a language, and nothing anywhere
|
|
170
|
+
* denylists a stdlib path — a path-shaped filter is the thing this field
|
|
171
|
+
* exists to make unnecessary, and it would break on any application that
|
|
172
|
+
* legitimately fails inside a library frame.
|
|
173
|
+
*
|
|
174
|
+
* ## Nothing is dropped
|
|
175
|
+
*
|
|
176
|
+
* Every frame stays in `frames`, including the unwinding frames above the
|
|
177
|
+
* failure site. This is a **view**, not a filter, which is what keeps
|
|
178
|
+
* `adapter-rust`'s standing decision intact — *"std/core frames are kept;
|
|
179
|
+
* filtering them would be a readability judgment applied to evidence"* —
|
|
180
|
+
* rather than superseding it. `payload.raw` keeps the verbatim block as
|
|
181
|
+
* well, as always.
|
|
182
|
+
*
|
|
183
|
+
* ## Required, deliberately
|
|
184
|
+
*
|
|
185
|
+
* Not optional, for the reason RT-056 records about `processLifecycle`:
|
|
186
|
+
* **an optional field is one every existing adapter may silently omit**, and
|
|
187
|
+
* an adapter that never considered the question would keep today's behaviour
|
|
188
|
+
* with no signal that it never considered it. Where the innermost frame
|
|
189
|
+
* genuinely is the failure site the answer is `0` — but stated, not
|
|
190
|
+
* defaulted.
|
|
191
|
+
*
|
|
192
|
+
* Consumers must treat an out-of-range value as a fault rather than
|
|
193
|
+
* clamping to `0`: a silent fallback would reintroduce exactly the defect
|
|
194
|
+
* this field removes, through the error path instead of the happy one.
|
|
195
|
+
*/
|
|
196
|
+
readonly primaryFrameIndex: number;
|
|
197
|
+
}
|
|
198
|
+
export interface Evidence {
|
|
199
|
+
readonly evidenceId: string;
|
|
200
|
+
readonly executionId: string;
|
|
201
|
+
readonly timestamp: string;
|
|
202
|
+
readonly source: EvidenceSource;
|
|
203
|
+
/** Which owned system this came from (§16.7) — null when not applicable. */
|
|
204
|
+
readonly service: string | null;
|
|
205
|
+
/** ProcessHandle.processId, when this evidence is attributable to one process. */
|
|
206
|
+
readonly process: string | null;
|
|
207
|
+
readonly eventType: RuntimeEventType;
|
|
208
|
+
/** Redacted per `redactionStatus` before this is readable by anything upstream (§25) — never raw secrets in transit. */
|
|
209
|
+
readonly payload: unknown;
|
|
210
|
+
readonly traceId: string | null;
|
|
211
|
+
readonly requestId: string | null;
|
|
212
|
+
/** Set only after the Correlation Engine resolves it (correlation.ts) — never assigned speculatively here. */
|
|
213
|
+
readonly correlationId: string | null;
|
|
214
|
+
/** @descryy/ir node ID, set only when resolved via the graph's own identity scheme. This file does not define graph identity. */
|
|
215
|
+
readonly graphNodeId: string | null;
|
|
216
|
+
readonly sourceLocation: SourceLocation | null;
|
|
217
|
+
readonly stackTrace: StackTrace | null;
|
|
218
|
+
/** Resolution-honesty confidence (§9), 0-1. Independent of environment fidelity level and of a Correlation's own confidence. */
|
|
219
|
+
readonly confidence: number;
|
|
220
|
+
readonly redactionStatus: RedactionStatus;
|
|
221
|
+
/**
|
|
222
|
+
* The `version` field of the `package.json` that owns the collector which
|
|
223
|
+
* produced this row (e.g. `@descryhq-wq/runtime-browser`'s own version for
|
|
224
|
+
* browser-sourced evidence) — read from the package at module load, never
|
|
225
|
+
* hand-duplicated into a second string that can drift from what actually
|
|
226
|
+
* shipped. Same idea as `nodeVersion` elsewhere in this repo (`process.version`,
|
|
227
|
+
* always known, never probed) and as `@descryy/ir`'s `producedBy` (`adapterId@version`,
|
|
228
|
+
* "drives graph invalidation on adapter upgrade") applied to evidence instead of
|
|
229
|
+
* IR nodes — see RUNTIME-CHECKLIST.md §3/§19/§23: without this, evidence "cannot
|
|
230
|
+
* be invalidated by collector version the way IR nodes can."
|
|
231
|
+
*
|
|
232
|
+
* Required, not optional, for the same reason `primaryFrameIndex` above is
|
|
233
|
+
* required: an optional field is one an existing collector can silently omit,
|
|
234
|
+
* with no signal that it never considered the question.
|
|
235
|
+
*/
|
|
236
|
+
readonly collectorVersion: string;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Which `SourceLocation` an `Evidence` carries for a given stack — one rule,
|
|
240
|
+
* in one place, for every collector that turns a trace into evidence.
|
|
241
|
+
*
|
|
242
|
+
* ## Why it lives in the contract rather than in each collector
|
|
243
|
+
*
|
|
244
|
+
* It was written twice. `backend-observation`'s collector was moved onto
|
|
245
|
+
* `primaryFrameIndex` (RT-083); `browser`'s console collector kept its own
|
|
246
|
+
* `frames[0]` copy and nothing failed, because V8 reports
|
|
247
|
+
* `primaryFrameIndex: 0` and the two rules agree there **by coincidence**.
|
|
248
|
+
* A copied rule is a rule that will hold in one of them, and this one held
|
|
249
|
+
* in one of them for exactly as long as one runtime was involved.
|
|
250
|
+
*
|
|
251
|
+
* ## The empty location, which is the part that is not obvious
|
|
252
|
+
*
|
|
253
|
+
* `StackFrame.location` is not nullable, so a frame that resolved nothing
|
|
254
|
+
* still carries a `SourceLocation` — one whose `file`, `line` and
|
|
255
|
+
* `functionName` are all null. Returning it would set
|
|
256
|
+
* `Evidence.sourceLocation` to a non-null object naming nothing, and
|
|
257
|
+
* `evidence-package.ts` censuses located evidence with `sourceLocation !==
|
|
258
|
+
* null`. An unsymbolicated crash would be counted as *located* in the very
|
|
259
|
+
* artifact handed to a model — RT-124's shape (a thing reported as the thing
|
|
260
|
+
* it failed to be), one field over.
|
|
261
|
+
*
|
|
262
|
+
* Measured rather than imagined (Lane C, RT-126): on a CI runner a real
|
|
263
|
+
* Swift crash produced a real three-thread backtrace in which every frame is
|
|
264
|
+
* address-only — no symbol, no `at file:line`.
|
|
265
|
+
*
|
|
266
|
+
* ## The discriminator is `functionName`, not `file`
|
|
267
|
+
*
|
|
268
|
+
* A stripped JVM frame (`at com.example.Thrower.handler(Unknown Source)`)
|
|
269
|
+
* and a Rust release frame both have a null file **and a real symbol**,
|
|
270
|
+
* which `SourceLocation.file`'s own doc calls real evidence that still
|
|
271
|
+
* resolves against the graph by name. `adapter-jvm` and `adapter-rust` each
|
|
272
|
+
* assert exactly that. Keying emptiness on a null file would delete the
|
|
273
|
+
* location for every stripped build in both languages — the case this type
|
|
274
|
+
* was widened to express.
|
|
275
|
+
*
|
|
276
|
+
* ## Nothing is lost by returning null
|
|
277
|
+
*
|
|
278
|
+
* The frames stay on `Evidence.stackTrace` with their raw text and their
|
|
279
|
+
* `reliability`. "There was no stack" and "there was a stack that could name
|
|
280
|
+
* nothing" therefore remain distinguishable **on the same record**, because
|
|
281
|
+
* `stackTrace` separates them. That recoverability is the test for whether
|
|
282
|
+
* nulling a field is honest degradation or information loss; here it is the
|
|
283
|
+
* first.
|
|
284
|
+
*/
|
|
285
|
+
export declare function primaryFrameLocation(stackTrace: StackTrace | null): SourceLocation | null;
|
|
286
|
+
/**
|
|
287
|
+
* True when a location identifies no place in any source.
|
|
288
|
+
*
|
|
289
|
+
* `column` is deliberately not consulted: a column is an offset into a line,
|
|
290
|
+
* so with no line it names no position and cannot make an otherwise-empty
|
|
291
|
+
* location informative. `reliability` and `resolvedVia` are not consulted
|
|
292
|
+
* either — they record *why* nothing resolved, which describes the failure
|
|
293
|
+
* rather than a place.
|
|
294
|
+
*/
|
|
295
|
+
export declare function locationNamesNothing(location: SourceLocation): boolean;
|
|
296
|
+
//# sourceMappingURL=evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"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"}
|
package/dist/evidence.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence contract.
|
|
3
|
+
*
|
|
4
|
+
* Field list is verbatim from `documents/descry-runtime-plan.md` §13
|
|
5
|
+
* (Evidence model), plus `evidenceId` (needed for the ID-reference pattern
|
|
6
|
+
* Execution uses) and `stackTrace` (structured detail for the plan's
|
|
7
|
+
* STACK_TRACE event type, per Agent 3's stack-fidelity finding below). Also
|
|
8
|
+
* grounded in the architecture doc's §18.2 (evidence bundling —
|
|
9
|
+
* screenshot/console/network/backend log, "none of these individually
|
|
10
|
+
* would have been enough"), §17.2 (the observe stream), §9 (the three
|
|
11
|
+
* confidence axes — this file's `confidence` field is the resolution-
|
|
12
|
+
* honesty axis, never conflated with environment fidelity, which lives on
|
|
13
|
+
* Execution/Capability instead) and §25 (redaction before storage).
|
|
14
|
+
*
|
|
15
|
+
* Static facts and runtime observations stay separate. Evidence never
|
|
16
|
+
* embeds a graph node's data — `graphNodeId` is a reference into
|
|
17
|
+
* @descryy/ir's identity scheme, resolved by whoever reads it. This file
|
|
18
|
+
* does not, and must not, redefine graph identity or storage.
|
|
19
|
+
*/
|
|
20
|
+
export const EVIDENCE_SOURCES = [
|
|
21
|
+
// Also the source for VIDEO (runtime-event.ts) -- SCREENSHOT's own
|
|
22
|
+
// precedent: a captured-artifact *kind* is a RuntimeEventType, not a
|
|
23
|
+
// watched *domain*, so it reuses this entry rather than adding one.
|
|
24
|
+
"browser-dom",
|
|
25
|
+
"browser-console",
|
|
26
|
+
"browser-network",
|
|
27
|
+
"backend-log",
|
|
28
|
+
"backend-process",
|
|
29
|
+
"process-exit",
|
|
30
|
+
"http-response-payload",
|
|
31
|
+
/** §17 (Test Runner Support, RT-073): TEST_STARTED/PASSED/FAILED, from a runner's own structured reporter output -- never parsed from printed prose (see `packages/test-runner`'s own module doc for why). */
|
|
32
|
+
"test-runner",
|
|
33
|
+
/**
|
|
34
|
+
* RT-219 (runtime self-observability). Every other value in this list
|
|
35
|
+
* names a domain the runtime is *watching* (a browser, a backend
|
|
36
|
+
* process, a test runner). `"harness"` names the opposite direction: the
|
|
37
|
+
* runtime observing **itself** -- a collector/orchestrator/correlator/
|
|
38
|
+
* evidence-store operation that broke on its own terms, not on the
|
|
39
|
+
* observed application's. DEC-273's `automation` fault value (Descry's
|
|
40
|
+
* own harness broke, not the app) had no evidence this repo could point
|
|
41
|
+
* at to positively establish it; this is that evidence's tag.
|
|
42
|
+
*
|
|
43
|
+
* Deliberately a new `source`, not a repurposing of `COLLECTOR_ERROR`
|
|
44
|
+
* alone. `COLLECTOR_ERROR` already existed (`runtime-event.ts`) for "the
|
|
45
|
+
* observer failed, not the observed system," but every existing emitter
|
|
46
|
+
* stamps it with the *domain* source it was observing when it died
|
|
47
|
+
* (`"backend-process"` for a log collector's consume loop, etc.) --
|
|
48
|
+
* correct for a collector's own mid-stream failure, but it means a
|
|
49
|
+
* COLLECTOR_ERROR row is not on its own distinguishable from ordinary
|
|
50
|
+
* domain evidence by `source` alone, only by `eventType`. A harness
|
|
51
|
+
* component with no domain of its own (the orchestrator's own
|
|
52
|
+
* `Promise.all` around `collector.start()`, for instance) has no honest
|
|
53
|
+
* domain source to reuse, and reusing one anyway would make a self-
|
|
54
|
+
* failure look like it came from the thing being watched. `"harness"`
|
|
55
|
+
* is that missing, honestly-named source -- additive, not a
|
|
56
|
+
* retag of any existing emitter.
|
|
57
|
+
*/
|
|
58
|
+
"harness",
|
|
59
|
+
/**
|
|
60
|
+
* `DEC-NEXT-fault-layer-empirical-confirmation.md`'s `dependency`
|
|
61
|
+
* mechanism (`@descryy/runtime-controller`'s
|
|
62
|
+
* `checkDependencyVersions`): a structural comparison finding the
|
|
63
|
+
* project's lockfile-declared version of a direct dependency does not
|
|
64
|
+
* match the version actually installed under `node_modules` at
|
|
65
|
+
* execution time. Same standing as `"harness"` -- a fact the runtime
|
|
66
|
+
* establishes about its own execution environment, not an observation of
|
|
67
|
+
* the domain under test, so `signal` stays `null` for records carrying
|
|
68
|
+
* this source (`classifyEvidenceChannel` fails it closed, same as
|
|
69
|
+
* `"harness"`).
|
|
70
|
+
*/
|
|
71
|
+
"dependency-check",
|
|
72
|
+
/**
|
|
73
|
+
* The same ruling's `environment` mechanism
|
|
74
|
+
* (`checkEnvironmentVersion`): a structural comparison finding the
|
|
75
|
+
* project's declared runner version (`.nvmrc`/`package.json
|
|
76
|
+
* engines.node`) does not match the runner version actually observed at
|
|
77
|
+
* execution (`process.version`). Same standing as `"dependency-check"`.
|
|
78
|
+
*/
|
|
79
|
+
"environment-check",
|
|
80
|
+
];
|
|
81
|
+
export const REDACTION_STATUSES = ["not-required", "redacted", "pending-redaction"];
|
|
82
|
+
/**
|
|
83
|
+
* Source-location reliability is not one axis with a probabilistic middle —
|
|
84
|
+
* it is three structurally different classes (Agent 3's finding), and
|
|
85
|
+
* conflating them into a single confidence number loses exactly the
|
|
86
|
+
* information a reader needs to judge a location claim:
|
|
87
|
+
*
|
|
88
|
+
* - self-contained: the location came from the process's own captured
|
|
89
|
+
* state (a Python traceback, a Ruby backtrace, a Go `recover()` frame).
|
|
90
|
+
* Accurate when captured; the risk is *capture completeness*, not
|
|
91
|
+
* correctness.
|
|
92
|
+
* - debug-info-present / debug-info-stripped: a binary's own line-number
|
|
93
|
+
* table (Java/Kotlin). A binary outcome — there is no partial case.
|
|
94
|
+
* - side-artifact-resolved / side-artifact-stale / side-artifact-missing:
|
|
95
|
+
* resolution went through a separate file that can drift or vanish
|
|
96
|
+
* (a Node source map, a C# PDB, a Swift dSYM). "We mapped it and it's
|
|
97
|
+
* right" and "we mapped it through an artifact that may be stale" are
|
|
98
|
+
* different confidence claims, and this type is what lets Evidence say
|
|
99
|
+
* which one it is instead of reporting both identically.
|
|
100
|
+
* - self-contained-eval-line: same mechanism as self-contained — the
|
|
101
|
+
* process's own captured backtrace, nothing translated through a side
|
|
102
|
+
* artifact — but the *line* does not index the named file. Ruby's
|
|
103
|
+
* `instance_eval`/`eval` frames print a synthetic path,
|
|
104
|
+
* `(eval at file.rb:12):1`, where `12` is where `eval` was called from
|
|
105
|
+
* but `1` counts lines within the evaluated string, not within
|
|
106
|
+
* `file.rb`. Opening `file.rb` at line `1` shows unrelated code, so this
|
|
107
|
+
* is not a plain self-contained claim; it is not a side-artifact claim
|
|
108
|
+
* either, since nothing was resolved through a separate file. See
|
|
109
|
+
* `packages/adapter-ruby/src/ruby-source-location-resolver.ts` for the
|
|
110
|
+
* one producer of this value.
|
|
111
|
+
*/
|
|
112
|
+
export const SOURCE_LOCATION_RELIABILITIES = [
|
|
113
|
+
"self-contained",
|
|
114
|
+
"debug-info-present",
|
|
115
|
+
"debug-info-stripped",
|
|
116
|
+
"side-artifact-resolved",
|
|
117
|
+
"side-artifact-stale",
|
|
118
|
+
"side-artifact-missing",
|
|
119
|
+
"self-contained-eval-line",
|
|
120
|
+
];
|
|
121
|
+
/**
|
|
122
|
+
* Whether a captured stack reflects the actual logical call chain is a
|
|
123
|
+
* third, orthogonal axis (Agent 3's finding): concurrency models
|
|
124
|
+
* (coroutines, goroutines, async/await, tokio tasks) can capture a stack
|
|
125
|
+
* successfully while structurally breaking the "reflects the logical
|
|
126
|
+
* caller" guarantee. That is not a low-confidence stack — it is a
|
|
127
|
+
* different kind of evidence, and gets its own field rather than a lower
|
|
128
|
+
* number folded into `confidence`.
|
|
129
|
+
*/
|
|
130
|
+
export const STACK_FIDELITIES = ["synchronous", "concurrency-fragmented", "unavailable"];
|
|
131
|
+
/**
|
|
132
|
+
* Which `SourceLocation` an `Evidence` carries for a given stack — one rule,
|
|
133
|
+
* in one place, for every collector that turns a trace into evidence.
|
|
134
|
+
*
|
|
135
|
+
* ## Why it lives in the contract rather than in each collector
|
|
136
|
+
*
|
|
137
|
+
* It was written twice. `backend-observation`'s collector was moved onto
|
|
138
|
+
* `primaryFrameIndex` (RT-083); `browser`'s console collector kept its own
|
|
139
|
+
* `frames[0]` copy and nothing failed, because V8 reports
|
|
140
|
+
* `primaryFrameIndex: 0` and the two rules agree there **by coincidence**.
|
|
141
|
+
* A copied rule is a rule that will hold in one of them, and this one held
|
|
142
|
+
* in one of them for exactly as long as one runtime was involved.
|
|
143
|
+
*
|
|
144
|
+
* ## The empty location, which is the part that is not obvious
|
|
145
|
+
*
|
|
146
|
+
* `StackFrame.location` is not nullable, so a frame that resolved nothing
|
|
147
|
+
* still carries a `SourceLocation` — one whose `file`, `line` and
|
|
148
|
+
* `functionName` are all null. Returning it would set
|
|
149
|
+
* `Evidence.sourceLocation` to a non-null object naming nothing, and
|
|
150
|
+
* `evidence-package.ts` censuses located evidence with `sourceLocation !==
|
|
151
|
+
* null`. An unsymbolicated crash would be counted as *located* in the very
|
|
152
|
+
* artifact handed to a model — RT-124's shape (a thing reported as the thing
|
|
153
|
+
* it failed to be), one field over.
|
|
154
|
+
*
|
|
155
|
+
* Measured rather than imagined (Lane C, RT-126): on a CI runner a real
|
|
156
|
+
* Swift crash produced a real three-thread backtrace in which every frame is
|
|
157
|
+
* address-only — no symbol, no `at file:line`.
|
|
158
|
+
*
|
|
159
|
+
* ## The discriminator is `functionName`, not `file`
|
|
160
|
+
*
|
|
161
|
+
* A stripped JVM frame (`at com.example.Thrower.handler(Unknown Source)`)
|
|
162
|
+
* and a Rust release frame both have a null file **and a real symbol**,
|
|
163
|
+
* which `SourceLocation.file`'s own doc calls real evidence that still
|
|
164
|
+
* resolves against the graph by name. `adapter-jvm` and `adapter-rust` each
|
|
165
|
+
* assert exactly that. Keying emptiness on a null file would delete the
|
|
166
|
+
* location for every stripped build in both languages — the case this type
|
|
167
|
+
* was widened to express.
|
|
168
|
+
*
|
|
169
|
+
* ## Nothing is lost by returning null
|
|
170
|
+
*
|
|
171
|
+
* The frames stay on `Evidence.stackTrace` with their raw text and their
|
|
172
|
+
* `reliability`. "There was no stack" and "there was a stack that could name
|
|
173
|
+
* nothing" therefore remain distinguishable **on the same record**, because
|
|
174
|
+
* `stackTrace` separates them. That recoverability is the test for whether
|
|
175
|
+
* nulling a field is honest degradation or information loss; here it is the
|
|
176
|
+
* first.
|
|
177
|
+
*/
|
|
178
|
+
export function primaryFrameLocation(stackTrace) {
|
|
179
|
+
if (stackTrace === null || stackTrace.frames.length === 0)
|
|
180
|
+
return null;
|
|
181
|
+
const index = stackTrace.primaryFrameIndex;
|
|
182
|
+
if (!Number.isInteger(index) || index < 0 || index >= stackTrace.frames.length) {
|
|
183
|
+
throw new RangeError(`primaryFrameIndex ${String(index)} is outside the ${stackTrace.frames.length}-frame list it indexes. ` +
|
|
184
|
+
"The adapter that produced this trace declared a failure site that does not exist; reported rather " +
|
|
185
|
+
"than clamped to frames[0], which would silently restore the stdlib-frame defect this index removes.");
|
|
186
|
+
}
|
|
187
|
+
const location = stackTrace.frames[index]?.location ?? null;
|
|
188
|
+
if (location === null)
|
|
189
|
+
return null;
|
|
190
|
+
return locationNamesNothing(location) ? null : location;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* True when a location identifies no place in any source.
|
|
194
|
+
*
|
|
195
|
+
* `column` is deliberately not consulted: a column is an offset into a line,
|
|
196
|
+
* so with no line it names no position and cannot make an otherwise-empty
|
|
197
|
+
* location informative. `reliability` and `resolvedVia` are not consulted
|
|
198
|
+
* either — they record *why* nothing resolved, which describes the failure
|
|
199
|
+
* rather than a place.
|
|
200
|
+
*/
|
|
201
|
+
export function locationNamesNothing(location) {
|
|
202
|
+
return location.file === null && location.line === null && location.functionName === null;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=evidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,mEAAmE;IACnE,qEAAqE;IACrE,oEAAoE;IACpE,aAAa;IACb,iBAAiB;IACjB,iBAAiB;IACjB,aAAa;IACb,iBAAiB;IACjB,cAAc;IACd,uBAAuB;IACvB,8MAA8M;IAC9M,aAAa;IACb;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,SAAS;IACT;;;;;;;;;;;OAWG;IACH,kBAAkB;IAClB;;;;;;OAMG;IACH,mBAAmB;CACX,CAAC;AAGX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,cAAc,EAAE,UAAU,EAAE,mBAAmB,CAAU,CAAC;AAG7F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,gBAAgB;IAChB,oBAAoB;IACpB,qBAAqB;IACrB,wBAAwB;IACxB,qBAAqB;IACrB,uBAAuB;IACvB,0BAA0B;CAClB,CAAC;AAgDX;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,aAAa,EAAE,wBAAwB,EAAE,aAAa,CAAU,CAAC;AAqIlG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAA6B;IAChE,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvE,MAAM,KAAK,GAAG,UAAU,CAAC,iBAAiB,CAAC;IAC3C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/E,MAAM,IAAI,UAAU,CAClB,qBAAqB,MAAM,CAAC,KAAK,CAAC,mBAAmB,UAAU,CAAC,MAAM,CAAC,MAAM,0BAA0B;YACrG,oGAAoG;YACpG,qGAAqG,CACxG,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,QAAQ,IAAI,IAAI,CAAC;IAC5D,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAwB;IAC3D,OAAO,QAAQ,CAAC,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,YAAY,KAAK,IAAI,CAAC;AAC5F,CAAC"}
|