@descryy/runtime-graph-correlator 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.
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The first production caller of `applyRuntimeObservations()` — architecture
3
+ * §11B.3's R4 runtime confirmation, wired to a real observation source.
4
+ *
5
+ * §11B.3 calls runtime confirmation *"the core technical moat rather than the
6
+ * graph itself"*, and states the consequence plainly: *"a purely static
7
+ * code-graph tool is capped at R3 permanently."* The mechanism has existed in
8
+ * `@descryy/core` since it was built, and the two EARNED tables it writes
9
+ * (`observed_edges`, `edge_corrections`) have been in the store's schema since
10
+ * the store was first written — each with a comment explaining why they cannot
11
+ * be regenerated from source at any price. **Nothing read or wrote either one.**
12
+ * This is what makes the moat run.
13
+ *
14
+ * ## Why this producer
15
+ *
16
+ * `resolveObservedFrontendCaller` already does the hard half. It takes a real
17
+ * captured `fetch()` call-site stack, resolves its site of interest to a
18
+ * `FUNCTION` node, and checks that node against the structural candidate set the
19
+ * graph holds for the endpoint. Its two observed outcomes *are* two of §11B.3's
20
+ * three arrows, and needed only to be spoken in the vocabulary
21
+ * `applyRuntimeObservations` reads:
22
+ *
23
+ * | resolution outcome | arrow |
24
+ * | --- | --- |
25
+ * | `observed` | the graph already holds this `USES_API` edge below R4 — **promote it** |
26
+ * | `structural-observed-conflict` | a real node the structural side never named — **mint the edge at R4** (§11B.3's *"recall gap closed"*) |
27
+ *
28
+ * Everything else — no stack, an unresolvable frame, an ambiguous or missing
29
+ * symbol — produces **no observation at all**. Not an empty confirmation that
30
+ * looks like one; none.
31
+ *
32
+ * ## Why there is no denial arrow here, and why that is a decision
33
+ *
34
+ * `applyRuntimeObservations` accepts `held: false` — runtime saw that an edge
35
+ * did not hold — and records a correction that demotes the edge's confidence.
36
+ * **This producer never emits one, and must not.**
37
+ *
38
+ * A frontend caller resolution can establish that a call *happened*. It cannot
39
+ * establish that one did not: a page visit exercises one code path, and the
40
+ * absence of a captured stack for some other function is absence of evidence,
41
+ * not evidence of absence. Minting a denial from that would demote a correct
42
+ * edge on the strength of a route the run happened not to take — precisely the
43
+ * wrong-direction failure rule 2 exists to prevent, arriving through the one
44
+ * mechanism designed to make the graph *more* trustworthy.
45
+ *
46
+ * The denial arrow is real and stays available; it belongs to a producer that
47
+ * can actually establish non-occurrence (an exhaustive call-graph trace over a
48
+ * fully exercised path), not to this one.
49
+ *
50
+ * ## What this does not do
51
+ *
52
+ * - **It does not judge a finding.** Resolution has no opinion on confidence
53
+ * (RT-027). Nothing here reads or writes a finding, hypothesis or category.
54
+ * - **It does not decide staleness.** An R4-vs-R4 disagreement is reported by
55
+ * the core function as `staleR4` and passed through untouched.
56
+ * - **It does not invent a node.** That refusal is core's, and its `refused`
57
+ * list is passed through rather than swallowed.
58
+ */
59
+ import type { RuntimeEdgeObservation } from "@descryy/ir";
60
+ import { type RuntimeConfirmationResult, type SqlDriver } from "@descryy/core";
61
+ import type { StackTrace } from "@descryy/runtime-contracts";
62
+ import { type ObservedFrontendCallerResolution } from "./observed-frontend-caller.ts";
63
+ export interface ConfirmObservedCallerInput {
64
+ /** The endpoint whose callers this observation is about. */
65
+ readonly endpointNodeId: string;
66
+ /** The captured call-site stack, or `null` when the collector captured none. */
67
+ readonly stackTrace: StackTrace | null;
68
+ readonly repo: string;
69
+ /** The run that witnessed this. Becomes `edges.observed_by_run` and `observed_edges.run_id`. */
70
+ readonly runId: string;
71
+ /** The commit the observed application was built from, so a later reader can tell whether the code moved under the observation. */
72
+ readonly commitSha: string;
73
+ readonly repoRoot?: string;
74
+ }
75
+ export interface ConfirmObservedCallerOutcome {
76
+ /**
77
+ * The underlying resolution, unchanged and always present — including when it
78
+ * produced no observation. A caller that wants the structural answer still
79
+ * gets exactly what `resolveObservedFrontendCaller` would have returned.
80
+ */
81
+ readonly resolution: ObservedFrontendCallerResolution;
82
+ /** What was sent to the graph. Empty when the resolution observed nothing. */
83
+ readonly observations: readonly RuntimeEdgeObservation[];
84
+ /** Core's own result, passed through whole — refusals and `staleR4` included. */
85
+ readonly confirmation: RuntimeConfirmationResult;
86
+ }
87
+ /**
88
+ * Resolve one observed frontend call and, when it genuinely observed something,
89
+ * record it as R4 evidence against the graph.
90
+ */
91
+ export declare function confirmObservedFrontendCaller(driver: SqlDriver, input: ConfirmObservedCallerInput): ConfirmObservedCallerOutcome;
92
+ //# sourceMappingURL=confirm-observed-caller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm-observed-caller.d.ts","sourceRoot":"","sources":["../src/confirm-observed-caller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAEL,KAAK,gCAAgC,EACtC,MAAM,+BAA+B,CAAC;AAEvC,MAAM,WAAW,0BAA0B;IACzC,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gGAAgG;IAChG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,mIAAmI;IACnI,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,gCAAgC,CAAC;IACtD,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACzD,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,yBAAyB,CAAC;CAClD;AAMD;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,0BAA0B,GAChC,4BAA4B,CAyB9B"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * The first production caller of `applyRuntimeObservations()` — architecture
3
+ * §11B.3's R4 runtime confirmation, wired to a real observation source.
4
+ *
5
+ * §11B.3 calls runtime confirmation *"the core technical moat rather than the
6
+ * graph itself"*, and states the consequence plainly: *"a purely static
7
+ * code-graph tool is capped at R3 permanently."* The mechanism has existed in
8
+ * `@descryy/core` since it was built, and the two EARNED tables it writes
9
+ * (`observed_edges`, `edge_corrections`) have been in the store's schema since
10
+ * the store was first written — each with a comment explaining why they cannot
11
+ * be regenerated from source at any price. **Nothing read or wrote either one.**
12
+ * This is what makes the moat run.
13
+ *
14
+ * ## Why this producer
15
+ *
16
+ * `resolveObservedFrontendCaller` already does the hard half. It takes a real
17
+ * captured `fetch()` call-site stack, resolves its site of interest to a
18
+ * `FUNCTION` node, and checks that node against the structural candidate set the
19
+ * graph holds for the endpoint. Its two observed outcomes *are* two of §11B.3's
20
+ * three arrows, and needed only to be spoken in the vocabulary
21
+ * `applyRuntimeObservations` reads:
22
+ *
23
+ * | resolution outcome | arrow |
24
+ * | --- | --- |
25
+ * | `observed` | the graph already holds this `USES_API` edge below R4 — **promote it** |
26
+ * | `structural-observed-conflict` | a real node the structural side never named — **mint the edge at R4** (§11B.3's *"recall gap closed"*) |
27
+ *
28
+ * Everything else — no stack, an unresolvable frame, an ambiguous or missing
29
+ * symbol — produces **no observation at all**. Not an empty confirmation that
30
+ * looks like one; none.
31
+ *
32
+ * ## Why there is no denial arrow here, and why that is a decision
33
+ *
34
+ * `applyRuntimeObservations` accepts `held: false` — runtime saw that an edge
35
+ * did not hold — and records a correction that demotes the edge's confidence.
36
+ * **This producer never emits one, and must not.**
37
+ *
38
+ * A frontend caller resolution can establish that a call *happened*. It cannot
39
+ * establish that one did not: a page visit exercises one code path, and the
40
+ * absence of a captured stack for some other function is absence of evidence,
41
+ * not evidence of absence. Minting a denial from that would demote a correct
42
+ * edge on the strength of a route the run happened not to take — precisely the
43
+ * wrong-direction failure rule 2 exists to prevent, arriving through the one
44
+ * mechanism designed to make the graph *more* trustworthy.
45
+ *
46
+ * The denial arrow is real and stays available; it belongs to a producer that
47
+ * can actually establish non-occurrence (an exhaustive call-graph trace over a
48
+ * fully exercised path), not to this one.
49
+ *
50
+ * ## What this does not do
51
+ *
52
+ * - **It does not judge a finding.** Resolution has no opinion on confidence
53
+ * (RT-027). Nothing here reads or writes a finding, hypothesis or category.
54
+ * - **It does not decide staleness.** An R4-vs-R4 disagreement is reported by
55
+ * the core function as `staleR4` and passed through untouched.
56
+ * - **It does not invent a node.** That refusal is core's, and its `refused`
57
+ * list is passed through rather than swallowed.
58
+ */
59
+ import { applyRuntimeObservations, } from "@descryy/core";
60
+ import { resolveObservedFrontendCaller, } from "./observed-frontend-caller.js";
61
+ const EMPTY = {
62
+ promoted: [], created: [], confirmed: [], contradictions: [], staleR4: [], refused: [],
63
+ };
64
+ /**
65
+ * Resolve one observed frontend call and, when it genuinely observed something,
66
+ * record it as R4 evidence against the graph.
67
+ */
68
+ export function confirmObservedFrontendCaller(driver, input) {
69
+ const resolution = resolveObservedFrontendCaller(driver, input.endpointNodeId, input.stackTrace, input.repo, input.repoRoot === undefined ? {} : { repoRoot: input.repoRoot });
70
+ const observations = observationsFor(resolution, input.endpointNodeId);
71
+ if (observations.length === 0) {
72
+ // Nothing observed. Deliberately not a call with an empty list: an
73
+ // `adapter_runs` row would be minted for a run that witnessed nothing,
74
+ // which reads in the ledger exactly like a run that observed and found
75
+ // nothing to say. Those are different statements.
76
+ return { resolution, observations, confirmation: EMPTY };
77
+ }
78
+ const confirmation = applyRuntimeObservations(driver, {
79
+ runId: input.runId,
80
+ commitSha: input.commitSha,
81
+ observations,
82
+ });
83
+ return { resolution, observations, confirmation };
84
+ }
85
+ function observationsFor(resolution, endpointNodeId) {
86
+ if (resolution.outcome === "observed") {
87
+ return [
88
+ {
89
+ from: resolution.node.id,
90
+ to: endpointNodeId,
91
+ edgeType: "USES_API",
92
+ held: true,
93
+ detail: `A captured fetch() call-site stack resolved to ${resolution.node.name} ` +
94
+ `(${resolution.node.file ?? "unknown file"}), which the graph already names as a ` +
95
+ "structural caller of this endpoint.",
96
+ },
97
+ ];
98
+ }
99
+ if (resolution.outcome === "structural-observed-conflict") {
100
+ return [
101
+ {
102
+ from: resolution.observedNode.id,
103
+ to: endpointNodeId,
104
+ edgeType: "USES_API",
105
+ held: true,
106
+ detail: `A captured fetch() call-site stack resolved to ${resolution.observedNode.name} ` +
107
+ `(${resolution.observedNode.file ?? "unknown file"}), which static analysis did not name ` +
108
+ `as a caller of this endpoint (${resolution.structuralCandidates.length} structural ` +
109
+ "candidate(s) found, none of them this one). Recorded as observed rather than adjudicated.",
110
+ },
111
+ ];
112
+ }
113
+ // Every other outcome is a refusal or a purely structural answer. Neither is
114
+ // an observation, and neither becomes one by being written down.
115
+ return [];
116
+ }
117
+ //# sourceMappingURL=confirm-observed-caller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm-observed-caller.js","sourceRoot":"","sources":["../src/confirm-observed-caller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAGH,OAAO,EACL,wBAAwB,GAGzB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,6BAA6B,GAE9B,MAAM,+BAA+B,CAAC;AA4BvC,MAAM,KAAK,GAA8B;IACvC,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;CACvF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,MAAiB,EACjB,KAAiC;IAEjC,MAAM,UAAU,GAAG,6BAA6B,CAC9C,MAAM,EACN,KAAK,CAAC,cAAc,EACpB,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CACjE,CAAC;IAEF,MAAM,YAAY,GAAG,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IACvE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,mEAAmE;QACnE,uEAAuE;QACvE,uEAAuE;QACvE,kDAAkD;QAClD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAC3D,CAAC;IAED,MAAM,YAAY,GAAG,wBAAwB,CAAC,MAAM,EAAE;QACpD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,YAAY;KACb,CAAC,CAAC;IAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AACpD,CAAC;AAED,SAAS,eAAe,CACtB,UAA4C,EAC5C,cAAsB;IAEtB,IAAI,UAAU,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACtC,OAAO;YACL;gBACE,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE;gBACxB,EAAE,EAAE,cAAc;gBAClB,QAAQ,EAAE,UAAU;gBACpB,IAAI,EAAE,IAAI;gBACV,MAAM,EACJ,kDAAkD,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG;oBACzE,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,cAAc,wCAAwC;oBAClF,qCAAqC;aACxC;SACF,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,OAAO,KAAK,8BAA8B,EAAE,CAAC;QAC1D,OAAO;YACL;gBACE,IAAI,EAAE,UAAU,CAAC,YAAY,CAAC,EAAE;gBAChC,EAAE,EAAE,cAAc;gBAClB,QAAQ,EAAE,UAAU;gBACpB,IAAI,EAAE,IAAI;gBACV,MAAM,EACJ,kDAAkD,UAAU,CAAC,YAAY,CAAC,IAAI,GAAG;oBACjF,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,IAAI,cAAc,wCAAwC;oBAC1F,iCAAiC,UAAU,CAAC,oBAAoB,CAAC,MAAM,cAAc;oBACrF,2FAA2F;aAC9F;SACF,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,iEAAiE;IACjE,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Resolving a captured query's target table name (a real, observed string —
3
+ * `extractTargetTable`, `@descryhq-wq/runtime-database-observation`) to the
4
+ * `DATABASE_TABLE` node it names — the §10/§18 join `DatabaseQueryCollector`
5
+ * disclosed as missing since RT-141: real query capture, `graphNodeId`
6
+ * always null.
7
+ *
8
+ * **`DATABASE_TABLE` is workspace-scoped, not repo-scoped** (`adapter-sql`'s
9
+ * own `extract`/`adapter.ts`, DEC-054) — the same reason `resolveEndpointNode`
10
+ * (`endpoint.ts`, this package) takes no `repo` parameter: a migration can
11
+ * live in one repository and the service reading the table in another, and
12
+ * DEC-054 exists specifically so they still join. A runtime observation
13
+ * carries no repository at all for a bare table name — the observed
14
+ * process's own source may not even be one of the repos this graph indexed
15
+ * — so taking a `repo` filter here would be inventing a constraint the
16
+ * caller has no way to satisfy.
17
+ *
18
+ * **Unlike an endpoint, a table name is not a template.** No segment
19
+ * matching, no `{param}` — `DATABASE_TABLE.name` is the bare table name
20
+ * (`adapter-sql`'s `extract.ts`: `name: table.table`), so this is a plain
21
+ * equality match against every candidate, the simpler half of
22
+ * `resolveEndpointNode`'s own two-part job.
23
+ */
24
+ import type { IRNode } from "@descryy/ir";
25
+ import { type SqlDriver } from "@descryy/core";
26
+ export type DatabaseTableResolution = {
27
+ readonly outcome: "resolved";
28
+ readonly node: IRNode;
29
+ } | {
30
+ readonly outcome: "not-found";
31
+ readonly reason: string;
32
+ } | {
33
+ readonly outcome: "ambiguous";
34
+ readonly candidates: readonly IRNode[];
35
+ readonly reason: string;
36
+ };
37
+ export declare function resolveDatabaseTableNode(driver: SqlDriver, tableName: string, options?: {
38
+ readonly limit?: number;
39
+ }): DatabaseTableResolution;
40
+ //# sourceMappingURL=database-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-table.d.ts","sourceRoot":"","sources":["../src/database-table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAE5D,MAAM,MAAM,uBAAuB,GAC/B;IAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvG,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,uBAAuB,CA+BzB"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Resolving a captured query's target table name (a real, observed string —
3
+ * `extractTargetTable`, `@descryhq-wq/runtime-database-observation`) to the
4
+ * `DATABASE_TABLE` node it names — the §10/§18 join `DatabaseQueryCollector`
5
+ * disclosed as missing since RT-141: real query capture, `graphNodeId`
6
+ * always null.
7
+ *
8
+ * **`DATABASE_TABLE` is workspace-scoped, not repo-scoped** (`adapter-sql`'s
9
+ * own `extract`/`adapter.ts`, DEC-054) — the same reason `resolveEndpointNode`
10
+ * (`endpoint.ts`, this package) takes no `repo` parameter: a migration can
11
+ * live in one repository and the service reading the table in another, and
12
+ * DEC-054 exists specifically so they still join. A runtime observation
13
+ * carries no repository at all for a bare table name — the observed
14
+ * process's own source may not even be one of the repos this graph indexed
15
+ * — so taking a `repo` filter here would be inventing a constraint the
16
+ * caller has no way to satisfy.
17
+ *
18
+ * **Unlike an endpoint, a table name is not a template.** No segment
19
+ * matching, no `{param}` — `DATABASE_TABLE.name` is the bare table name
20
+ * (`adapter-sql`'s `extract.ts`: `name: table.table`), so this is a plain
21
+ * equality match against every candidate, the simpler half of
22
+ * `resolveEndpointNode`'s own two-part job.
23
+ */
24
+ import { nodesOfType } from "@descryy/core";
25
+ export function resolveDatabaseTableNode(driver, tableName, options = {}) {
26
+ const { nodes, truncated } = nodesOfType(driver, "DATABASE_TABLE", options.limit ?? 5000);
27
+ const matches = nodes.filter((node) => node.name === tableName);
28
+ if (matches.length === 0) {
29
+ return {
30
+ outcome: "not-found",
31
+ reason: `No DATABASE_TABLE node named "${tableName}".` +
32
+ (truncated
33
+ ? " The DATABASE_TABLE scan was truncated by the node budget, so this may be a coverage " +
34
+ "gap rather than a genuine absence."
35
+ : " Either no schema declares this table, or no SQL adapter has read the migration that " +
36
+ "creates it — a real gap to report rather than assume clean."),
37
+ };
38
+ }
39
+ if (matches.length > 1) {
40
+ return {
41
+ outcome: "ambiguous",
42
+ candidates: matches,
43
+ reason: `${matches.length} DATABASE_TABLE nodes are named "${tableName}" — ` +
44
+ `${matches.map((n) => `${n.attrs.schema ?? "?"}.${n.name}`).join(", ")}. ` +
45
+ "Two schemas naming the same table is real and not rare (a per-tenant schema pattern, " +
46
+ "or two workspaces this graph both indexed); picking one would be a guess this resolver " +
47
+ "has no basis for.",
48
+ };
49
+ }
50
+ return { outcome: "resolved", node: matches[0] };
51
+ }
52
+ //# sourceMappingURL=database-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-table.js","sourceRoot":"","sources":["../src/database-table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,WAAW,EAAkB,MAAM,eAAe,CAAC;AAO5D,MAAM,UAAU,wBAAwB,CACtC,MAAiB,EACjB,SAAiB,EACjB,UAAuC,EAAE;IAEzC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IAC1F,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAEhE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,OAAO,EAAE,WAAW;YACpB,MAAM,EACJ,iCAAiC,SAAS,IAAI;gBAC9C,CAAC,SAAS;oBACR,CAAC,CAAC,uFAAuF;wBACvF,oCAAoC;oBACtC,CAAC,CAAC,uFAAuF;wBACvF,6DAA6D,CAAC;SACrE,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,OAAO,EAAE,WAAW;YACpB,UAAU,EAAE,OAAO;YACnB,MAAM,EACJ,GAAG,OAAO,CAAC,MAAM,oCAAoC,SAAS,MAAM;gBACpE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAI,CAAC,CAAC,KAAK,CAAC,MAA6B,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBAClG,uFAAuF;gBACvF,yFAAyF;gBACzF,mBAAmB;SACtB,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,CAAC;AACpD,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Resolving observed HTTP evidence (a real request's method + literal path)
3
+ * to the `API_ENDPOINT` node it was served by — plan §12/§25 ("Runtime
4
+ * should be able to build an observed path such as FUNCTION → API_ROUTE →
5
+ * API_ENDPOINT → FUNCTION → DATABASE_TABLE, where the static graph and
6
+ * runtime evidence actually support those links").
7
+ *
8
+ * `API_ENDPOINT` is workspace-scoped, not repo-scoped (DEC-054) — it is
9
+ * deliberately the one join node two repositories mint identically with no
10
+ * shared code (DEC-115). That means, unlike a `FUNCTION` lookup, there is no
11
+ * "wrong repository" version of this node to accidentally pick: any
12
+ * `API_ENDPOINT` in the store is the one shared join point by construction,
13
+ * so this file takes no `repo`/`scope` parameter — adding one would be
14
+ * inventing a filter with nothing behind it to filter on.
15
+ *
16
+ * What this file *does* have to solve, that a bare identity hash cannot: a
17
+ * real request's URL is a literal (`/orders/5`), while the route that served
18
+ * it may have been minted from a parameterised template
19
+ * (`/orders/{param}`, per `normaliseEndpointPath`). Those hash to different
20
+ * ids, so resolution here is a segment-wise match against every candidate's
21
+ * *name*, not a single `getNode` by a computed id. That is also what makes
22
+ * "similar endpoint" (plan §38's own negative-control name) a real,
23
+ * representable outcome here rather than a hypothetical: a literal route
24
+ * (`GET /orders/active`) and a parameterised one (`GET /orders/{param}`) can
25
+ * both legitimately match one observed request, and this resolver reports
26
+ * that as `ambiguous` rather than guessing which one actually served it —
27
+ * the same discipline `resolveOneNode` (descry-core's MCP lookup) applies to
28
+ * a name search, one layer down at the network-evidence layer instead.
29
+ */
30
+ import { type IRNode } from "@descryy/ir";
31
+ import { type SqlDriver } from "@descryy/core";
32
+ export type EndpointResolution = {
33
+ readonly outcome: "resolved";
34
+ readonly node: IRNode;
35
+ } | {
36
+ readonly outcome: "not-found";
37
+ readonly reason: string;
38
+ } | {
39
+ readonly outcome: "ambiguous";
40
+ readonly candidates: readonly IRNode[];
41
+ readonly reason: string;
42
+ };
43
+ export declare function resolveEndpointNode(driver: SqlDriver, method: string, observedPath: string, options?: {
44
+ readonly limit?: number;
45
+ }): EndpointResolution;
46
+ /**
47
+ * Every `API_ENDPOINT` whose path shape matches `observedPath`, **regardless
48
+ * of method** — the query `resolveEndpointNode` deliberately does not answer
49
+ * on its own, since it filters by method first and a caller asking "does
50
+ * this path exist under a different method" needs the method filter removed
51
+ * entirely, not relaxed.
52
+ *
53
+ * Built for one caller (`@descryhq-wq/runtime-openapi-observation`'s "wrong
54
+ * method" vs "undocumented" distinction, checklist §15): a request whose
55
+ * exact method+path resolves to nothing is a different fact from one whose
56
+ * path resolves under some *other* method — the first says the operation
57
+ * was never declared, the second says it was declared and the request used
58
+ * the wrong verb. Conflating them would report "undocumented" for a request
59
+ * a contract-reading person would call a client bug, not a documentation
60
+ * gap.
61
+ *
62
+ * Ambiguity is not resolved here either — every shape-matching node is
63
+ * returned, and the caller decides what "more than one, across methods"
64
+ * means for its own question, the same "refuse rather than rank" split
65
+ * `resolveEndpointNode` already uses for its own single-method case.
66
+ */
67
+ export declare function resolveEndpointNodesByPath(driver: SqlDriver, observedPath: string, options?: {
68
+ readonly limit?: number;
69
+ }): {
70
+ readonly nodes: readonly IRNode[];
71
+ readonly truncated: boolean;
72
+ };
73
+ //# sourceMappingURL=endpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAsC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAE5D,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAavG,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,kBAAkB,CA2CpB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAapE"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Resolving observed HTTP evidence (a real request's method + literal path)
3
+ * to the `API_ENDPOINT` node it was served by — plan §12/§25 ("Runtime
4
+ * should be able to build an observed path such as FUNCTION → API_ROUTE →
5
+ * API_ENDPOINT → FUNCTION → DATABASE_TABLE, where the static graph and
6
+ * runtime evidence actually support those links").
7
+ *
8
+ * `API_ENDPOINT` is workspace-scoped, not repo-scoped (DEC-054) — it is
9
+ * deliberately the one join node two repositories mint identically with no
10
+ * shared code (DEC-115). That means, unlike a `FUNCTION` lookup, there is no
11
+ * "wrong repository" version of this node to accidentally pick: any
12
+ * `API_ENDPOINT` in the store is the one shared join point by construction,
13
+ * so this file takes no `repo`/`scope` parameter — adding one would be
14
+ * inventing a filter with nothing behind it to filter on.
15
+ *
16
+ * What this file *does* have to solve, that a bare identity hash cannot: a
17
+ * real request's URL is a literal (`/orders/5`), while the route that served
18
+ * it may have been minted from a parameterised template
19
+ * (`/orders/{param}`, per `normaliseEndpointPath`). Those hash to different
20
+ * ids, so resolution here is a segment-wise match against every candidate's
21
+ * *name*, not a single `getNode` by a computed id. That is also what makes
22
+ * "similar endpoint" (plan §38's own negative-control name) a real,
23
+ * representable outcome here rather than a hypothetical: a literal route
24
+ * (`GET /orders/active`) and a parameterised one (`GET /orders/{param}`) can
25
+ * both legitimately match one observed request, and this resolver reports
26
+ * that as `ambiguous` rather than guessing which one actually served it —
27
+ * the same discipline `resolveOneNode` (descry-core's MCP lookup) applies to
28
+ * a name search, one layer down at the network-evidence layer instead.
29
+ */
30
+ import { endpointQsp, normaliseEndpointPath } from "@descryy/ir";
31
+ import { nodesOfType } from "@descryy/core";
32
+ function pathSegments(path) {
33
+ // `endpointQsp`'s own qualified path is "METHOD /normalised/path" — split
34
+ // on "/" after the method prefix is stripped, same shape either side.
35
+ return normaliseEndpointPath(path).split("/");
36
+ }
37
+ function segmentsMatch(templateSegments, observedSegments) {
38
+ if (templateSegments.length !== observedSegments.length)
39
+ return false;
40
+ return templateSegments.every((segment, i) => segment === "{param}" || segment === observedSegments[i]);
41
+ }
42
+ export function resolveEndpointNode(driver, method, observedPath, options = {}) {
43
+ const methodUpper = method.toUpperCase();
44
+ const observedSegments = pathSegments(observedPath);
45
+ const prefix = `${methodUpper} `;
46
+ const { nodes, truncated } = nodesOfType(driver, "API_ENDPOINT", options.limit ?? 5000);
47
+ const matches = [];
48
+ for (const node of nodes) {
49
+ if (!node.name.startsWith(prefix))
50
+ continue;
51
+ const templateSegments = node.name.slice(prefix.length).split("/");
52
+ if (segmentsMatch(templateSegments, observedSegments))
53
+ matches.push(node);
54
+ }
55
+ const observed = endpointQsp(methodUpper, observedPath);
56
+ if (matches.length === 0) {
57
+ return {
58
+ outcome: "not-found",
59
+ reason: `No API_ENDPOINT node's shape matches ${observed}.` +
60
+ (truncated
61
+ ? " The API_ENDPOINT scan was truncated by the node budget, so this may be a coverage " +
62
+ "gap rather than a genuine absence."
63
+ : " Either no route was minted for this request, or it was, and this is a real gap to " +
64
+ "report rather than assume clean."),
65
+ };
66
+ }
67
+ if (matches.length > 1) {
68
+ return {
69
+ outcome: "ambiguous",
70
+ candidates: matches,
71
+ reason: `${matches.length} API_ENDPOINT nodes' shapes all match ${observed} — ` +
72
+ `${matches.map((n) => n.name).join(", ")}. This is the "similar endpoint" case (a literal ` +
73
+ "route and a parameterised one can both textually match one real request): this resolver " +
74
+ "has no router-precedence information to break the tie, so it refuses rather than guessing " +
75
+ "which one actually served the request.",
76
+ };
77
+ }
78
+ return { outcome: "resolved", node: matches[0] };
79
+ }
80
+ /**
81
+ * Every `API_ENDPOINT` whose path shape matches `observedPath`, **regardless
82
+ * of method** — the query `resolveEndpointNode` deliberately does not answer
83
+ * on its own, since it filters by method first and a caller asking "does
84
+ * this path exist under a different method" needs the method filter removed
85
+ * entirely, not relaxed.
86
+ *
87
+ * Built for one caller (`@descryhq-wq/runtime-openapi-observation`'s "wrong
88
+ * method" vs "undocumented" distinction, checklist §15): a request whose
89
+ * exact method+path resolves to nothing is a different fact from one whose
90
+ * path resolves under some *other* method — the first says the operation
91
+ * was never declared, the second says it was declared and the request used
92
+ * the wrong verb. Conflating them would report "undocumented" for a request
93
+ * a contract-reading person would call a client bug, not a documentation
94
+ * gap.
95
+ *
96
+ * Ambiguity is not resolved here either — every shape-matching node is
97
+ * returned, and the caller decides what "more than one, across methods"
98
+ * means for its own question, the same "refuse rather than rank" split
99
+ * `resolveEndpointNode` already uses for its own single-method case.
100
+ */
101
+ export function resolveEndpointNodesByPath(driver, observedPath, options = {}) {
102
+ const observedSegments = pathSegments(observedPath);
103
+ const { nodes, truncated } = nodesOfType(driver, "API_ENDPOINT", options.limit ?? 5000);
104
+ const matches = [];
105
+ for (const node of nodes) {
106
+ const spaceIndex = node.name.indexOf(" ");
107
+ if (spaceIndex === -1)
108
+ continue; // not this adapter's "METHOD /path" naming -- refuse rather than guess at a split
109
+ const templateSegments = node.name.slice(spaceIndex + 1).split("/");
110
+ if (segmentsMatch(templateSegments, observedSegments))
111
+ matches.push(node);
112
+ }
113
+ return { nodes: matches, truncated };
114
+ }
115
+ //# sourceMappingURL=endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The **first leg** of the path the product requires:
3
+ * `Frontend FUNCTION → API_ENDPOINT → API_ROUTE → Backend FUNCTION`.
4
+ *
5
+ * `RUNTIME-CHECKLIST.md` §11 states that path and its own boxes covered
6
+ * only the last three legs — the audit added a box for the first and marked
7
+ * it absent. The graph has had the edge all along: `adapter-typescript`
8
+ * emits `USES_API` from a frontend function to the endpoint it calls, read
9
+ * from source. Nothing correlated it.
10
+ *
11
+ * ---
12
+ *
13
+ * **This is a structural claim, and calling it anything else would be the
14
+ * central lie this project exists not to tell.**
15
+ *
16
+ * `USES_API` says *this function contains a call to that endpoint*. It does
17
+ * **not** say this function issued the request that was just observed. When
18
+ * three components call one endpoint, the graph names all three and the
19
+ * browser saw one — and nothing in a `NETWORK_REQUEST` says which. Playwright
20
+ * exposes an initiator chain that could narrow it; the network collector
21
+ * does not capture it today (§6 records that as a gap), and until it does,
22
+ * *which* caller ran is not something this repo knows.
23
+ *
24
+ * So the outcome vocabulary says so at the type level: a single caller is
25
+ * `sole-structural-caller`, never `resolved`. A reader who sees `resolved`
26
+ * elsewhere in this package is looking at an observation; here they are
27
+ * looking at the only candidate the code admits, which is a different and
28
+ * weaker fact even when it happens to be right.
29
+ *
30
+ * **Consequence for reliability, per the architecture's resolution cap:** a
31
+ * finding whose path rests on this leg is capped by the `USES_API` edge's
32
+ * own resolution, exactly as any other structural hop is. Extending the
33
+ * path does not upgrade the evidence.
34
+ */
35
+ import { type SqlDriver } from "@descryy/core";
36
+ import type { IRNode } from "@descryy/ir";
37
+ export type FrontendCallerResolution =
38
+ /** Exactly one frontend function declares a call to this endpoint. The only candidate — **not** proof that it is the one that ran. */
39
+ {
40
+ readonly outcome: "sole-structural-caller";
41
+ readonly node: IRNode;
42
+ readonly reason: string;
43
+ }
44
+ /** Several functions call this endpoint. The graph cannot say which one issued the observed request, and neither can this. */
45
+ | {
46
+ readonly outcome: "ambiguous";
47
+ readonly candidates: readonly IRNode[];
48
+ readonly reason: string;
49
+ }
50
+ /** No `USES_API` edge points at this endpoint — the caller is in code this adapter did not read, or is not a direct call at all. */
51
+ | {
52
+ readonly outcome: "not-found";
53
+ readonly reason: string;
54
+ };
55
+ /**
56
+ * Every frontend function the graph says calls this endpoint.
57
+ *
58
+ * Ambiguity is returned to the caller rather than ranked, the same way
59
+ * `resolveSymbolNode` and `resolveEndpointNode` refuse it. There is a
60
+ * tempting heuristic here — prefer the caller in the file the browser most
61
+ * recently loaded, or the one whose line number is nearest the event — and
62
+ * both are timing and locality standing in for causality, which §27's own
63
+ * rule forbids in one sentence: *similarity must never be treated as
64
+ * causality*.
65
+ */
66
+ export declare function resolveFrontendCallers(driver: SqlDriver, endpointNodeId: string): FrontendCallerResolution;
67
+ //# sourceMappingURL=frontend-caller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontend-caller.d.ts","sourceRoot":"","sources":["../src/frontend-caller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,MAAM,wBAAwB;AAClC,sIAAsI;AACpI;IAAE,QAAQ,CAAC,OAAO,EAAE,wBAAwB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAChG,8HAA8H;GAC5H;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACpG,oIAAoI;GAClI;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,GAAG,wBAAwB,CA2C1G"}