@descryy/mcp 0.6.0 → 0.7.1
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/action-handshake.d.ts +8 -75
- package/dist/action-handshake.d.ts.map +1 -1
- package/dist/action-handshake.js +9 -79
- package/dist/action-handshake.js.map +1 -1
- package/dist/bin/descry-mcp.d.ts +4 -15
- package/dist/bin/descry-mcp.d.ts.map +1 -1
- package/dist/bin/descry-mcp.js +12 -42
- package/dist/bin/descry-mcp.js.map +1 -1
- package/dist/browser/driver.d.ts +121 -224
- package/dist/browser/driver.d.ts.map +1 -1
- package/dist/browser/driver.js +9 -55
- package/dist/browser/driver.js.map +1 -1
- package/dist/browser/evidence.d.ts +10 -43
- package/dist/browser/evidence.d.ts.map +1 -1
- package/dist/browser/evidence.js +20 -54
- package/dist/browser/evidence.js.map +1 -1
- package/dist/browser/fake-driver.d.ts +12 -19
- package/dist/browser/fake-driver.d.ts.map +1 -1
- package/dist/browser/fake-driver.js +31 -26
- package/dist/browser/fake-driver.js.map +1 -1
- package/dist/browser/graph-write.d.ts +4 -45
- package/dist/browser/graph-write.d.ts.map +1 -1
- package/dist/browser/graph-write.js +8 -53
- package/dist/browser/graph-write.js.map +1 -1
- package/dist/browser/playwright-driver.d.ts +7 -91
- package/dist/browser/playwright-driver.d.ts.map +1 -1
- package/dist/browser/playwright-driver.js +59 -197
- package/dist/browser/playwright-driver.js.map +1 -1
- package/dist/browser/provider.d.ts +5 -34
- package/dist/browser/provider.d.ts.map +1 -1
- package/dist/browser/provider.js +4 -24
- package/dist/browser/provider.js.map +1 -1
- package/dist/browser/registry.d.ts +26 -106
- package/dist/browser/registry.d.ts.map +1 -1
- package/dist/browser/registry.js +20 -77
- package/dist/browser/registry.js.map +1 -1
- package/dist/browser/scenario-provenance.d.ts +23 -0
- package/dist/browser/scenario-provenance.d.ts.map +1 -0
- package/dist/browser/scenario-provenance.js +59 -0
- package/dist/browser/scenario-provenance.js.map +1 -0
- package/dist/browser/scenario-resolve.d.ts +10 -44
- package/dist/browser/scenario-resolve.d.ts.map +1 -1
- package/dist/browser/scenario-resolve.js +10 -41
- package/dist/browser/scenario-resolve.js.map +1 -1
- package/dist/browser/scenario-runner.d.ts +12 -70
- package/dist/browser/scenario-runner.d.ts.map +1 -1
- package/dist/browser/scenario-runner.js +30 -90
- package/dist/browser/scenario-runner.js.map +1 -1
- package/dist/browser/stack-parser.d.ts +4 -28
- package/dist/browser/stack-parser.d.ts.map +1 -1
- package/dist/browser/stack-parser.js +12 -39
- package/dist/browser/stack-parser.js.map +1 -1
- package/dist/browser/tool-support.d.ts +20 -67
- package/dist/browser/tool-support.d.ts.map +1 -1
- package/dist/browser/tool-support.js +21 -65
- package/dist/browser/tool-support.js.map +1 -1
- package/dist/browser/url-scheme.d.ts +14 -0
- package/dist/browser/url-scheme.d.ts.map +1 -0
- package/dist/browser/url-scheme.js +38 -0
- package/dist/browser/url-scheme.js.map +1 -0
- package/dist/cancellation.d.ts +11 -46
- package/dist/cancellation.d.ts.map +1 -1
- package/dist/cancellation.js +11 -46
- package/dist/cancellation.js.map +1 -1
- package/dist/capped.d.ts +9 -33
- package/dist/capped.d.ts.map +1 -1
- package/dist/capped.js +7 -27
- package/dist/capped.js.map +1 -1
- package/dist/disclosure-ledger.d.ts +6 -30
- package/dist/disclosure-ledger.d.ts.map +1 -1
- package/dist/disclosure-ledger.js +4 -26
- package/dist/disclosure-ledger.js.map +1 -1
- package/dist/index.d.ts +10 -26
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -17
- package/dist/index.js.map +1 -1
- package/dist/module-trust.d.ts +24 -0
- package/dist/module-trust.d.ts.map +1 -0
- package/dist/module-trust.js +60 -0
- package/dist/module-trust.js.map +1 -0
- package/dist/path-confinement.d.ts +31 -0
- package/dist/path-confinement.d.ts.map +1 -0
- package/dist/path-confinement.js +44 -0
- package/dist/path-confinement.js.map +1 -0
- package/dist/protocol.d.ts +10 -53
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +14 -60
- package/dist/protocol.js.map +1 -1
- package/dist/registry.d.ts +37 -58
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +88 -96
- package/dist/registry.js.map +1 -1
- package/dist/render.d.ts +89 -13
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +111 -16
- package/dist/render.js.map +1 -1
- package/dist/runtime-registry.d.ts +7 -66
- package/dist/runtime-registry.d.ts.map +1 -1
- package/dist/runtime-registry.js +39 -114
- package/dist/runtime-registry.js.map +1 -1
- package/dist/scenarios/index.d.ts +1 -1
- package/dist/scenarios/index.d.ts.map +1 -1
- package/dist/scenarios/index.js +1 -1
- package/dist/scenarios/index.js.map +1 -1
- package/dist/scenarios/parse.d.ts +4 -18
- package/dist/scenarios/parse.d.ts.map +1 -1
- package/dist/scenarios/parse.js +14 -34
- package/dist/scenarios/parse.js.map +1 -1
- package/dist/scenarios/scenario.d.ts +18 -74
- package/dist/scenarios/scenario.d.ts.map +1 -1
- package/dist/scenarios/scenario.js +7 -34
- package/dist/scenarios/scenario.js.map +1 -1
- package/dist/scenarios/storage.d.ts +11 -41
- package/dist/scenarios/storage.d.ts.map +1 -1
- package/dist/scenarios/storage.js +57 -47
- package/dist/scenarios/storage.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +69 -19
- package/dist/server.js.map +1 -1
- package/dist/session.d.ts +90 -259
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +136 -250
- package/dist/session.js.map +1 -1
- package/dist/tools/analyze.d.ts +32 -118
- package/dist/tools/analyze.d.ts.map +1 -1
- package/dist/tools/analyze.js +65 -186
- package/dist/tools/analyze.js.map +1 -1
- package/dist/tools/browser-click.d.ts +3 -21
- package/dist/tools/browser-click.d.ts.map +1 -1
- package/dist/tools/browser-click.js +10 -31
- package/dist/tools/browser-click.js.map +1 -1
- package/dist/tools/browser-close-session.d.ts +4 -13
- package/dist/tools/browser-close-session.d.ts.map +1 -1
- package/dist/tools/browser-close-session.js +4 -13
- package/dist/tools/browser-close-session.js.map +1 -1
- package/dist/tools/browser-fill.d.ts +5 -36
- package/dist/tools/browser-fill.d.ts.map +1 -1
- package/dist/tools/browser-fill.js +9 -44
- package/dist/tools/browser-fill.js.map +1 -1
- package/dist/tools/browser-navigate.d.ts +6 -27
- package/dist/tools/browser-navigate.d.ts.map +1 -1
- package/dist/tools/browser-navigate.js +6 -23
- package/dist/tools/browser-navigate.js.map +1 -1
- package/dist/tools/browser-run-scenario.d.ts +5 -31
- package/dist/tools/browser-run-scenario.d.ts.map +1 -1
- package/dist/tools/browser-run-scenario.js +10 -46
- package/dist/tools/browser-run-scenario.js.map +1 -1
- package/dist/tools/browser-save-scenario.d.ts +3 -28
- package/dist/tools/browser-save-scenario.d.ts.map +1 -1
- package/dist/tools/browser-save-scenario.js +47 -84
- package/dist/tools/browser-save-scenario.js.map +1 -1
- package/dist/tools/browser-snapshot.d.ts +6 -39
- package/dist/tools/browser-snapshot.d.ts.map +1 -1
- package/dist/tools/browser-snapshot.js +4 -31
- package/dist/tools/browser-snapshot.js.map +1 -1
- package/dist/tools/browser-start-session.d.ts +4 -23
- package/dist/tools/browser-start-session.d.ts.map +1 -1
- package/dist/tools/browser-start-session.js +145 -56
- package/dist/tools/browser-start-session.js.map +1 -1
- package/dist/tools/browser-type.d.ts +5 -35
- package/dist/tools/browser-type.d.ts.map +1 -1
- package/dist/tools/browser-type.js +10 -45
- package/dist/tools/browser-type.js.map +1 -1
- package/dist/tools/contracts.d.ts +9 -86
- package/dist/tools/contracts.d.ts.map +1 -1
- package/dist/tools/contracts.js +24 -80
- package/dist/tools/contracts.js.map +1 -1
- package/dist/tools/cross-pr.d.ts +42 -30
- package/dist/tools/cross-pr.d.ts.map +1 -1
- package/dist/tools/cross-pr.js +81 -62
- package/dist/tools/cross-pr.js.map +1 -1
- package/dist/tools/git-diff.d.ts +18 -2
- package/dist/tools/git-diff.d.ts.map +1 -1
- package/dist/tools/git-diff.js +118 -26
- package/dist/tools/git-diff.js.map +1 -1
- package/dist/tools/git-history.d.ts +5 -16
- package/dist/tools/git-history.d.ts.map +1 -1
- package/dist/tools/git-history.js +3 -10
- package/dist/tools/git-history.js.map +1 -1
- package/dist/tools/history.d.ts +4 -33
- package/dist/tools/history.d.ts.map +1 -1
- package/dist/tools/history.js +6 -31
- package/dist/tools/history.js.map +1 -1
- package/dist/tools/impact.d.ts +7 -51
- package/dist/tools/impact.d.ts.map +1 -1
- package/dist/tools/impact.js +15 -67
- package/dist/tools/impact.js.map +1 -1
- package/dist/tools/index.d.ts +3 -8
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/kit.d.ts +66 -113
- package/dist/tools/kit.d.ts.map +1 -1
- package/dist/tools/kit.js +60 -28
- package/dist/tools/kit.js.map +1 -1
- package/dist/tools/link-workspace.d.ts +7 -45
- package/dist/tools/link-workspace.d.ts.map +1 -1
- package/dist/tools/link-workspace.js +10 -48
- package/dist/tools/link-workspace.js.map +1 -1
- package/dist/tools/lookup.d.ts +4 -14
- package/dist/tools/lookup.d.ts.map +1 -1
- package/dist/tools/lookup.js +4 -14
- package/dist/tools/lookup.js.map +1 -1
- package/dist/tools/mark-incident.d.ts +7 -54
- package/dist/tools/mark-incident.d.ts.map +1 -1
- package/dist/tools/mark-incident.js +15 -68
- package/dist/tools/mark-incident.js.map +1 -1
- package/dist/tools/observe-runtime.d.ts +27 -210
- package/dist/tools/observe-runtime.d.ts.map +1 -1
- package/dist/tools/observe-runtime.js +273 -434
- package/dist/tools/observe-runtime.js.map +1 -1
- package/dist/tools/observe-tests.d.ts +9 -100
- package/dist/tools/observe-tests.d.ts.map +1 -1
- package/dist/tools/observe-tests.js +74 -152
- package/dist/tools/observe-tests.js.map +1 -1
- package/dist/tools/pr-analysis.d.ts +18 -2
- package/dist/tools/pr-analysis.d.ts.map +1 -1
- package/dist/tools/pr-analysis.js +73 -23
- package/dist/tools/pr-analysis.js.map +1 -1
- package/dist/tools/pre-push.d.ts +74 -16
- package/dist/tools/pre-push.d.ts.map +1 -1
- package/dist/tools/pre-push.js +152 -51
- package/dist/tools/pre-push.js.map +1 -1
- package/dist/tools/propagation.d.ts +11 -53
- package/dist/tools/propagation.d.ts.map +1 -1
- package/dist/tools/propagation.js +17 -58
- package/dist/tools/propagation.js.map +1 -1
- package/dist/tools/questions.d.ts +13 -63
- package/dist/tools/questions.d.ts.map +1 -1
- package/dist/tools/questions.js +33 -105
- package/dist/tools/questions.js.map +1 -1
- package/dist/tools/refusal-fetch.d.ts +4 -40
- package/dist/tools/refusal-fetch.d.ts.map +1 -1
- package/dist/tools/refusal-fetch.js +4 -40
- package/dist/tools/refusal-fetch.js.map +1 -1
- package/dist/tools/runtime-incident.d.ts +4 -63
- package/dist/tools/runtime-incident.d.ts.map +1 -1
- package/dist/tools/runtime-incident.js +10 -87
- package/dist/tools/runtime-incident.js.map +1 -1
- package/dist/tools/scope.d.ts +7 -25
- package/dist/tools/scope.d.ts.map +1 -1
- package/dist/tools/scope.js +10 -29
- package/dist/tools/scope.js.map +1 -1
- package/dist/tools/similar-incidents.d.ts +11 -86
- package/dist/tools/similar-incidents.d.ts.map +1 -1
- package/dist/tools/similar-incidents.js +7 -71
- package/dist/tools/similar-incidents.js.map +1 -1
- package/dist/tools/validate.d.ts +29 -70
- package/dist/tools/validate.d.ts.map +1 -1
- package/dist/tools/validate.js +141 -85
- package/dist/tools/validate.js.map +1 -1
- package/dist/tools/verification-status.d.ts +9 -64
- package/dist/tools/verification-status.d.ts.map +1 -1
- package/dist/tools/verification-status.js +9 -62
- package/dist/tools/verification-status.js.map +1 -1
- package/dist/tools/verify-claim.d.ts +5 -52
- package/dist/tools/verify-claim.d.ts.map +1 -1
- package/dist/tools/verify-claim.js +6 -56
- package/dist/tools/verify-claim.js.map +1 -1
- package/dist/transport.d.ts +15 -52
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +16 -60
- package/dist/transport.js.map +1 -1
- package/package.json +40 -22
package/dist/tools/analyze.d.ts
CHANGED
|
@@ -1,48 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* never told about, and this is where the gaps become known.
|
|
7
|
-
*
|
|
8
|
-
* ## What is disclosed, and why each one earns its line
|
|
9
|
-
*
|
|
10
|
-
* - **Sources that would not load.** "No problem found in your Python service"
|
|
11
|
-
* and "your Python adapter did not import" are different statements (§20.2).
|
|
12
|
-
* - **Sources that loaded and did not claim the repository.** The same
|
|
13
|
-
* distinction, one level up: an unanalysed language is *not analysable*, not
|
|
14
|
-
* clean.
|
|
15
|
-
* - **The resolution each source reached.** A run that degraded to R0 because a
|
|
16
|
-
* virtualenv was missing produces a graph that looks identical to a healthy
|
|
17
|
-
* one until you read this number. Principle 3 then caps everything above it.
|
|
18
|
-
* - **Identity collisions.** Two things arrived under one id. There is no
|
|
19
|
-
* correct merge, so the builder reports rather than picks (DEC-024).
|
|
20
|
-
* - **Evicted files.** Rows a previous run owned and this one did not re-supply.
|
|
21
|
-
* They are gone from the graph; a query over them will now find nothing, and
|
|
22
|
-
* nothing would otherwise say why.
|
|
23
|
-
* - **The workspace join.** Zero cross-repo joins looks exactly like success — and, on the ordinary
|
|
24
|
-
* single-repository run every shipped call actually makes, is the *only* value possible, which is
|
|
25
|
-
* narrated too (`crossRepoJoinNote`) rather than left for a reader to infer from `repos.length`.
|
|
26
|
-
*
|
|
27
|
-
* ## The repo identity warning
|
|
28
|
-
*
|
|
29
|
-
* With no `.descry/config.json`, `repo` defaults to the directory name — and
|
|
30
|
-
* every repo-scoped node id is a hash over it. Clone into a differently-named
|
|
31
|
-
* folder and every id changes, which silently destroys incident links and
|
|
32
|
-
* `CHANGES_WITH` weights. That is DEC-004's failure arriving through the one
|
|
33
|
-
* field a default cannot get right, so it is stated on every unconfigured run.
|
|
34
|
-
*/
|
|
1
|
+
/** `analyze` — the only tool that writes to the graph. Disclosures matter most: a
|
|
2
|
+
* query can't report a gap it wasn't told about. Discloses: sources that failed or
|
|
3
|
+
* didn't claim the repo (§20.2 — not-analysable ≠ clean), each source's resolution
|
|
4
|
+
* reached (caps reliability, rule 3), id collisions (DEC-024), evicted files, and the
|
|
5
|
+
* cross-repo join count. No config → `repo` defaults to dir name, hashed into every id (DEC-004). */
|
|
35
6
|
import type { IRBatch, UnresolvedRef } from "@descryy/ir";
|
|
36
7
|
import type { BuildResult, JoinMetric, StoreCounts } from "@descryy/core";
|
|
37
8
|
import { type ToolDefinition } from "./kit.ts";
|
|
38
|
-
import { type
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
* `reachedResolution` is the number principle 3 caps everything above it by. A
|
|
43
|
-
* run that degraded to R0 because a dependency was missing produces a graph
|
|
44
|
-
* that looks identical to a healthy one until this field is read.
|
|
45
|
-
*/
|
|
9
|
+
import { type LoadedSource } from "../registry.ts";
|
|
10
|
+
export { configDriftNote } from "../session.ts";
|
|
11
|
+
/** What one source read, and how well. `reachedResolution` is what rule 3 caps everything
|
|
12
|
+
* above it by — a run degraded to R0 looks identical to a healthy one until this is read. */
|
|
46
13
|
export interface SourceRun {
|
|
47
14
|
readonly source: string;
|
|
48
15
|
readonly files: number;
|
|
@@ -50,55 +17,34 @@ export interface SourceRun {
|
|
|
50
17
|
readonly edges: number;
|
|
51
18
|
/** Refusal-ledger rows: gaps this source disclosed rather than guessed at. */
|
|
52
19
|
readonly unresolved: number;
|
|
53
|
-
/**
|
|
54
|
-
*
|
|
55
|
-
* entirely, not confirmed clean. Never counted in `files`; see
|
|
56
|
-
* `IRBatch.skippedFiles`.
|
|
57
|
-
*/
|
|
20
|
+
/** Files attempted but not parsed — absent from the graph, not confirmed clean. Never
|
|
21
|
+
* counted in `files`; see `IRBatch.skippedFiles`. */
|
|
58
22
|
readonly skippedFiles: number;
|
|
59
23
|
readonly reachedResolution: number;
|
|
60
24
|
/** Wall-clock time this source took, including the git-history reader. */
|
|
61
25
|
readonly ms: number;
|
|
62
26
|
}
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* `normaliseBatch` — every batch's gatekeeper on the way to the store — treats
|
|
67
|
-
* `skippedFiles` and `unresolved` as absent-means-none, and says why in its own
|
|
68
|
-
* comment: absent is what a producer not yet updated to report them sends. That
|
|
69
|
-
* is a deliberate compatibility promise to adapters compiled against an older
|
|
70
|
-
* `@descryy/ir`, and adapters are versioned and released on their own cadence
|
|
71
|
-
* precisely so that can happen.
|
|
72
|
-
*
|
|
73
|
-
* This function is that promise, applied one layer earlier. `analyze` used to
|
|
74
|
-
* read `.length` off both directly, which meant an adapter the Normaliser would
|
|
75
|
-
* have happily accepted crashed the run before it ever got there — reported as
|
|
76
|
-
* the *adapter* failing, taking a whole language into "not analysable". A real
|
|
77
|
-
* shipped adapter did exactly that while returning over a thousand perfectly
|
|
78
|
-
* good nodes.
|
|
79
|
-
*
|
|
80
|
-
* Absent and malformed stay different, which is the line the Normaliser draws
|
|
81
|
-
* too: a missing field is an older producer, a field holding a string is a
|
|
82
|
-
* broken one, and defaulting the second away would hide a real defect.
|
|
83
|
-
*/
|
|
27
|
+
/** `skippedFiles`/`unresolved`: absent means an adapter compiled against an older
|
|
28
|
+
* `@descryy/ir`, not malformed — a real adapter once crashed here on `.length` of
|
|
29
|
+
* undefined despite returning 1000+ good nodes. Absent ⇒ old producer; wrong type ⇒ broken, never defaulted away. */
|
|
84
30
|
export declare function optionalBatchLists(batch: IRBatch): {
|
|
85
31
|
readonly skippedFiles: IRBatch["skippedFiles"];
|
|
86
32
|
readonly unresolved: IRBatch["unresolved"];
|
|
87
33
|
};
|
|
34
|
+
/** Distinguishes "the adapter failed" from "Descry's own code broke handling its
|
|
35
|
+
* output" — before this, a `TypeError` thrown in this file was reported as the
|
|
36
|
+
* adapter failing, sending users to debug working code instead of reporting our bug. */
|
|
88
37
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* The distinction is not cosmetic. "That adapter could not read this" tells a
|
|
98
|
-
* user to look at their own toolchain; "Descry broke" tells them to report a
|
|
99
|
-
* bug. Sending the second as the first spends the user's time on the wrong
|
|
100
|
-
* thing and hides the defect from us.
|
|
38
|
+
* F2 (UAT phase 4 F3 / Part 13 §13.3.2): which build actually ran. A bare
|
|
39
|
+
* specifier can resolve to more than one installed copy with the same
|
|
40
|
+
* name — CJS resolution walks upward through `node_modules`, so a stray
|
|
41
|
+
* install above the repository silently wins over the intended one, and
|
|
42
|
+
* `producedBy` alone cannot tell them apart (it carries the module's own
|
|
43
|
+
* self-declared version, which can drift from what actually shipped).
|
|
44
|
+
* This is the disclosure that makes "why are my results different from
|
|
45
|
+
* yours" answerable instead of a debugging session.
|
|
101
46
|
*/
|
|
47
|
+
export declare function sourceProvenanceNote(entry: LoadedSource): string;
|
|
102
48
|
export declare function sourceFailureNote(sourceId: string, error: unknown, phase: "emit" | "engine"): string;
|
|
103
49
|
export interface AnalyzeData {
|
|
104
50
|
readonly repo: string;
|
|
@@ -147,49 +93,17 @@ export interface AnalyzeData {
|
|
|
147
93
|
readonly evictedFiles: number;
|
|
148
94
|
};
|
|
149
95
|
}
|
|
150
|
-
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* sources this call just read could not resolve, so it is a fresh
|
|
154
|
-
* population every run rather than accumulated history, and honestly
|
|
155
|
-
* scoped to "what this call found" the way the field's own contract asks.
|
|
156
|
-
*
|
|
157
|
-
* `undefined` on zero rows — the envelope's `refusals` stays `null` rather
|
|
158
|
-
* than carrying a summary with no exemplar or handle to show (matching
|
|
159
|
-
* `summariseRefusals`'s own `count === 0` shape one level up).
|
|
160
|
-
*/
|
|
96
|
+
/** §5.4's `refusals` field for this run only, not the graph's whole ledger
|
|
97
|
+
* (`refusal_fetch`'s job) — a fresh population per call, honestly scoped to what
|
|
98
|
+
* this run found. `undefined` on zero rows so `refusals` stays `null`, not an empty summary. */
|
|
161
99
|
export declare function refusalSummaryField(unresolved: readonly UnresolvedRef[]): {
|
|
162
100
|
readonly count: number;
|
|
163
101
|
readonly exemplar: string;
|
|
164
102
|
readonly handle: string;
|
|
165
103
|
} | undefined;
|
|
166
|
-
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* hand edit — changes the file on disk without this process ever knowing, and
|
|
170
|
-
* without this check the notes below would tell the agent to add a "sources"
|
|
171
|
-
* array that the file has actually had since the write. Comparing the two
|
|
172
|
-
* turns a misleading "still not configured" into an accurate "restart to pick
|
|
173
|
-
* this up".
|
|
174
|
-
*/
|
|
175
|
-
export declare function configDriftNote(onDisk: DescryConfig | null, loaded: DescryConfig): string | undefined;
|
|
176
|
-
/**
|
|
177
|
-
* The single-repo half of the joins disclosure — UAT round 3, second-look
|
|
178
|
-
* item's other half.
|
|
179
|
-
*
|
|
180
|
-
* `build.ts`'s own `NO_CROSS_REPO_JOIN` warning (folded into `notes` just
|
|
181
|
-
* above this function's call site) already narrates the alarming case: two
|
|
182
|
-
* or more repositories that emitted a workspace-scoped type and none of it
|
|
183
|
-
* joined. What it does not narrate is the ordinary case — every `analyze`
|
|
184
|
-
* call in the shipped product passes exactly one repository's batches, so
|
|
185
|
-
* every entry in `built.crossRepoJoins` has `crossRepoJoinPossible: false`
|
|
186
|
-
* and `suppliedByTwoOrMoreRepos: 0` by construction, not by failure. Left
|
|
187
|
-
* un-narrated, `{ total: 48, suppliedByTwoOrMoreRepos: 0 }` sitting beside a
|
|
188
|
-
* disclosure about 55 unrelated within-repo edges having just succeeded
|
|
189
|
-
* reads as a failure of the very thing that disclosure said worked. This
|
|
190
|
-
* states outright that one repository was in scope, so a reader is not left
|
|
191
|
-
* to infer it from `repos.length` themselves.
|
|
192
|
-
*/
|
|
104
|
+
/** Single-repo half of the joins disclosure. In the ordinary case — one repo in scope —
|
|
105
|
+
* every join metric's `suppliedByTwoOrMoreRepos: 0` looks like `NO_CROSS_REPO_JOIN`'s
|
|
106
|
+
* failure case; this states outright it's just scope, not a failed join. */
|
|
193
107
|
export declare function crossRepoJoinNote(joins: readonly JoinMetric[]): string | undefined;
|
|
194
108
|
export declare const analyzeTool: ToolDefinition;
|
|
195
109
|
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/tools/analyze.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/tools/analyze.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/analyze.js
CHANGED
|
@@ -1,63 +1,18 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* never told about, and this is where the gaps become known.
|
|
7
|
-
*
|
|
8
|
-
* ## What is disclosed, and why each one earns its line
|
|
9
|
-
*
|
|
10
|
-
* - **Sources that would not load.** "No problem found in your Python service"
|
|
11
|
-
* and "your Python adapter did not import" are different statements (§20.2).
|
|
12
|
-
* - **Sources that loaded and did not claim the repository.** The same
|
|
13
|
-
* distinction, one level up: an unanalysed language is *not analysable*, not
|
|
14
|
-
* clean.
|
|
15
|
-
* - **The resolution each source reached.** A run that degraded to R0 because a
|
|
16
|
-
* virtualenv was missing produces a graph that looks identical to a healthy
|
|
17
|
-
* one until you read this number. Principle 3 then caps everything above it.
|
|
18
|
-
* - **Identity collisions.** Two things arrived under one id. There is no
|
|
19
|
-
* correct merge, so the builder reports rather than picks (DEC-024).
|
|
20
|
-
* - **Evicted files.** Rows a previous run owned and this one did not re-supply.
|
|
21
|
-
* They are gone from the graph; a query over them will now find nothing, and
|
|
22
|
-
* nothing would otherwise say why.
|
|
23
|
-
* - **The workspace join.** Zero cross-repo joins looks exactly like success — and, on the ordinary
|
|
24
|
-
* single-repository run every shipped call actually makes, is the *only* value possible, which is
|
|
25
|
-
* narrated too (`crossRepoJoinNote`) rather than left for a reader to infer from `repos.length`.
|
|
26
|
-
*
|
|
27
|
-
* ## The repo identity warning
|
|
28
|
-
*
|
|
29
|
-
* With no `.descry/config.json`, `repo` defaults to the directory name — and
|
|
30
|
-
* every repo-scoped node id is a hash over it. Clone into a differently-named
|
|
31
|
-
* folder and every id changes, which silently destroys incident links and
|
|
32
|
-
* `CHANGES_WITH` weights. That is DEC-004's failure arriving through the one
|
|
33
|
-
* field a default cannot get right, so it is stated on every unconfigured run.
|
|
34
|
-
*/
|
|
35
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
/** `analyze` — the only tool that writes to the graph. Disclosures matter most: a
|
|
2
|
+
* query can't report a gap it wasn't told about. Discloses: sources that failed or
|
|
3
|
+
* didn't claim the repo (§20.2 — not-analysable ≠ clean), each source's resolution
|
|
4
|
+
* reached (caps reliability, rule 3), id collisions (DEC-024), evicted files, and the
|
|
5
|
+
* cross-repo join count. No config → `repo` defaults to dir name, hashed into every id (DEC-004). */
|
|
36
6
|
import { applyConfirmedFacts, buildGraph, counts, createConfirmedIncidentSource, createGitSource, mintEdgesFromConfirmedFacts, MINT_PRODUCED_BY, persistGraph, summariseRefusals, } from "@descryy/core";
|
|
37
7
|
import { answer, ToolInputError } from "./kit.js";
|
|
38
8
|
import { detectSources, loadSources } from "../registry.js";
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* is a deliberate compatibility promise to adapters compiled against an older
|
|
47
|
-
* `@descryy/ir`, and adapters are versioned and released on their own cadence
|
|
48
|
-
* precisely so that can happen.
|
|
49
|
-
*
|
|
50
|
-
* This function is that promise, applied one layer earlier. `analyze` used to
|
|
51
|
-
* read `.length` off both directly, which meant an adapter the Normaliser would
|
|
52
|
-
* have happily accepted crashed the run before it ever got there — reported as
|
|
53
|
-
* the *adapter* failing, taking a whole language into "not analysable". A real
|
|
54
|
-
* shipped adapter did exactly that while returning over a thousand perfectly
|
|
55
|
-
* good nodes.
|
|
56
|
-
*
|
|
57
|
-
* Absent and malformed stay different, which is the line the Normaliser draws
|
|
58
|
-
* too: a missing field is an older producer, a field holding a string is a
|
|
59
|
-
* broken one, and defaulting the second away would hide a real defect.
|
|
60
|
-
*/
|
|
9
|
+
// Re-exported for `analyze.test.ts`, which covers this pure helper in isolation.
|
|
10
|
+
// The check itself now runs centrally in `server.ts` (13.3.16 / N2 steps 2-3) —
|
|
11
|
+
// every reply discloses a stale config, not only this tool's.
|
|
12
|
+
export { configDriftNote } from "../session.js";
|
|
13
|
+
/** `skippedFiles`/`unresolved`: absent means an adapter compiled against an older
|
|
14
|
+
* `@descryy/ir`, not malformed — a real adapter once crashed here on `.length` of
|
|
15
|
+
* undefined despite returning 1000+ good nodes. Absent ⇒ old producer; wrong type ⇒ broken, never defaulted away. */
|
|
61
16
|
export function optionalBatchLists(batch) {
|
|
62
17
|
const read = (value, field) => {
|
|
63
18
|
if (value === undefined || value === null)
|
|
@@ -72,20 +27,26 @@ export function optionalBatchLists(batch) {
|
|
|
72
27
|
unresolved: read(batch.unresolved, "unresolved"),
|
|
73
28
|
};
|
|
74
29
|
}
|
|
30
|
+
/** Distinguishes "the adapter failed" from "Descry's own code broke handling its
|
|
31
|
+
* output" — before this, a `TypeError` thrown in this file was reported as the
|
|
32
|
+
* adapter failing, sending users to debug working code instead of reporting our bug. */
|
|
75
33
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* The distinction is not cosmetic. "That adapter could not read this" tells a
|
|
85
|
-
* user to look at their own toolchain; "Descry broke" tells them to report a
|
|
86
|
-
* bug. Sending the second as the first spends the user's time on the wrong
|
|
87
|
-
* thing and hides the defect from us.
|
|
34
|
+
* F2 (UAT phase 4 F3 / Part 13 §13.3.2): which build actually ran. A bare
|
|
35
|
+
* specifier can resolve to more than one installed copy with the same
|
|
36
|
+
* name — CJS resolution walks upward through `node_modules`, so a stray
|
|
37
|
+
* install above the repository silently wins over the intended one, and
|
|
38
|
+
* `producedBy` alone cannot tell them apart (it carries the module's own
|
|
39
|
+
* self-declared version, which can drift from what actually shipped).
|
|
40
|
+
* This is the disclosure that makes "why are my results different from
|
|
41
|
+
* yours" answerable instead of a debugging session.
|
|
88
42
|
*/
|
|
43
|
+
export function sourceProvenanceNote(entry) {
|
|
44
|
+
const version = entry.packageVersion ?? "unknown version";
|
|
45
|
+
const location = entry.resolvedPath !== null
|
|
46
|
+
? `resolved from ${entry.resolvedPath} (${entry.via === "repo" ? "the scanned repository" : "this server's own module closure"})`
|
|
47
|
+
: "resolved via this server's own module closure (the exact path could not be determined)";
|
|
48
|
+
return `${entry.source.id} — ${entry.spec.module}@${version}, ${location}.`;
|
|
49
|
+
}
|
|
89
50
|
export function sourceFailureNote(sourceId, error, phase) {
|
|
90
51
|
const message = error instanceof Error ? error.message : String(error);
|
|
91
52
|
return phase === "emit"
|
|
@@ -112,63 +73,18 @@ const SCHEMA = {
|
|
|
112
73
|
},
|
|
113
74
|
additionalProperties: false,
|
|
114
75
|
};
|
|
115
|
-
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* sources this call just read could not resolve, so it is a fresh
|
|
119
|
-
* population every run rather than accumulated history, and honestly
|
|
120
|
-
* scoped to "what this call found" the way the field's own contract asks.
|
|
121
|
-
*
|
|
122
|
-
* `undefined` on zero rows — the envelope's `refusals` stays `null` rather
|
|
123
|
-
* than carrying a summary with no exemplar or handle to show (matching
|
|
124
|
-
* `summariseRefusals`'s own `count === 0` shape one level up).
|
|
125
|
-
*/
|
|
76
|
+
/** §5.4's `refusals` field for this run only, not the graph's whole ledger
|
|
77
|
+
* (`refusal_fetch`'s job) — a fresh population per call, honestly scoped to what
|
|
78
|
+
* this run found. `undefined` on zero rows so `refusals` stays `null`, not an empty summary. */
|
|
126
79
|
export function refusalSummaryField(unresolved) {
|
|
127
80
|
const summary = summariseRefusals(unresolved);
|
|
128
81
|
if (summary.count === 0 || summary.exemplar === null || summary.handle === null)
|
|
129
82
|
return undefined;
|
|
130
83
|
return { count: summary.count, exemplar: summary.exemplar, handle: summary.handle };
|
|
131
84
|
}
|
|
132
|
-
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* hand edit — changes the file on disk without this process ever knowing, and
|
|
136
|
-
* without this check the notes below would tell the agent to add a "sources"
|
|
137
|
-
* array that the file has actually had since the write. Comparing the two
|
|
138
|
-
* turns a misleading "still not configured" into an accurate "restart to pick
|
|
139
|
-
* this up".
|
|
140
|
-
*/
|
|
141
|
-
export function configDriftNote(onDisk, loaded) {
|
|
142
|
-
if (onDisk === null)
|
|
143
|
-
return undefined;
|
|
144
|
-
const changed = onDisk.configPath !== loaded.configPath ||
|
|
145
|
-
onDisk.workspace !== loaded.workspace ||
|
|
146
|
-
onDisk.sources.length !== loaded.sources.length;
|
|
147
|
-
if (!changed)
|
|
148
|
-
return undefined;
|
|
149
|
-
return ("The on-disk .descry/config.json no longer matches what this server loaded at startup. " +
|
|
150
|
-
"Configuration is read once per process, not on every call (session.ts) — this run is still " +
|
|
151
|
-
"using the configuration this server started with, not the current file. Restart the MCP " +
|
|
152
|
-
"server for on-disk changes to take effect; the notes below describe the stale, running " +
|
|
153
|
-
"configuration, not what is actually on disk now.");
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* The single-repo half of the joins disclosure — UAT round 3, second-look
|
|
157
|
-
* item's other half.
|
|
158
|
-
*
|
|
159
|
-
* `build.ts`'s own `NO_CROSS_REPO_JOIN` warning (folded into `notes` just
|
|
160
|
-
* above this function's call site) already narrates the alarming case: two
|
|
161
|
-
* or more repositories that emitted a workspace-scoped type and none of it
|
|
162
|
-
* joined. What it does not narrate is the ordinary case — every `analyze`
|
|
163
|
-
* call in the shipped product passes exactly one repository's batches, so
|
|
164
|
-
* every entry in `built.crossRepoJoins` has `crossRepoJoinPossible: false`
|
|
165
|
-
* and `suppliedByTwoOrMoreRepos: 0` by construction, not by failure. Left
|
|
166
|
-
* un-narrated, `{ total: 48, suppliedByTwoOrMoreRepos: 0 }` sitting beside a
|
|
167
|
-
* disclosure about 55 unrelated within-repo edges having just succeeded
|
|
168
|
-
* reads as a failure of the very thing that disclosure said worked. This
|
|
169
|
-
* states outright that one repository was in scope, so a reader is not left
|
|
170
|
-
* to infer it from `repos.length` themselves.
|
|
171
|
-
*/
|
|
85
|
+
/** Single-repo half of the joins disclosure. In the ordinary case — one repo in scope —
|
|
86
|
+
* every join metric's `suppliedByTwoOrMoreRepos: 0` looks like `NO_CROSS_REPO_JOIN`'s
|
|
87
|
+
* failure case; this states outright it's just scope, not a failed join. */
|
|
172
88
|
export function crossRepoJoinNote(joins) {
|
|
173
89
|
const singleRepo = joins.filter((j) => !j.crossRepoJoinPossible);
|
|
174
90
|
if (singleRepo.length === 0)
|
|
@@ -188,21 +104,16 @@ async function run(args, ctx) {
|
|
|
188
104
|
}
|
|
189
105
|
const root = await session.root();
|
|
190
106
|
const notes = [];
|
|
191
|
-
// MK-4: analyze
|
|
192
|
-
//
|
|
193
|
-
// see Session.repairStaleGraph's own doc for why only this tool does this.
|
|
107
|
+
// MK-4: analyze rebuilds from source regardless, so a stale IR schema is repaired
|
|
108
|
+
// here rather than refused — see `Session.repairStaleGraph` for why only this tool does this.
|
|
194
109
|
const { rebuilt } = session.repairStaleGraph();
|
|
195
110
|
if (rebuilt) {
|
|
196
111
|
notes.push("The stored graph was written under an older IR schema version. Its derived tables were " +
|
|
197
112
|
"dropped and are rebuilt by this run; earned data (R4 observations, edge corrections, " +
|
|
198
113
|
"incident links) was not affected.");
|
|
199
114
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const drift = configDriftNote(onDisk, session.config);
|
|
203
|
-
if (drift !== undefined)
|
|
204
|
-
notes.push(drift);
|
|
205
|
-
}
|
|
115
|
+
// Config drift is now checked centrally in server.ts for every tool (13.3.16 /
|
|
116
|
+
// N2 steps 2-3), not just this one — see `checkConfigDrift` in session.ts.
|
|
206
117
|
if (session.config.configPath === null) {
|
|
207
118
|
notes.push(`No ${".descry/config.json"} was found, so the repository identity defaults to the ` +
|
|
208
119
|
`directory name ("${session.config.repo}"). Every repo-scoped node id is a hash over that ` +
|
|
@@ -222,12 +133,13 @@ async function run(args, ctx) {
|
|
|
222
133
|
notes.push(`The source "${failure.spec.module}" could not be loaded (${failure.reason}). Anything it ` +
|
|
223
134
|
"would have read is not analysable — not clean.");
|
|
224
135
|
}
|
|
136
|
+
for (const entry of registry.loaded) {
|
|
137
|
+
notes.push(sourceProvenanceNote(entry));
|
|
138
|
+
}
|
|
225
139
|
if (session.config.sources.length === 0) {
|
|
226
140
|
notes.push(
|
|
227
|
-
// No example package name here
|
|
228
|
-
//
|
|
229
|
-
// language — the exact inversion `registry.ts` exists to prevent — and the
|
|
230
|
-
// list of installed adapters is not something this process can see.
|
|
141
|
+
// No example package name here — naming one would leak a specific language into
|
|
142
|
+
// this engine, the inversion `registry.ts` exists to prevent (rule 1: IR boundary).
|
|
231
143
|
"No language adapters are configured, so nothing was read from source. Add a \"sources\" " +
|
|
232
144
|
`array to ${".descry/config.json"} listing the adapter packages to load, as module ` +
|
|
233
145
|
"specifiers. This engine does not know the name of any adapter: the IR boundary is a " +
|
|
@@ -246,30 +158,17 @@ async function run(args, ctx) {
|
|
|
246
158
|
};
|
|
247
159
|
const batches = [];
|
|
248
160
|
const perSource = [];
|
|
249
|
-
/**
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
* The floor is drawn from these alone, and the git-history reader is why. It
|
|
253
|
-
* reaches R0 and always will: R0 is what reading a commit log *is*, not a
|
|
254
|
-
* degradation of it. Folding it into a single graph-wide minimum pinned every
|
|
255
|
-
* analyse reply at R0 and therefore at reliability class C — which then
|
|
256
|
-
* described a set of directly counted rows as "a behavioural prediction".
|
|
257
|
-
*
|
|
258
|
-
* DEC-058 already settled the general form of this: an edge carries the
|
|
259
|
-
* resolution of *its own evidence*, not of the run, so a graph has no single
|
|
260
|
-
* floor and each answer computes its own. This is that rule applied one level
|
|
261
|
-
* up. Every source's level is still reported individually in `sources`, and a
|
|
262
|
-
* source that fell short of its own declared ceiling is disclosed separately.
|
|
263
|
-
*/
|
|
161
|
+
/** Resolution floor comes from code-reading sources only — git history is always R0
|
|
162
|
+
* by nature, not degradation; folding it in would cap every reply at class C. DEC-058:
|
|
163
|
+
* an edge carries its own evidence's resolution, not the run's; each source still reported individually. */
|
|
264
164
|
const codeResolutions = [];
|
|
265
165
|
const total = applicable.length + (includeHistory ? 1 : 0);
|
|
266
166
|
let done = 0;
|
|
267
167
|
for (const entry of applicable) {
|
|
268
168
|
ctx.progress(`Reading ${entry.source.id}`, done, total);
|
|
269
169
|
const started = Date.now();
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
// TypeError in the lines below be reported as the adapter failing.
|
|
170
|
+
// Adapter's own work and Descry's handling of its output are separate phases with
|
|
171
|
+
// separate blame — folding them into one `try` let a `TypeError` here be blamed on the adapter.
|
|
273
172
|
let batch;
|
|
274
173
|
try {
|
|
275
174
|
batch = await entry.source.emit(context);
|
|
@@ -293,9 +192,8 @@ async function run(args, ctx) {
|
|
|
293
192
|
reachedResolution: batch.reachedResolution,
|
|
294
193
|
ms: Date.now() - started,
|
|
295
194
|
});
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
// repository stopped it.
|
|
195
|
+
// Declared ceiling vs what this run reached — a gap is honest degradation (rule 7):
|
|
196
|
+
// the adapter can do better but something in this repo stopped it.
|
|
299
197
|
const ceiling = entry.adapter?.capabilities().maxResolution;
|
|
300
198
|
if (ceiling !== undefined)
|
|
301
199
|
codeResolutions.push(batch.reachedResolution);
|
|
@@ -315,15 +213,12 @@ async function run(args, ctx) {
|
|
|
315
213
|
}
|
|
316
214
|
}
|
|
317
215
|
catch (error) {
|
|
318
|
-
// Reached only when Descry's own handling threw
|
|
319
|
-
// returned, so blaming it here would send the user to debug working code.
|
|
216
|
+
// Reached only when Descry's own handling threw — the adapter already returned successfully.
|
|
320
217
|
notes.push(sourceFailureNote(entry.source.id, error, "engine"));
|
|
321
218
|
}
|
|
322
219
|
finally {
|
|
323
|
-
// `dispose` is a `LanguageAdapter` obligation, not
|
|
324
|
-
//
|
|
325
|
-
// hundreds of megabytes per repo. Sources with no processes to release
|
|
326
|
-
// (the git reader) have no method and need none.
|
|
220
|
+
// `dispose` is a `LanguageAdapter` obligation, not `IRSource`'s — a leaked language
|
|
221
|
+
// server costs hundreds of MB per repo. Sources with none to release (git reader) need no method.
|
|
327
222
|
await entry.adapter?.dispose();
|
|
328
223
|
done += 1;
|
|
329
224
|
}
|
|
@@ -359,13 +254,9 @@ async function run(args, ctx) {
|
|
|
359
254
|
notes.push("Git history was skipped by request, so no CHANGES_WITH edges were produced and the blast " +
|
|
360
255
|
"radius will miss files that historically change together.");
|
|
361
256
|
}
|
|
362
|
-
// Developer-confirmed incidents, re-projected
|
|
363
|
-
//
|
|
364
|
-
//
|
|
365
|
-
// exists nowhere else (DEC-223's storage decision); the graph holds a
|
|
366
|
-
// projection. Re-emitting it here is what makes "a rebuild never loses it"
|
|
367
|
-
// true rather than merely intended — a store is derived data and every
|
|
368
|
-
// derived table is dropped on a schema bump.
|
|
257
|
+
// Developer-confirmed incidents, re-projected every analyze run. The record lives in
|
|
258
|
+
// `.descry/config.json` (testimony, DEC-223) — the graph only holds a derived projection,
|
|
259
|
+
// dropped on every schema bump, so re-emitting here is what keeps a rebuild from losing it.
|
|
369
260
|
const confirmedIncidents = session.config.confirmedIncidents ?? [];
|
|
370
261
|
if (confirmedIncidents.length > 0) {
|
|
371
262
|
const projected = await createConfirmedIncidentSource({
|
|
@@ -424,11 +315,9 @@ async function run(args, ctx) {
|
|
|
424
315
|
}
|
|
425
316
|
// --- mint edges from confirmed facts --------------------------------------
|
|
426
317
|
//
|
|
427
|
-
// DEC-223
|
|
428
|
-
//
|
|
429
|
-
//
|
|
430
|
-
// backed by the SQL reader, not by `built`'s in-memory result, so the
|
|
431
|
-
// endpoint has to already exist as a row for the lookup to find it.
|
|
318
|
+
// DEC-223/DEC-138 minting, sequenced after the graph is persisted: a confirmed answer
|
|
319
|
+
// joins against a stored `API_ENDPOINT` row via the SQL-backed `EndpointLookup`, not
|
|
320
|
+
// `built`'s in-memory result, so the row must already exist for the lookup to find it.
|
|
432
321
|
ctx.progress("Minting edges from confirmed facts", done, total);
|
|
433
322
|
const provider = session.provider();
|
|
434
323
|
const { refs: ledgerRefs } = provider.unresolvedRefs();
|
|
@@ -438,18 +327,9 @@ async function run(args, ctx) {
|
|
|
438
327
|
...(session.config.workspace === undefined ? {} : { workspace: session.config.workspace }),
|
|
439
328
|
};
|
|
440
329
|
const mintResult = mintEdgesFromConfirmedFacts(answered, provider, scope, MINT_PRODUCED_BY, root.commitSha);
|
|
441
|
-
//
|
|
442
|
-
//
|
|
443
|
-
//
|
|
444
|
-
// a re-run after a changed or removed answer safe: the run id is derived
|
|
445
|
-
// from (producedBy, repo, commitSha, sourceFiles), so a re-run at the same
|
|
446
|
-
// commit with the same askable domain lands on the *same* run id, and the
|
|
447
|
-
// writer's own self-clean pass (`writer.ts` rule 3) retires whatever this
|
|
448
|
-
// run no longer supplies — the edge from a superseded answer does not
|
|
449
|
-
// survive next to a new one. Scoping to the *answered* subset instead
|
|
450
|
-
// would let a file drop out of `sourceFiles` the moment its one answer was
|
|
451
|
-
// removed, and a stale edge for it would then never be found as a
|
|
452
|
-
// prior-run to retire at all.
|
|
330
|
+
// Invalidation key (DEC-015: producedBy+sourceFiles), scoped to every *askable* file this
|
|
331
|
+
// run, not just answered ones — else a file dropping its one answer would vanish from
|
|
332
|
+
// sourceFiles and its stale edge could never be found by the writer's self-clean pass to retire.
|
|
453
333
|
const mintFiles = [
|
|
454
334
|
...new Set(ledgerRefs.flatMap((ref) => ref.attrs?.["refusalClass"] === "value-unknown" && typeof ref.file === "string" ? [ref.file] : [])),
|
|
455
335
|
].sort();
|
|
@@ -499,8 +379,7 @@ async function run(args, ctx) {
|
|
|
499
379
|
"changed) — the edges they previously grounded have been retired, not left to coexist with " +
|
|
500
380
|
"whatever this run minted instead.");
|
|
501
381
|
}
|
|
502
|
-
// No code-reading source ran
|
|
503
|
-
// rest a claim on. R0 rather than a cheerful default.
|
|
382
|
+
// No code-reading source ran — R0, not a cheerful default.
|
|
504
383
|
const floor = (codeResolutions.length === 0
|
|
505
384
|
? 0
|
|
506
385
|
: Math.min(...codeResolutions));
|