@descryy/mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/action-handshake.d.ts +86 -0
- package/dist/action-handshake.d.ts.map +1 -0
- package/dist/action-handshake.js +144 -0
- package/dist/action-handshake.js.map +1 -0
- package/dist/bin/descry-mcp.d.ts +18 -0
- package/dist/bin/descry-mcp.d.ts.map +1 -0
- package/dist/bin/descry-mcp.js +54 -0
- package/dist/bin/descry-mcp.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/language-guess.d.ts +17 -0
- package/dist/language-guess.d.ts.map +1 -0
- package/dist/language-guess.js +43 -0
- package/dist/language-guess.js.map +1 -0
- package/dist/protocol.d.ts +91 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +127 -0
- package/dist/protocol.js.map +1 -0
- package/dist/registry.d.ts +72 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +136 -0
- package/dist/registry.js.map +1 -0
- package/dist/render.d.ts +275 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +333 -0
- package/dist/render.js.map +1 -0
- package/dist/server.d.ts +42 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +263 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +164 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +302 -0
- package/dist/session.js.map +1 -0
- package/dist/tools/analyze.d.ts +124 -0
- package/dist/tools/analyze.d.ts.map +1 -0
- package/dist/tools/analyze.js +411 -0
- package/dist/tools/analyze.js.map +1 -0
- package/dist/tools/contracts.d.ts +105 -0
- package/dist/tools/contracts.d.ts.map +1 -0
- package/dist/tools/contracts.js +141 -0
- package/dist/tools/contracts.js.map +1 -0
- package/dist/tools/cross-pr.d.ts +137 -0
- package/dist/tools/cross-pr.d.ts.map +1 -0
- package/dist/tools/cross-pr.js +216 -0
- package/dist/tools/cross-pr.js.map +1 -0
- package/dist/tools/git-diff.d.ts +29 -0
- package/dist/tools/git-diff.d.ts.map +1 -0
- package/dist/tools/git-diff.js +117 -0
- package/dist/tools/git-diff.js.map +1 -0
- package/dist/tools/git-history.d.ts +27 -0
- package/dist/tools/git-history.d.ts.map +1 -0
- package/dist/tools/git-history.js +91 -0
- package/dist/tools/git-history.js.map +1 -0
- package/dist/tools/history.d.ts +63 -0
- package/dist/tools/history.d.ts.map +1 -0
- package/dist/tools/history.js +114 -0
- package/dist/tools/history.js.map +1 -0
- package/dist/tools/impact.d.ts +81 -0
- package/dist/tools/impact.d.ts.map +1 -0
- package/dist/tools/impact.js +229 -0
- package/dist/tools/impact.js.map +1 -0
- package/dist/tools/index.d.ts +33 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +47 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/kit.d.ts +183 -0
- package/dist/tools/kit.d.ts.map +1 -0
- package/dist/tools/kit.js +117 -0
- package/dist/tools/kit.js.map +1 -0
- package/dist/tools/link-workspace.d.ts +62 -0
- package/dist/tools/link-workspace.d.ts.map +1 -0
- package/dist/tools/link-workspace.js +156 -0
- package/dist/tools/link-workspace.js.map +1 -0
- package/dist/tools/lookup.d.ts +29 -0
- package/dist/tools/lookup.d.ts.map +1 -0
- package/dist/tools/lookup.js +73 -0
- package/dist/tools/lookup.js.map +1 -0
- package/dist/tools/pr-analysis.d.ts +89 -0
- package/dist/tools/pr-analysis.d.ts.map +1 -0
- package/dist/tools/pr-analysis.js +169 -0
- package/dist/tools/pr-analysis.js.map +1 -0
- package/dist/tools/propagation.d.ts +74 -0
- package/dist/tools/propagation.d.ts.map +1 -0
- package/dist/tools/propagation.js +194 -0
- package/dist/tools/propagation.js.map +1 -0
- package/dist/tools/questions.d.ts +80 -0
- package/dist/tools/questions.d.ts.map +1 -0
- package/dist/tools/questions.js +213 -0
- package/dist/tools/questions.js.map +1 -0
- package/dist/tools/refusal-fetch.d.ts +71 -0
- package/dist/tools/refusal-fetch.d.ts.map +1 -0
- package/dist/tools/refusal-fetch.js +137 -0
- package/dist/tools/refusal-fetch.js.map +1 -0
- package/dist/tools/scope.d.ts +60 -0
- package/dist/tools/scope.d.ts.map +1 -0
- package/dist/tools/scope.js +160 -0
- package/dist/tools/scope.js.map +1 -0
- package/dist/tools/similar-incidents.d.ts +105 -0
- package/dist/tools/similar-incidents.d.ts.map +1 -0
- package/dist/tools/similar-incidents.js +228 -0
- package/dist/tools/similar-incidents.js.map +1 -0
- package/dist/tools/validate.d.ts +103 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +176 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/tools/verification-status.d.ts +68 -0
- package/dist/tools/verification-status.d.ts.map +1 -0
- package/dist/tools/verification-status.js +179 -0
- package/dist/tools/verification-status.js.map +1 -0
- package/dist/transport.d.ts +58 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +115 -0
- package/dist/transport.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One repository, one graph, one process.
|
|
3
|
+
*
|
|
4
|
+
* The session owns everything with a lifetime: the SQLite handle, the resolved
|
|
5
|
+
* configuration, the loaded sources. Tools receive it and own nothing, which is
|
|
6
|
+
* what lets the whole tool layer be tested against an in-memory graph.
|
|
7
|
+
*
|
|
8
|
+
* ## Configuration is read once and reported, not read repeatedly and assumed
|
|
9
|
+
*
|
|
10
|
+
* `.descry/config.json` is optional. Everything in it has a default that makes
|
|
11
|
+
* local mode work unconfigured, per the architecture's local-first guarantee —
|
|
12
|
+
* except the source list, which cannot have one: this repository must not name
|
|
13
|
+
* an adapter (see `registry.ts`). So an unconfigured session can query a graph
|
|
14
|
+
* and cannot build one, and `analyze` says exactly that rather than reporting a
|
|
15
|
+
* successful run over zero sources.
|
|
16
|
+
*
|
|
17
|
+
* ## The graph is opened lazily
|
|
18
|
+
*
|
|
19
|
+
* A server that opened the database at startup would fail to start on a repo
|
|
20
|
+
* that has never been analysed — the worst possible first experience for the
|
|
21
|
+
* primary UX. Opening on first use means `tools/list` works everywhere, and a
|
|
22
|
+
* query against a missing graph fails as a *tool* result the agent can read and
|
|
23
|
+
* act on ("run analyze first"), not as a crash before the handshake.
|
|
24
|
+
*/
|
|
25
|
+
import type { ConfirmedFact, RepoRoot } from "@descryy/ir";
|
|
26
|
+
import { type AdjacencyProvider, type Store } from "@descryy/core";
|
|
27
|
+
import { type SourceSpec } from "./registry.ts";
|
|
28
|
+
export interface DescryConfig {
|
|
29
|
+
/** Identity scope for repo-scoped nodes. Never a path — see DEC-004. */
|
|
30
|
+
readonly repo: string;
|
|
31
|
+
/**
|
|
32
|
+
* The contract boundary (DEC-054). Must be byte-identical in every repository
|
|
33
|
+
* of the workspace; a mismatch produces a graph that joins nothing silently.
|
|
34
|
+
*/
|
|
35
|
+
readonly workspace?: string | undefined;
|
|
36
|
+
/** Graph file, relative to the repository root unless absolute. */
|
|
37
|
+
readonly graph: string;
|
|
38
|
+
readonly sources: readonly SourceSpec[];
|
|
39
|
+
/**
|
|
40
|
+
* DEC-223 §4's storage decision: human-confirmed answers to refusal-ledger
|
|
41
|
+
* rows, in the same small, field-additive, human-inspectable file as
|
|
42
|
+
* `repo`/`workspace` rather than a new store table — recommended there on
|
|
43
|
+
* measured population (a handful of facts per repository, not thousands;
|
|
44
|
+
* see DEC-223 for the number this rests on). Revisit if that stops holding.
|
|
45
|
+
*/
|
|
46
|
+
readonly confirmedFacts: readonly ConfirmedFact[];
|
|
47
|
+
/** Where the settings came from, so a surprising run can be explained. */
|
|
48
|
+
readonly configPath: string | null;
|
|
49
|
+
}
|
|
50
|
+
export declare const CONFIG_RELATIVE_PATH: string;
|
|
51
|
+
export declare const DEFAULT_GRAPH_RELATIVE_PATH: string;
|
|
52
|
+
export declare class ConfigError extends Error {
|
|
53
|
+
constructor(message: string);
|
|
54
|
+
}
|
|
55
|
+
export declare function loadConfig(repoPath: string): Promise<DescryConfig>;
|
|
56
|
+
export interface ConfigPatch {
|
|
57
|
+
readonly repo: string;
|
|
58
|
+
/** Omit to leave a previously-set workspace untouched; there is no way to clear one here. */
|
|
59
|
+
readonly workspace?: string | undefined;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* `.descry/config.json`'s writer, the counterpart to `loadConfig`.
|
|
63
|
+
*
|
|
64
|
+
* One writer for one file, used by both front doors that set the workspace
|
|
65
|
+
* id — `descry init` (`@descryhq-wq/cli`) and the `link_workspace` MCP tool — so
|
|
66
|
+
* the two can never drift into writing two different shapes of the same
|
|
67
|
+
* file. Fields this function does not know about (`graph`, `sources`, or
|
|
68
|
+
* anything a future version adds) survive a re-run untouched: this patches
|
|
69
|
+
* `repo` and `workspace`, it does not own the whole file.
|
|
70
|
+
*/
|
|
71
|
+
export declare function writeConfig(repoPath: string, patch: ConfigPatch): Promise<{
|
|
72
|
+
readonly path: string;
|
|
73
|
+
readonly previousWorkspace: string | undefined;
|
|
74
|
+
}>;
|
|
75
|
+
/**
|
|
76
|
+
* `confirmedFacts`'s writer — separate from `writeConfig` on purpose.
|
|
77
|
+
*
|
|
78
|
+
* `writeConfig`'s own doc is explicit that it "patches `repo` and
|
|
79
|
+
* `workspace`, it does not own the whole file" — a second, narrow writer for
|
|
80
|
+
* a second, narrow field keeps that boundary rather than growing one
|
|
81
|
+
* function into "the file's owner." Both read-modify-write the same JSON
|
|
82
|
+
* file the same way, so a future field gets a third writer, not a branch in
|
|
83
|
+
* this one.
|
|
84
|
+
*
|
|
85
|
+
* Keyed on exact `(repo, blockedBy, environment)` — DEC-223 §3 and
|
|
86
|
+
* `ConfirmedFact`'s own doc; `environment` is `undefined` for an unscoped
|
|
87
|
+
* answer, which is its own distinct key value, not a wildcard that a later
|
|
88
|
+
* environment-scoped answer would collide with. A second call with the same
|
|
89
|
+
* key **replaces** the first rather than appending a duplicate: a
|
|
90
|
+
* re-confirmation (the value changed, or the same value is being
|
|
91
|
+
* re-asserted after §7's staleness note) updates in place, and a caller can
|
|
92
|
+
* always find out what was overwritten from the return value rather than
|
|
93
|
+
* having to read the file first. A second call with a *different*
|
|
94
|
+
* environment for the same `blockedBy` adds a second fact rather than
|
|
95
|
+
* replacing the first — a repository can genuinely need one value per
|
|
96
|
+
* environment.
|
|
97
|
+
*/
|
|
98
|
+
export declare function writeConfirmedFact(repoPath: string, fact: ConfirmedFact): Promise<{
|
|
99
|
+
readonly path: string;
|
|
100
|
+
readonly replaced: ConfirmedFact | null;
|
|
101
|
+
}>;
|
|
102
|
+
/**
|
|
103
|
+
* `sources`' writer — MK-3, the third narrow field-writer beside `writeConfig`
|
|
104
|
+
* (`repo`/`workspace`) and `writeConfirmedFact` (`confirmedFacts`), for the
|
|
105
|
+
* same reason those two stayed separate: a shared file gets one writer per
|
|
106
|
+
* field it owns, not one function that grows a branch per field.
|
|
107
|
+
*
|
|
108
|
+
* Unconditional: the caller (`descry init`) decides whether writing is
|
|
109
|
+
* appropriate — reading `loadConfig(repoPath).sources` first and skipping
|
|
110
|
+
* this call when it is already non-empty — because "should this overwrite
|
|
111
|
+
* what's there" is a policy question `writeConfig`'s own precedent leaves to
|
|
112
|
+
* the caller, not to the file-writing primitive.
|
|
113
|
+
*/
|
|
114
|
+
export declare function writeSources(repoPath: string, sources: readonly string[]): Promise<{
|
|
115
|
+
readonly path: string;
|
|
116
|
+
}>;
|
|
117
|
+
export interface SessionOptions {
|
|
118
|
+
readonly repoPath: string;
|
|
119
|
+
/** Swap the store — the reason tools can be tested with no file on disk. */
|
|
120
|
+
readonly openGraph?: (path: string) => Store;
|
|
121
|
+
readonly config?: DescryConfig;
|
|
122
|
+
}
|
|
123
|
+
export declare class Session {
|
|
124
|
+
#private;
|
|
125
|
+
readonly repoPath: string;
|
|
126
|
+
readonly config: DescryConfig;
|
|
127
|
+
constructor(repoPath: string, config: DescryConfig, openGraph?: (path: string) => Store);
|
|
128
|
+
static open(options: SessionOptions): Promise<Session>;
|
|
129
|
+
get graphPath(): string;
|
|
130
|
+
/** Open on first use; reuse thereafter. */
|
|
131
|
+
store(): Store;
|
|
132
|
+
/**
|
|
133
|
+
* MK-4 — `analyze`'s own repair path, and the only caller entitled to one.
|
|
134
|
+
*
|
|
135
|
+
* Every other tool goes through `store()`/`provider()` and keeps refusing a
|
|
136
|
+
* version mismatch per DEC-017 (`SchemaVersionError`'s own message names
|
|
137
|
+
* this method's caller as the fix). `analyze` is different: it is about to
|
|
138
|
+
* rebuild the graph from source regardless, so there is nothing lost by
|
|
139
|
+
* repairing the derived tables first instead of stopping.
|
|
140
|
+
*
|
|
141
|
+
* Opens a short-lived `NodeSqliteDriver` directly rather than going through
|
|
142
|
+
* `this.#openGraph` — the injected-store path a test fixture uses bypasses
|
|
143
|
+
* a real file on disk entirely, and a `SchemaVersionError` from `migrate()`
|
|
144
|
+
* only exists for a real one. A no-op here on that path (nothing found to
|
|
145
|
+
* repair, `rebuilt: false`) is correct: an injected in-memory fixture store
|
|
146
|
+
* is never stale by construction, and `store()` right after this still
|
|
147
|
+
* goes through the real, checked path either way — this only ever removes
|
|
148
|
+
* a refusal that check would otherwise have hit first.
|
|
149
|
+
*/
|
|
150
|
+
repairStaleGraph(): {
|
|
151
|
+
readonly rebuilt: boolean;
|
|
152
|
+
};
|
|
153
|
+
provider(): AdjacencyProvider;
|
|
154
|
+
/**
|
|
155
|
+
* The repo root for an analysis run.
|
|
156
|
+
*
|
|
157
|
+
* The commit sha is read from git and **is not defaulted** when git is absent:
|
|
158
|
+
* every node and edge is stamped with it, and a placeholder would make the
|
|
159
|
+
* staleness stamp a lie that nothing downstream could detect.
|
|
160
|
+
*/
|
|
161
|
+
root(): Promise<RepoRoot>;
|
|
162
|
+
close(): void;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One repository, one graph, one process.
|
|
3
|
+
*
|
|
4
|
+
* The session owns everything with a lifetime: the SQLite handle, the resolved
|
|
5
|
+
* configuration, the loaded sources. Tools receive it and own nothing, which is
|
|
6
|
+
* what lets the whole tool layer be tested against an in-memory graph.
|
|
7
|
+
*
|
|
8
|
+
* ## Configuration is read once and reported, not read repeatedly and assumed
|
|
9
|
+
*
|
|
10
|
+
* `.descry/config.json` is optional. Everything in it has a default that makes
|
|
11
|
+
* local mode work unconfigured, per the architecture's local-first guarantee —
|
|
12
|
+
* except the source list, which cannot have one: this repository must not name
|
|
13
|
+
* an adapter (see `registry.ts`). So an unconfigured session can query a graph
|
|
14
|
+
* and cannot build one, and `analyze` says exactly that rather than reporting a
|
|
15
|
+
* successful run over zero sources.
|
|
16
|
+
*
|
|
17
|
+
* ## The graph is opened lazily
|
|
18
|
+
*
|
|
19
|
+
* A server that opened the database at startup would fail to start on a repo
|
|
20
|
+
* that has never been analysed — the worst possible first experience for the
|
|
21
|
+
* primary UX. Opening on first use means `tools/list` works everywhere, and a
|
|
22
|
+
* query against a missing graph fails as a *tool* result the agent can read and
|
|
23
|
+
* act on ("run analyze first"), not as a crash before the handshake.
|
|
24
|
+
*/
|
|
25
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
26
|
+
import { basename, isAbsolute, join, resolve } from "node:path";
|
|
27
|
+
import { createStoreProvider, gitHead, isGitRepository, NodeSqliteDriver, openStore, rebuildStaleGraph, } from "@descryy/core";
|
|
28
|
+
import { normaliseSpec } from "./registry.js";
|
|
29
|
+
export const CONFIG_RELATIVE_PATH = join(".descry", "config.json");
|
|
30
|
+
export const DEFAULT_GRAPH_RELATIVE_PATH = join(".descry", "graph.db");
|
|
31
|
+
function parseConfirmedFacts(raw, configPath) {
|
|
32
|
+
if (raw === undefined)
|
|
33
|
+
return [];
|
|
34
|
+
if (!Array.isArray(raw)) {
|
|
35
|
+
throw new ConfigError(`${configPath}: "confirmedFacts" must be an array`);
|
|
36
|
+
}
|
|
37
|
+
return raw.map((entry, index) => {
|
|
38
|
+
const e = entry;
|
|
39
|
+
for (const key of ["repo", "blockedBy", "value", "confirmedBy", "confirmedAt"]) {
|
|
40
|
+
if (typeof e[key] !== "string" || e[key] === "") {
|
|
41
|
+
throw new ConfigError(`${configPath}: confirmedFacts[${index}].${key} must be a non-empty string`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (e["environment"] !== undefined && (typeof e["environment"] !== "string" || e["environment"] === "")) {
|
|
45
|
+
throw new ConfigError(`${configPath}: confirmedFacts[${index}].environment must be a non-empty string when present`);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
repo: e["repo"],
|
|
49
|
+
blockedBy: e["blockedBy"],
|
|
50
|
+
value: e["value"],
|
|
51
|
+
...(e["environment"] === undefined ? {} : { environment: e["environment"] }),
|
|
52
|
+
confirmedBy: e["confirmedBy"],
|
|
53
|
+
confirmedAt: e["confirmedAt"],
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** `(repo, blockedBy, environment)` — `undefined` environment is its own value, never a wildcard. */
|
|
58
|
+
function sameFactKey(a, b) {
|
|
59
|
+
return a.repo === b.repo && a.blockedBy === b.blockedBy && a.environment === b.environment;
|
|
60
|
+
}
|
|
61
|
+
export class ConfigError extends Error {
|
|
62
|
+
constructor(message) {
|
|
63
|
+
super(message);
|
|
64
|
+
this.name = "ConfigError";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export async function loadConfig(repoPath) {
|
|
68
|
+
const configPath = join(repoPath, CONFIG_RELATIVE_PATH);
|
|
69
|
+
let raw = {};
|
|
70
|
+
let found = null;
|
|
71
|
+
try {
|
|
72
|
+
raw = JSON.parse(await readFile(configPath, "utf8"));
|
|
73
|
+
found = configPath;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
const code = error.code;
|
|
77
|
+
if (code !== "ENOENT") {
|
|
78
|
+
// A config that exists and cannot be parsed is refused rather than
|
|
79
|
+
// defaulted past. Silently falling back would run the whole session under
|
|
80
|
+
// settings the user believes they overrode.
|
|
81
|
+
throw new ConfigError(`${configPath} exists but could not be read: ${error.message}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (raw.sources !== undefined && !Array.isArray(raw.sources)) {
|
|
85
|
+
throw new ConfigError(`${configPath}: "sources" must be an array`);
|
|
86
|
+
}
|
|
87
|
+
const sources = (raw.sources ?? []).map((entry, index) => {
|
|
88
|
+
if (typeof entry === "string")
|
|
89
|
+
return normaliseSpec(entry);
|
|
90
|
+
if (typeof entry === "object" && entry !== null && typeof entry.module === "string") {
|
|
91
|
+
return entry;
|
|
92
|
+
}
|
|
93
|
+
throw new ConfigError(`${configPath}: sources[${index}] must be a module specifier or an object with a "module" field`);
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
// The directory name is a defensible default and a poor identity: it changes
|
|
97
|
+
// when someone clones into a different folder, and every repo-scoped node id
|
|
98
|
+
// changes with it. Stated in the analyze disclosures rather than left to be
|
|
99
|
+
// discovered when two machines produce different graphs.
|
|
100
|
+
repo: typeof raw.repo === "string" && raw.repo !== "" ? raw.repo : basename(resolve(repoPath)),
|
|
101
|
+
workspace: typeof raw.workspace === "string" && raw.workspace !== "" ? raw.workspace : undefined,
|
|
102
|
+
graph: typeof raw.graph === "string" && raw.graph !== "" ? raw.graph : DEFAULT_GRAPH_RELATIVE_PATH,
|
|
103
|
+
sources,
|
|
104
|
+
confirmedFacts: parseConfirmedFacts(raw.confirmedFacts, configPath),
|
|
105
|
+
configPath: found,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* `.descry/config.json`'s writer, the counterpart to `loadConfig`.
|
|
110
|
+
*
|
|
111
|
+
* One writer for one file, used by both front doors that set the workspace
|
|
112
|
+
* id — `descry init` (`@descryhq-wq/cli`) and the `link_workspace` MCP tool — so
|
|
113
|
+
* the two can never drift into writing two different shapes of the same
|
|
114
|
+
* file. Fields this function does not know about (`graph`, `sources`, or
|
|
115
|
+
* anything a future version adds) survive a re-run untouched: this patches
|
|
116
|
+
* `repo` and `workspace`, it does not own the whole file.
|
|
117
|
+
*/
|
|
118
|
+
export async function writeConfig(repoPath, patch) {
|
|
119
|
+
const path = join(repoPath, CONFIG_RELATIVE_PATH);
|
|
120
|
+
let existing = {};
|
|
121
|
+
try {
|
|
122
|
+
existing = JSON.parse(await readFile(path, "utf8"));
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
// A config that cannot be parsed is what a write here is entitled to fix
|
|
126
|
+
// — proceed from an empty base rather than refusing, unlike `loadConfig`,
|
|
127
|
+
// whose job is to run a session rather than repair one. Genuinely absent
|
|
128
|
+
// (ENOENT) takes the same path; both mean "start from nothing".
|
|
129
|
+
void error;
|
|
130
|
+
existing = {};
|
|
131
|
+
}
|
|
132
|
+
const previousWorkspace = typeof existing.workspace === "string" ? existing.workspace : undefined;
|
|
133
|
+
const next = { ...existing, repo: patch.repo };
|
|
134
|
+
if (patch.workspace !== undefined)
|
|
135
|
+
next.workspace = patch.workspace;
|
|
136
|
+
await mkdir(join(repoPath, ".descry"), { recursive: true });
|
|
137
|
+
await writeFile(path, `${JSON.stringify(next, null, 2)}\n`, "utf8");
|
|
138
|
+
return { path, previousWorkspace };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* `confirmedFacts`'s writer — separate from `writeConfig` on purpose.
|
|
142
|
+
*
|
|
143
|
+
* `writeConfig`'s own doc is explicit that it "patches `repo` and
|
|
144
|
+
* `workspace`, it does not own the whole file" — a second, narrow writer for
|
|
145
|
+
* a second, narrow field keeps that boundary rather than growing one
|
|
146
|
+
* function into "the file's owner." Both read-modify-write the same JSON
|
|
147
|
+
* file the same way, so a future field gets a third writer, not a branch in
|
|
148
|
+
* this one.
|
|
149
|
+
*
|
|
150
|
+
* Keyed on exact `(repo, blockedBy, environment)` — DEC-223 §3 and
|
|
151
|
+
* `ConfirmedFact`'s own doc; `environment` is `undefined` for an unscoped
|
|
152
|
+
* answer, which is its own distinct key value, not a wildcard that a later
|
|
153
|
+
* environment-scoped answer would collide with. A second call with the same
|
|
154
|
+
* key **replaces** the first rather than appending a duplicate: a
|
|
155
|
+
* re-confirmation (the value changed, or the same value is being
|
|
156
|
+
* re-asserted after §7's staleness note) updates in place, and a caller can
|
|
157
|
+
* always find out what was overwritten from the return value rather than
|
|
158
|
+
* having to read the file first. A second call with a *different*
|
|
159
|
+
* environment for the same `blockedBy` adds a second fact rather than
|
|
160
|
+
* replacing the first — a repository can genuinely need one value per
|
|
161
|
+
* environment.
|
|
162
|
+
*/
|
|
163
|
+
export async function writeConfirmedFact(repoPath, fact) {
|
|
164
|
+
const path = join(repoPath, CONFIG_RELATIVE_PATH);
|
|
165
|
+
let existing = {};
|
|
166
|
+
try {
|
|
167
|
+
existing = JSON.parse(await readFile(path, "utf8"));
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
void error;
|
|
171
|
+
existing = {};
|
|
172
|
+
}
|
|
173
|
+
const priorRaw = Array.isArray(existing["confirmedFacts"]) ? existing["confirmedFacts"] : [];
|
|
174
|
+
const prior = parseConfirmedFacts(priorRaw, path);
|
|
175
|
+
const replaced = prior.find((f) => sameFactKey(f, fact)) ?? null;
|
|
176
|
+
const rest = prior.filter((f) => !sameFactKey(f, fact));
|
|
177
|
+
const next = { ...existing, confirmedFacts: [...rest, fact] };
|
|
178
|
+
await mkdir(join(repoPath, ".descry"), { recursive: true });
|
|
179
|
+
await writeFile(path, `${JSON.stringify(next, null, 2)}\n`, "utf8");
|
|
180
|
+
return { path, replaced };
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* `sources`' writer — MK-3, the third narrow field-writer beside `writeConfig`
|
|
184
|
+
* (`repo`/`workspace`) and `writeConfirmedFact` (`confirmedFacts`), for the
|
|
185
|
+
* same reason those two stayed separate: a shared file gets one writer per
|
|
186
|
+
* field it owns, not one function that grows a branch per field.
|
|
187
|
+
*
|
|
188
|
+
* Unconditional: the caller (`descry init`) decides whether writing is
|
|
189
|
+
* appropriate — reading `loadConfig(repoPath).sources` first and skipping
|
|
190
|
+
* this call when it is already non-empty — because "should this overwrite
|
|
191
|
+
* what's there" is a policy question `writeConfig`'s own precedent leaves to
|
|
192
|
+
* the caller, not to the file-writing primitive.
|
|
193
|
+
*/
|
|
194
|
+
export async function writeSources(repoPath, sources) {
|
|
195
|
+
const path = join(repoPath, CONFIG_RELATIVE_PATH);
|
|
196
|
+
let existing = {};
|
|
197
|
+
try {
|
|
198
|
+
existing = JSON.parse(await readFile(path, "utf8"));
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
void error;
|
|
202
|
+
existing = {};
|
|
203
|
+
}
|
|
204
|
+
const next = { ...existing, sources: [...sources] };
|
|
205
|
+
await mkdir(join(repoPath, ".descry"), { recursive: true });
|
|
206
|
+
await writeFile(path, `${JSON.stringify(next, null, 2)}\n`, "utf8");
|
|
207
|
+
return { path };
|
|
208
|
+
}
|
|
209
|
+
export class Session {
|
|
210
|
+
repoPath;
|
|
211
|
+
config;
|
|
212
|
+
#store = null;
|
|
213
|
+
#provider = null;
|
|
214
|
+
#openGraph;
|
|
215
|
+
constructor(repoPath, config, openGraph) {
|
|
216
|
+
this.repoPath = repoPath;
|
|
217
|
+
this.config = config;
|
|
218
|
+
this.#openGraph = openGraph ?? ((path) => openStore(path));
|
|
219
|
+
}
|
|
220
|
+
static async open(options) {
|
|
221
|
+
const repoPath = resolve(options.repoPath);
|
|
222
|
+
const config = options.config ?? (await loadConfig(repoPath));
|
|
223
|
+
return new Session(repoPath, config, options.openGraph);
|
|
224
|
+
}
|
|
225
|
+
get graphPath() {
|
|
226
|
+
return isAbsolute(this.config.graph)
|
|
227
|
+
? this.config.graph
|
|
228
|
+
: join(this.repoPath, this.config.graph);
|
|
229
|
+
}
|
|
230
|
+
/** Open on first use; reuse thereafter. */
|
|
231
|
+
store() {
|
|
232
|
+
if (this.#store === null)
|
|
233
|
+
this.#store = this.#openGraph(this.graphPath);
|
|
234
|
+
return this.#store;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* MK-4 — `analyze`'s own repair path, and the only caller entitled to one.
|
|
238
|
+
*
|
|
239
|
+
* Every other tool goes through `store()`/`provider()` and keeps refusing a
|
|
240
|
+
* version mismatch per DEC-017 (`SchemaVersionError`'s own message names
|
|
241
|
+
* this method's caller as the fix). `analyze` is different: it is about to
|
|
242
|
+
* rebuild the graph from source regardless, so there is nothing lost by
|
|
243
|
+
* repairing the derived tables first instead of stopping.
|
|
244
|
+
*
|
|
245
|
+
* Opens a short-lived `NodeSqliteDriver` directly rather than going through
|
|
246
|
+
* `this.#openGraph` — the injected-store path a test fixture uses bypasses
|
|
247
|
+
* a real file on disk entirely, and a `SchemaVersionError` from `migrate()`
|
|
248
|
+
* only exists for a real one. A no-op here on that path (nothing found to
|
|
249
|
+
* repair, `rebuilt: false`) is correct: an injected in-memory fixture store
|
|
250
|
+
* is never stale by construction, and `store()` right after this still
|
|
251
|
+
* goes through the real, checked path either way — this only ever removes
|
|
252
|
+
* a refusal that check would otherwise have hit first.
|
|
253
|
+
*/
|
|
254
|
+
repairStaleGraph() {
|
|
255
|
+
if (this.#store !== null)
|
|
256
|
+
return { rebuilt: false };
|
|
257
|
+
const driver = new NodeSqliteDriver();
|
|
258
|
+
try {
|
|
259
|
+
driver.open(this.graphPath);
|
|
260
|
+
return rebuildStaleGraph(driver);
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// Anything from opening — a missing directory, a genuinely corrupt file
|
|
264
|
+
// — is not this method's job to diagnose. `store()` right after this
|
|
265
|
+
// hits the same path through its own, already-disclosed error handling.
|
|
266
|
+
return { rebuilt: false };
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
driver.close();
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
provider() {
|
|
273
|
+
if (this.#provider === null)
|
|
274
|
+
this.#provider = createStoreProvider(this.store().driver);
|
|
275
|
+
return this.#provider;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* The repo root for an analysis run.
|
|
279
|
+
*
|
|
280
|
+
* The commit sha is read from git and **is not defaulted** when git is absent:
|
|
281
|
+
* every node and edge is stamped with it, and a placeholder would make the
|
|
282
|
+
* staleness stamp a lie that nothing downstream could detect.
|
|
283
|
+
*/
|
|
284
|
+
async root() {
|
|
285
|
+
if (!(await isGitRepository(this.repoPath))) {
|
|
286
|
+
throw new ConfigError(`${this.repoPath} is not a git repository. Every node is stamped with the commit it was ` +
|
|
287
|
+
"read at, so there is nothing honest to record for a directory with no history.");
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
repo: this.config.repo,
|
|
291
|
+
...(this.config.workspace === undefined ? {} : { workspace: this.config.workspace }),
|
|
292
|
+
absolutePath: this.repoPath,
|
|
293
|
+
commitSha: await gitHead(this.repoPath),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
close() {
|
|
297
|
+
this.#store?.close();
|
|
298
|
+
this.#store = null;
|
|
299
|
+
this.#provider = null;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `analyze` — read the repository into the graph.
|
|
3
|
+
*
|
|
4
|
+
* The only tool that writes. Everything else queries what this produced, so its
|
|
5
|
+
* disclosures are the ones that matter most: a query cannot report a gap it was
|
|
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.
|
|
24
|
+
*
|
|
25
|
+
* ## The repo identity warning
|
|
26
|
+
*
|
|
27
|
+
* With no `.descry/config.json`, `repo` defaults to the directory name — and
|
|
28
|
+
* every repo-scoped node id is a hash over it. Clone into a differently-named
|
|
29
|
+
* folder and every id changes, which silently destroys incident links and
|
|
30
|
+
* `CHANGES_WITH` weights. That is DEC-004's failure arriving through the one
|
|
31
|
+
* field a default cannot get right, so it is stated on every unconfigured run.
|
|
32
|
+
*/
|
|
33
|
+
import type { UnresolvedRef } from "@descryy/ir";
|
|
34
|
+
import type { BuildResult, StoreCounts } from "@descryy/core";
|
|
35
|
+
import { type ToolDefinition } from "./kit.ts";
|
|
36
|
+
/**
|
|
37
|
+
* What one source read, and how well.
|
|
38
|
+
*
|
|
39
|
+
* `reachedResolution` is the number principle 3 caps everything above it by. A
|
|
40
|
+
* run that degraded to R0 because a dependency was missing produces a graph
|
|
41
|
+
* that looks identical to a healthy one until this field is read.
|
|
42
|
+
*/
|
|
43
|
+
export interface SourceRun {
|
|
44
|
+
readonly source: string;
|
|
45
|
+
readonly files: number;
|
|
46
|
+
readonly nodes: number;
|
|
47
|
+
readonly edges: number;
|
|
48
|
+
/** Refusal-ledger rows: gaps this source disclosed rather than guessed at. */
|
|
49
|
+
readonly unresolved: number;
|
|
50
|
+
/**
|
|
51
|
+
* Files this source attempted but could not parse — absent from the graph
|
|
52
|
+
* entirely, not confirmed clean. Never counted in `files`; see
|
|
53
|
+
* `IRBatch.skippedFiles`.
|
|
54
|
+
*/
|
|
55
|
+
readonly skippedFiles: number;
|
|
56
|
+
readonly reachedResolution: number;
|
|
57
|
+
/** Wall-clock time this source took, including the git-history reader. */
|
|
58
|
+
readonly ms: number;
|
|
59
|
+
}
|
|
60
|
+
export interface AnalyzeData {
|
|
61
|
+
readonly repo: string;
|
|
62
|
+
readonly workspace: string | null;
|
|
63
|
+
readonly commitSha: string;
|
|
64
|
+
readonly graphPath: string;
|
|
65
|
+
/** One entry per source that ran. An empty array is the not-analysable case. */
|
|
66
|
+
readonly sources: readonly SourceRun[];
|
|
67
|
+
/** Configured sources whose module would not import. Not clean — unread. */
|
|
68
|
+
readonly sourcesFailed: readonly {
|
|
69
|
+
readonly module: string;
|
|
70
|
+
readonly reason: string;
|
|
71
|
+
}[];
|
|
72
|
+
/** Sources that loaded and did not claim this repository, with why. */
|
|
73
|
+
readonly sourcesSkipped: readonly {
|
|
74
|
+
readonly source: string;
|
|
75
|
+
readonly reason: string;
|
|
76
|
+
}[];
|
|
77
|
+
/** Row counts in the store after this run. */
|
|
78
|
+
readonly stored: StoreCounts;
|
|
79
|
+
readonly merge: {
|
|
80
|
+
/** Node ids more than one source supplied — this is the cross-language join, not an error. */
|
|
81
|
+
readonly mergedNodes: number;
|
|
82
|
+
readonly mergedEdges: number;
|
|
83
|
+
/** Two different things under one id. There is no correct merge, so they are reported (DEC-024). */
|
|
84
|
+
readonly collisions: number;
|
|
85
|
+
/** Edges dropped because an endpoint resolved to nothing. Never stubbed. */
|
|
86
|
+
readonly droppedEdges: number;
|
|
87
|
+
readonly rejections: number;
|
|
88
|
+
};
|
|
89
|
+
/** Per workspace-scoped node type: how many exist and how many two repositories both supplied. */
|
|
90
|
+
readonly joins: BuildResult["joins"];
|
|
91
|
+
readonly written: {
|
|
92
|
+
readonly nodes: number;
|
|
93
|
+
readonly edges: number;
|
|
94
|
+
readonly unresolved: number;
|
|
95
|
+
readonly orphanedEdges: number;
|
|
96
|
+
/** Files a previous run owned and this one did not re-supply. Their rows are gone. */
|
|
97
|
+
readonly evictedFiles: number;
|
|
98
|
+
};
|
|
99
|
+
/** Edges minted from human-confirmed answers, capped at reliability class B by DEC-223. */
|
|
100
|
+
readonly minted: {
|
|
101
|
+
readonly edges: number;
|
|
102
|
+
readonly orphaned: number;
|
|
103
|
+
readonly unjoinable: number;
|
|
104
|
+
readonly evictedFiles: number;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* §5.4's `refusals` field, for this run only — never the graph's whole
|
|
109
|
+
* stored ledger (`refusal_fetch`'s job). `built.unresolved` is what the
|
|
110
|
+
* sources this call just read could not resolve, so it is a fresh
|
|
111
|
+
* population every run rather than accumulated history, and honestly
|
|
112
|
+
* scoped to "what this call found" the way the field's own contract asks.
|
|
113
|
+
*
|
|
114
|
+
* `undefined` on zero rows — the envelope's `refusals` stays `null` rather
|
|
115
|
+
* than carrying a summary with no exemplar or handle to show (matching
|
|
116
|
+
* `summariseRefusals`'s own `count === 0` shape one level up).
|
|
117
|
+
*/
|
|
118
|
+
export declare function refusalSummaryField(unresolved: readonly UnresolvedRef[]): {
|
|
119
|
+
readonly count: number;
|
|
120
|
+
readonly exemplar: string;
|
|
121
|
+
readonly handle: string;
|
|
122
|
+
} | undefined;
|
|
123
|
+
export declare const analyzeTool: ToolDefinition;
|
|
124
|
+
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/tools/analyze.ts"],"names":[],"mappings":"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"}
|