@descryy/mcp 0.11.1 → 0.11.3
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/bin/descry-mcp.js +6 -0
- package/dist/bin/descry-mcp.js.map +1 -1
- package/dist/browser/auth.d.ts +8 -0
- package/dist/browser/auth.d.ts.map +1 -1
- package/dist/browser/auth.js +12 -2
- package/dist/browser/auth.js.map +1 -1
- package/dist/credential-store.d.ts +22 -0
- package/dist/credential-store.d.ts.map +1 -0
- package/dist/credential-store.js +33 -0
- package/dist/credential-store.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/planner/predict-then-propose.d.ts +34 -1
- package/dist/planner/predict-then-propose.d.ts.map +1 -1
- package/dist/planner/predict-then-propose.js +51 -1
- package/dist/planner/predict-then-propose.js.map +1 -1
- package/dist/planner/propose-journey.d.ts +15 -0
- package/dist/planner/propose-journey.d.ts.map +1 -1
- package/dist/planner/propose-journey.js.map +1 -1
- package/dist/render.d.ts +7 -11
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +22 -2
- package/dist/render.js.map +1 -1
- package/dist/scenarios/browser-run-plan-projection.d.ts +24 -6
- package/dist/scenarios/browser-run-plan-projection.d.ts.map +1 -1
- package/dist/scenarios/browser-run-plan-projection.js +45 -9
- package/dist/scenarios/browser-run-plan-projection.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +13 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/alias-kit.d.ts +29 -0
- package/dist/tools/alias-kit.d.ts.map +1 -0
- package/dist/tools/alias-kit.js +21 -0
- package/dist/tools/alias-kit.js.map +1 -0
- package/dist/tools/aliases.d.ts +42 -0
- package/dist/tools/aliases.d.ts.map +1 -0
- package/dist/tools/aliases.js +52 -0
- package/dist/tools/aliases.js.map +1 -0
- package/dist/tools/browser-close-session.d.ts +5 -1
- package/dist/tools/browser-close-session.d.ts.map +1 -1
- package/dist/tools/browser-close-session.js +3 -1
- package/dist/tools/browser-close-session.js.map +1 -1
- package/dist/tools/browser-navigate.d.ts +5 -1
- package/dist/tools/browser-navigate.d.ts.map +1 -1
- package/dist/tools/browser-navigate.js +3 -1
- package/dist/tools/browser-navigate.js.map +1 -1
- package/dist/tools/browser-read.d.ts +33 -0
- package/dist/tools/browser-read.d.ts.map +1 -0
- package/dist/tools/browser-read.js +113 -0
- package/dist/tools/browser-read.js.map +1 -0
- package/dist/tools/browser-snapshot.d.ts +5 -2
- package/dist/tools/browser-snapshot.d.ts.map +1 -1
- package/dist/tools/browser-snapshot.js +3 -1
- package/dist/tools/browser-snapshot.js.map +1 -1
- package/dist/tools/browser-start-session.d.ts.map +1 -1
- package/dist/tools/browser-start-session.js +57 -11
- package/dist/tools/browser-start-session.js.map +1 -1
- package/dist/tools/browser-wait-for.d.ts +5 -1
- package/dist/tools/browser-wait-for.d.ts.map +1 -1
- package/dist/tools/browser-wait-for.js +3 -1
- package/dist/tools/browser-wait-for.js.map +1 -1
- package/dist/tools/browser.d.ts +69 -0
- package/dist/tools/browser.d.ts.map +1 -0
- package/dist/tools/browser.js +386 -0
- package/dist/tools/browser.js.map +1 -0
- package/dist/tools/change-scope.d.ts +25 -0
- package/dist/tools/change-scope.d.ts.map +1 -0
- package/dist/tools/change-scope.js +110 -0
- package/dist/tools/change-scope.js.map +1 -0
- package/dist/tools/code-context.d.ts +83 -0
- package/dist/tools/code-context.d.ts.map +1 -0
- package/dist/tools/code-context.js +416 -0
- package/dist/tools/code-context.js.map +1 -0
- package/dist/tools/disclosure.d.ts +75 -0
- package/dist/tools/disclosure.d.ts.map +1 -0
- package/dist/tools/disclosure.js +288 -0
- package/dist/tools/disclosure.js.map +1 -0
- package/dist/tools/draw-conclusion.d.ts +12 -1
- package/dist/tools/draw-conclusion.d.ts.map +1 -1
- package/dist/tools/draw-conclusion.js +11 -2
- package/dist/tools/draw-conclusion.js.map +1 -1
- package/dist/tools/git-context.d.ts +39 -0
- package/dist/tools/git-context.d.ts.map +1 -0
- package/dist/tools/git-context.js +364 -0
- package/dist/tools/git-context.js.map +1 -0
- package/dist/tools/index.d.ts +16 -4
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +46 -67
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/kit.d.ts +3 -2
- package/dist/tools/kit.d.ts.map +1 -1
- package/dist/tools/kit.js.map +1 -1
- package/dist/tools/merged-browser.d.ts +11 -0
- package/dist/tools/merged-browser.d.ts.map +1 -0
- package/dist/tools/merged-browser.js +20 -0
- package/dist/tools/merged-browser.js.map +1 -0
- package/dist/tools/merged-context.d.ts +11 -0
- package/dist/tools/merged-context.d.ts.map +1 -0
- package/dist/tools/merged-context.js +21 -0
- package/dist/tools/merged-context.js.map +1 -0
- package/dist/tools/merged-observe.d.ts +13 -0
- package/dist/tools/merged-observe.d.ts.map +1 -0
- package/dist/tools/merged-observe.js +21 -0
- package/dist/tools/merged-observe.js.map +1 -0
- package/dist/tools/merged-workspace.d.ts +14 -0
- package/dist/tools/merged-workspace.d.ts.map +1 -0
- package/dist/tools/merged-workspace.js +21 -0
- package/dist/tools/merged-workspace.js.map +1 -0
- package/dist/tools/observe-runtime.d.ts +38 -1
- package/dist/tools/observe-runtime.d.ts.map +1 -1
- package/dist/tools/observe-runtime.js +236 -6
- package/dist/tools/observe-runtime.js.map +1 -1
- package/dist/tools/observe-tests.d.ts +12 -1
- package/dist/tools/observe-tests.d.ts.map +1 -1
- package/dist/tools/observe-tests.js +6 -2
- package/dist/tools/observe-tests.js.map +1 -1
- package/dist/tools/observe.d.ts +28 -0
- package/dist/tools/observe.d.ts.map +1 -0
- package/dist/tools/observe.js +330 -0
- package/dist/tools/observe.js.map +1 -0
- package/dist/tools/prove-reach.d.ts +74 -0
- package/dist/tools/prove-reach.d.ts.map +1 -0
- package/dist/tools/prove-reach.js +286 -0
- package/dist/tools/prove-reach.js.map +1 -0
- package/dist/tools/verb.d.ts +46 -0
- package/dist/tools/verb.d.ts.map +1 -0
- package/dist/tools/verb.js +78 -0
- package/dist/tools/verb.js.map +1 -0
- package/dist/tools/workspace.d.ts +28 -0
- package/dist/tools/workspace.d.ts.map +1 -0
- package/dist/tools/workspace.js +101 -0
- package/dist/tools/workspace.js.map +1 -0
- package/package.json +25 -21
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `prove_reach` — closes RG-10's loop. "Rename that column and these screens go blank" is
|
|
3
|
+
* three claims, made in order, each on evidence the last one didn't have:
|
|
4
|
+
*
|
|
5
|
+
* 1. **Predict** — from a node (typically a `DATABASE_COLUMN`), walk `reachablePages`
|
|
6
|
+
* (`@descryy/core`) to whatever `PAGE`/`COMPONENT` nodes the data reaches, and propose a
|
|
7
|
+
* navigate-only journey to them, exactly as `predict_reach` already does — this tool calls
|
|
8
|
+
* the identical pure planner (`../planner/predict-then-propose.ts#predictThenPropose`), never
|
|
9
|
+
* a second implementation. Nothing runs yet: a caller who has not yet approved the drive gets
|
|
10
|
+
* back the prediction, the proposal and a confirmation token, and this tool's `describeAction`
|
|
11
|
+
* is what mints that token — the dispatcher (`../action-handshake.ts`) never calls `run` at
|
|
12
|
+
* all until the second call arrives, so "nothing runs" is structural, not a promise this file
|
|
13
|
+
* keeps by convention.
|
|
14
|
+
* 2. **Approve and drive** — a second call, `confirmToken` in hand, drives the exact proposed
|
|
15
|
+
* scenario for real via `../browser/scenario-runner.ts#replayScenario`, in a browser session
|
|
16
|
+
* the caller already started and consented (`browser({ verb: "start_session" })`). Never boots an app,
|
|
17
|
+
* never widens the journey beyond what was proposed: the scenario driven is the one frozen at
|
|
18
|
+
* mint time, byte for byte.
|
|
19
|
+
* 3. **Prove** — correlates which of the predicted pages the drive's own step results actually
|
|
20
|
+
* reached (`../planner/predict-then-propose.ts#visitedPageIds` + `#proveOrDisprove`) — a page
|
|
21
|
+
* counts as visited only when the exact navigate URL built from its own route name replayed
|
|
22
|
+
* as `"ran"`, never a guess from proximity.
|
|
23
|
+
* 4. **Conclude** — routes the real, walked graph path (`#combinedGraphPath`, never a synthesised
|
|
24
|
+
* one) and the runtime evidence the drive actually observed (console errors, failed requests)
|
|
25
|
+
* through the same finding funnel `draw_conclusion` uses — `reportCategory`, `@descryy/ir`,
|
|
26
|
+
* `packages/ir/src/finding.ts` — so the reply carries a governed category, not a raw tally the
|
|
27
|
+
* caller has to interpret. A drive that reached every predicted page cleanly, with nothing
|
|
28
|
+
* wrong observed, reports so honestly: `hasRuntimeEvidence` is false and the category is
|
|
29
|
+
* `unconfirmed` by G3's own precondition, not "confirmed" because the pages loaded.
|
|
30
|
+
*
|
|
31
|
+
* **class: "action"**, gated only when there is something to drive: a node that reaches nothing,
|
|
32
|
+
* or reaches only non-path-shaped pages/components with no navigate step to propose, has nothing
|
|
33
|
+
* to approve, so `describeAction` returns `undefined` and this reports the prediction immediately
|
|
34
|
+
* — same discipline as `predict_reach`'s own empty case, never a gate for its own sake.
|
|
35
|
+
*/
|
|
36
|
+
import { directMechanismEvidence, evidencePrecondition, humanAssertedOnPath, independentSignalTypes, minimumResolution, reportCategory, } from "@descryy/ir";
|
|
37
|
+
import { combinedGraphPath, predictThenPropose, proveOrDisprove, visitedPageIds, } from "../planner/predict-then-propose.js";
|
|
38
|
+
import { browserAnswer, mutationRefusal, useSession, withinConsent } from "../browser/tool-support.js";
|
|
39
|
+
import { mutates, replayScenario } from "../browser/scenario-runner.js";
|
|
40
|
+
import { answer, briefNode, requiredString, optionalString, ToolInputError, } from "./kit.js";
|
|
41
|
+
import { resolveOneNode } from "./lookup.js";
|
|
42
|
+
const SCHEMA = {
|
|
43
|
+
type: "object",
|
|
44
|
+
properties: {
|
|
45
|
+
nodeId: { type: "string", description: "Graph node id to predict reach from — typically a DATABASE_COLUMN." },
|
|
46
|
+
symbol: {
|
|
47
|
+
type: "string",
|
|
48
|
+
description: "Symbol name to start from, when you do not have a node id. Ambiguity is reported rather than guessed at — narrow it with \"file\".",
|
|
49
|
+
},
|
|
50
|
+
file: { type: "string", description: "Repository-relative path, to disambiguate \"symbol\" or to start from a file." },
|
|
51
|
+
targetUrl: {
|
|
52
|
+
type: "string",
|
|
53
|
+
description: "REQUIRED. The running application's base URL — the same origin the browser session named in \"sessionId\" was consented for.",
|
|
54
|
+
},
|
|
55
|
+
sessionId: {
|
|
56
|
+
type: "string",
|
|
57
|
+
description: "REQUIRED. A browser session id from browser({ verb: \"start_session\" }), already consented for targetUrl's origin. " +
|
|
58
|
+
"This tool never starts a browser itself and never widens consent beyond that session's own.",
|
|
59
|
+
},
|
|
60
|
+
name: { type: "string", description: "What to call the proposed scenario. Defaults to \"predicted-journey\"." },
|
|
61
|
+
confirmToken: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "The token returned by a previous call. The first call predicts and proposes but drives nothing; call " +
|
|
64
|
+
"again with \"confirmToken\" to actually drive the proposed journey and correlate the result — with " +
|
|
65
|
+
"the arguments frozen when the token was minted, never whatever the confirming call supplies, so " +
|
|
66
|
+
"changing nodeId, targetUrl, sessionId or any other field on the confirming call is discarded rather " +
|
|
67
|
+
"than applied, and the reply discloses that it was; call again without confirmToken for a fresh token " +
|
|
68
|
+
"if something needs to change. A token is single-use, expires, and is only valid for this tool.",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
required: ["targetUrl", "sessionId"],
|
|
72
|
+
additionalProperties: false,
|
|
73
|
+
};
|
|
74
|
+
/** Resolves the start node and computes the identical prediction `predict_reach` would, from the
|
|
75
|
+
* same pure planner. Shared by `describeAction` and `run` so the two can never compute two
|
|
76
|
+
* different predictions for what a caller reads as one call. */
|
|
77
|
+
function prepare(args, ctx) {
|
|
78
|
+
const nodeIdArg = optionalString(args, "nodeId");
|
|
79
|
+
const symbol = optionalString(args, "symbol");
|
|
80
|
+
const file = optionalString(args, "file");
|
|
81
|
+
const targetUrl = requiredString(args, "targetUrl");
|
|
82
|
+
const sessionId = requiredString(args, "sessionId");
|
|
83
|
+
const name = optionalString(args, "name") ?? "predicted-journey";
|
|
84
|
+
if (nodeIdArg === undefined && symbol === undefined && file === undefined) {
|
|
85
|
+
throw new ToolInputError('give one of "nodeId", "symbol" or "file"');
|
|
86
|
+
}
|
|
87
|
+
const found = resolveOneNode(ctx.session, { nodeId: nodeIdArg, symbol, file });
|
|
88
|
+
if (found.node === null) {
|
|
89
|
+
return { ok: false, candidates: found.candidates.map(briefNode), headline: found.headline, notes: found.notes };
|
|
90
|
+
}
|
|
91
|
+
const provider = ctx.session.provider();
|
|
92
|
+
const base = provider.baseStamp();
|
|
93
|
+
const predicted = predictThenPropose(provider, found.node.id, { targetUrl, name, savedAtCommit: base.commitSha ?? "" });
|
|
94
|
+
return { ok: true, value: { node: found.node, predicted, targetUrl, sessionId } };
|
|
95
|
+
}
|
|
96
|
+
function drivable(predicted) {
|
|
97
|
+
return predicted.proposal !== null && predicted.proposal.scenario.steps.length > 0;
|
|
98
|
+
}
|
|
99
|
+
function emptyReport(node, predicted) {
|
|
100
|
+
return {
|
|
101
|
+
from: node === null ? { id: "", type: "", name: "", resolution: 0 } : briefNode(node),
|
|
102
|
+
reachedPages: predicted === null ? [] : predicted.reachedPages.map((n) => ({ id: n.id, type: n.type, name: n.name, resolution: 0 })),
|
|
103
|
+
proposal: predicted?.proposal === null || predicted === null
|
|
104
|
+
? null
|
|
105
|
+
: { scenario: predicted.proposal.scenario, reachedNotProposed: predicted.proposal.reachedNotProposed },
|
|
106
|
+
drive: null,
|
|
107
|
+
proof: null,
|
|
108
|
+
conclusion: null,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
async function describeAction(args, ctx) {
|
|
112
|
+
const prep = prepare(args, ctx);
|
|
113
|
+
if (!prep.ok)
|
|
114
|
+
return undefined; // nothing resolvable — run() reports the refusal immediately, no gate
|
|
115
|
+
const { node, predicted, sessionId } = prep.value;
|
|
116
|
+
if (!drivable(predicted))
|
|
117
|
+
return undefined; // nothing to drive — run() reports the prediction alone
|
|
118
|
+
const steps = predicted.proposal.scenario.steps.length;
|
|
119
|
+
const pageNames = predicted.reachedPages.map((p) => p.name);
|
|
120
|
+
return (`drive ${steps} navigate step(s) in browser session "${sessionId}", toward ${predicted.reachedPages.length} ` +
|
|
121
|
+
`predicted page/component reached from ${node.name} (${pageNames.slice(0, 5).join(", ")}${pageNames.length > 5 ? ", …" : ""}), ` +
|
|
122
|
+
"then correlate what the drive actually reached — and any console error or failed request observed while " +
|
|
123
|
+
"it ran — into a governed finding via the same gate draw_conclusion uses.");
|
|
124
|
+
}
|
|
125
|
+
async function run(args, ctx) {
|
|
126
|
+
const prep = prepare(args, ctx);
|
|
127
|
+
const base = ctx.session.provider().baseStamp();
|
|
128
|
+
if (!prep.ok) {
|
|
129
|
+
return {
|
|
130
|
+
result: { data: { candidates: prep.candidates }, stamp: { ...base, resolutionFloor: 0 }, truncated: false, notes: prep.notes },
|
|
131
|
+
nameLevel: true,
|
|
132
|
+
state: "refused",
|
|
133
|
+
headline: prep.headline,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const { node, predicted, targetUrl, sessionId } = prep.value;
|
|
137
|
+
const notes = [...predicted.notes];
|
|
138
|
+
if (!drivable(predicted)) {
|
|
139
|
+
return answer({
|
|
140
|
+
headline: predicted.proposal === null
|
|
141
|
+
? `${node.name} reaches no PAGE or COMPONENT this graph can walk to. Not a claim it reaches none in the running application — see notes.`
|
|
142
|
+
: `${node.name} reaches ${predicted.reachedPages.length} page/component, but none has a path-shaped route name — nothing to drive or prove.`,
|
|
143
|
+
state: "empty",
|
|
144
|
+
nameLevel: true,
|
|
145
|
+
resolutionFloor: 0,
|
|
146
|
+
commitSha: base.commitSha,
|
|
147
|
+
graphBuiltAt: base.graphBuiltAt,
|
|
148
|
+
irSchemaVersion: base.irSchemaVersion,
|
|
149
|
+
commitSpread: base.commitSpread,
|
|
150
|
+
repoCount: base.repoCount,
|
|
151
|
+
notes,
|
|
152
|
+
data: emptyReport(node, predicted),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// A non-empty proposal only reaches this line once the two-call handshake has already
|
|
156
|
+
// approved it — `describeAction` above gates every other case. Drive it, exactly as proposed.
|
|
157
|
+
const scenario = predicted.proposal.scenario;
|
|
158
|
+
const found = await useSession(ctx.session.browserSessions(), sessionId);
|
|
159
|
+
if (!found.ok) {
|
|
160
|
+
return browserAnswer({
|
|
161
|
+
ctx,
|
|
162
|
+
state: found.dead.state,
|
|
163
|
+
headline: found.dead.headline,
|
|
164
|
+
notes: [...notes, ...found.dead.notes],
|
|
165
|
+
data: emptyReport(node, predicted),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const { entry } = found;
|
|
169
|
+
if (!withinConsent(entry, targetUrl)) {
|
|
170
|
+
return browserAnswer({
|
|
171
|
+
ctx,
|
|
172
|
+
state: "refused",
|
|
173
|
+
headline: `The predicted journey targets ${targetUrl}, outside this session's consent.`,
|
|
174
|
+
notes: [
|
|
175
|
+
...notes,
|
|
176
|
+
`This session was consented for ${entry.consentedOrigin} only. Start a session against that origin to drive this prediction.`,
|
|
177
|
+
],
|
|
178
|
+
data: emptyReport(node, predicted),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
const refusedForSafety = mutationRefusal(entry);
|
|
182
|
+
if (refusedForSafety !== null && mutates(scenario)) {
|
|
183
|
+
// Dead in practice — proposeJourney only ever emits navigate steps — kept for the day a
|
|
184
|
+
// future planner proposes more, so a readOnly profile still refuses rather than driving.
|
|
185
|
+
return browserAnswer({
|
|
186
|
+
ctx,
|
|
187
|
+
state: "refused",
|
|
188
|
+
headline: `${entry.profile?.name ?? "This environment"} is read-only.`,
|
|
189
|
+
notes: [...notes, refusedForSafety],
|
|
190
|
+
data: emptyReport(node, predicted),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (entry.page.currentUrl() !== scenario.targetUrl) {
|
|
194
|
+
await entry.page.navigate(scenario.targetUrl);
|
|
195
|
+
}
|
|
196
|
+
ctx.progress(`Driving the predicted journey from ${node.name}`);
|
|
197
|
+
const replay = await replayScenario(ctx, ctx.session.browserSessions(), sessionId, scenario, process.env, ctx.session.credentialStore);
|
|
198
|
+
const visited = visitedPageIds(predicted, targetUrl, replay.steps.map((s) => ({ url: s.url, status: s.status })));
|
|
199
|
+
const proof = proveOrDisprove(predicted, { visitedNodeIds: visited });
|
|
200
|
+
// The hypothesis's own structural mechanism — every page the walk predicted, not only the ones
|
|
201
|
+
// this one drive happened to confirm — so the finding's graphPath describes what the graph
|
|
202
|
+
// claims propagates, and the runtime evidence below is what says whether it broke anything.
|
|
203
|
+
const graphPath = combinedGraphPath(predicted, predicted.reachedPages.map((p) => p.id));
|
|
204
|
+
const runtimeEvidence = [
|
|
205
|
+
...replay.evidence.consoleErrors.map((e) => ({ signal: "browser-console", detail: e.text, directMechanism: false })),
|
|
206
|
+
...replay.evidence.failedRequests.map((r) => {
|
|
207
|
+
const reached = replay.graph.reached.find((n) => n.via.method === r.method && n.via.url === r.url);
|
|
208
|
+
return {
|
|
209
|
+
signal: "network",
|
|
210
|
+
detail: `${r.method} ${r.url} failed${r.status === null ? "" : ` (status ${r.status})`}`,
|
|
211
|
+
...(reached === undefined ? {} : { nodeId: reached.nodeId, directMechanism: reached.nodeId === node.id }),
|
|
212
|
+
};
|
|
213
|
+
}),
|
|
214
|
+
];
|
|
215
|
+
const hasRuntimeEvidence = evidencePrecondition(runtimeEvidence);
|
|
216
|
+
const resolution = minimumResolution(graphPath);
|
|
217
|
+
const humanAsserted = humanAssertedOnPath(graphPath);
|
|
218
|
+
const eSignals = independentSignalTypes(runtimeEvidence);
|
|
219
|
+
const mMechanism = directMechanismEvidence(runtimeEvidence, node.id);
|
|
220
|
+
const gated = reportCategory({
|
|
221
|
+
hasRuntimeEvidence,
|
|
222
|
+
independentSignalTypes: eSignals,
|
|
223
|
+
directMechanismEvidence: mMechanism,
|
|
224
|
+
resolution,
|
|
225
|
+
// Name-level throughout — a route path is read off a node's qualified name, same as
|
|
226
|
+
// predict_reach's own cap, never a type-checked shape.
|
|
227
|
+
nameLevel: true,
|
|
228
|
+
humanAsserted,
|
|
229
|
+
});
|
|
230
|
+
const proofNotes = [
|
|
231
|
+
`Drove the proposed journey for real: ${proof.proven.length} of ${predicted.reachedPages.length} predicted ` +
|
|
232
|
+
`page(s)/component(s) confirmed reached, ${proof.disproven.length} not reached by this drive.`,
|
|
233
|
+
hasRuntimeEvidence
|
|
234
|
+
? `${runtimeEvidence.length} runtime observation(s) fed the gate — ${replay.evidence.consoleErrors.length} console error(s), ` +
|
|
235
|
+
`${replay.evidence.failedRequests.length} failed request(s).`
|
|
236
|
+
: "No console error or failed request was observed during this drive, so G3's evidence precondition fails " +
|
|
237
|
+
"and this reports unconfirmed regardless of the graph path — reaching a page cleanly is not evidence it broke.",
|
|
238
|
+
];
|
|
239
|
+
return browserAnswer({
|
|
240
|
+
ctx,
|
|
241
|
+
headline: `"${node.name}": ${gated.category} (reliability ${gated.reliabilityClass}). Drove ${scenario.steps.length} step(s), ` +
|
|
242
|
+
`${proof.proven.length} predicted page(s) confirmed reached, ${proof.disproven.length} not.`,
|
|
243
|
+
notes: [...notes, ...proofNotes, ...replay.notes],
|
|
244
|
+
data: {
|
|
245
|
+
from: briefNode(node),
|
|
246
|
+
reachedPages: predicted.reachedPages.map((n) => ({ id: n.id, type: n.type, name: n.name, resolution: 0 })),
|
|
247
|
+
proposal: { scenario: predicted.proposal.scenario, reachedNotProposed: predicted.proposal.reachedNotProposed },
|
|
248
|
+
drive: {
|
|
249
|
+
outcome: replay.outcome,
|
|
250
|
+
steps: replay.steps.map((s) => ({ url: s.url, status: s.status })),
|
|
251
|
+
consoleErrorCount: replay.evidence.consoleErrors.length,
|
|
252
|
+
failedRequestCount: replay.evidence.failedRequests.length,
|
|
253
|
+
},
|
|
254
|
+
proof,
|
|
255
|
+
conclusion: {
|
|
256
|
+
failurePoint: node.id,
|
|
257
|
+
category: gated.category,
|
|
258
|
+
reliabilityClass: gated.reliabilityClass,
|
|
259
|
+
resolution,
|
|
260
|
+
independentSignalTypes: eSignals,
|
|
261
|
+
directMechanismEvidence: mMechanism,
|
|
262
|
+
hasRuntimeEvidence,
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
export const proveReachTool = {
|
|
268
|
+
name: "prove_reach",
|
|
269
|
+
class: "action",
|
|
270
|
+
tier: "conclusion",
|
|
271
|
+
version: "1.0.0",
|
|
272
|
+
title: "Predict which pages a data change reaches, then drive a real browser to prove or disprove it",
|
|
273
|
+
description: "RG-10's full loop: predicts which PAGE/COMPONENT nodes a node (typically a DATABASE_COLUMN) reaches, " +
|
|
274
|
+
"exactly as predict_reach does, and proposes a navigate-only journey. The first call performs nothing " +
|
|
275
|
+
"and returns a confirmation token; call again with confirmToken to drive that exact proposed journey for " +
|
|
276
|
+
"real, in an already-consented browser session (sessionId, from browser({ verb: \"start_session\" })), then correlate " +
|
|
277
|
+
"which predicted pages the drive actually reached and route the graph path plus whatever the drive " +
|
|
278
|
+
"observed (console errors, failed requests) through the same governed gate draw_conclusion uses. Never " +
|
|
279
|
+
"boots an app, never clicks or types beyond the navigate-only proposal, and never widens the journey the " +
|
|
280
|
+
"first call showed you. A drive that reaches every predicted page with nothing wrong observed reports " +
|
|
281
|
+
"unconfirmed, honestly — a clean page load is not evidence of breakage.",
|
|
282
|
+
inputSchema: SCHEMA,
|
|
283
|
+
run,
|
|
284
|
+
describeAction,
|
|
285
|
+
};
|
|
286
|
+
//# sourceMappingURL=prove-reach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prove-reach.js","sourceRoot":"","sources":["../../src/tools/prove-reach.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-verb argument validation for a merged tool.
|
|
3
|
+
*
|
|
4
|
+
* ## Why a merged tool needs this at all
|
|
5
|
+
*
|
|
6
|
+
* The dispatch loop refuses any argument no schema declares
|
|
7
|
+
* (`server.ts`'s `unknownArgumentKeys`, built for UAT phase 5's F12 after
|
|
8
|
+
* `browser_start_session({ profile })` silently read `environment` and issued
|
|
9
|
+
* the wrong consent sentence). That check reads one flat `inputSchema`.
|
|
10
|
+
*
|
|
11
|
+
* A merged tool has one schema for many verbs, so its schema must declare the
|
|
12
|
+
* *union* of every verb's properties. `text` is then a declared property of the
|
|
13
|
+
* `browser` tool as a whole, and `browser({ verb: "snapshot", text: "hi" })`
|
|
14
|
+
* sails through the dispatch gate — the same silent-acceptance defect, one
|
|
15
|
+
* level further down, and invisible to the test that caught it the first time.
|
|
16
|
+
*
|
|
17
|
+
* So the strength the flat schema loses is re-established here, per verb. This
|
|
18
|
+
* is the price of merging, paid explicitly rather than absorbed.
|
|
19
|
+
*
|
|
20
|
+
* ## Why it names the other verb
|
|
21
|
+
*
|
|
22
|
+
* "unknown argument" is true but useless when the argument is real and the verb
|
|
23
|
+
* is wrong — the caller who sent `text` to `snapshot` did not misspell
|
|
24
|
+
* anything, they picked the wrong verb. Saying *`"text"` belongs to `type`*
|
|
25
|
+
* turns a refusal the caller must debug into one they can act on, which is the
|
|
26
|
+
* same reason `ToolInputError` exists separately from a thrown `Error`.
|
|
27
|
+
*/
|
|
28
|
+
export interface VerbSpec<V extends string = string> {
|
|
29
|
+
readonly verb: V;
|
|
30
|
+
/** Properties this verb accepts, beyond the shared ones. */
|
|
31
|
+
readonly accepts: readonly string[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolve and validate the verb of a merged tool call.
|
|
35
|
+
*
|
|
36
|
+
* Refuses, rather than defaulting or ignoring, on: a missing verb, an unknown
|
|
37
|
+
* verb, and any property that belongs to a different verb. Returns the verb so
|
|
38
|
+
* the caller can switch on a value already known to be valid.
|
|
39
|
+
*
|
|
40
|
+
* `shared` are properties every verb accepts — a session id, a budget. A
|
|
41
|
+
* property in neither `shared` nor any verb's `accepts` is not this function's
|
|
42
|
+
* to judge: the dispatch gate already refused it against the declared schema,
|
|
43
|
+
* and re-refusing it here would put the tool's property list in two places.
|
|
44
|
+
*/
|
|
45
|
+
export declare function selectVerb<V extends string>(args: Record<string, unknown>, key: string, specs: readonly VerbSpec<V>[], shared?: readonly string[]): V;
|
|
46
|
+
//# sourceMappingURL=verb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verb.d.ts","sourceRoot":"","sources":["../../src/tools/verb.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACjD,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,EAC7B,MAAM,GAAE,SAAS,MAAM,EAAO,GAC7B,CAAC,CAwCH"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-verb argument validation for a merged tool.
|
|
3
|
+
*
|
|
4
|
+
* ## Why a merged tool needs this at all
|
|
5
|
+
*
|
|
6
|
+
* The dispatch loop refuses any argument no schema declares
|
|
7
|
+
* (`server.ts`'s `unknownArgumentKeys`, built for UAT phase 5's F12 after
|
|
8
|
+
* `browser_start_session({ profile })` silently read `environment` and issued
|
|
9
|
+
* the wrong consent sentence). That check reads one flat `inputSchema`.
|
|
10
|
+
*
|
|
11
|
+
* A merged tool has one schema for many verbs, so its schema must declare the
|
|
12
|
+
* *union* of every verb's properties. `text` is then a declared property of the
|
|
13
|
+
* `browser` tool as a whole, and `browser({ verb: "snapshot", text: "hi" })`
|
|
14
|
+
* sails through the dispatch gate — the same silent-acceptance defect, one
|
|
15
|
+
* level further down, and invisible to the test that caught it the first time.
|
|
16
|
+
*
|
|
17
|
+
* So the strength the flat schema loses is re-established here, per verb. This
|
|
18
|
+
* is the price of merging, paid explicitly rather than absorbed.
|
|
19
|
+
*
|
|
20
|
+
* ## Why it names the other verb
|
|
21
|
+
*
|
|
22
|
+
* "unknown argument" is true but useless when the argument is real and the verb
|
|
23
|
+
* is wrong — the caller who sent `text` to `snapshot` did not misspell
|
|
24
|
+
* anything, they picked the wrong verb. Saying *`"text"` belongs to `type`*
|
|
25
|
+
* turns a refusal the caller must debug into one they can act on, which is the
|
|
26
|
+
* same reason `ToolInputError` exists separately from a thrown `Error`.
|
|
27
|
+
*/
|
|
28
|
+
import { ToolInputError } from "./kit.js";
|
|
29
|
+
/**
|
|
30
|
+
* Resolve and validate the verb of a merged tool call.
|
|
31
|
+
*
|
|
32
|
+
* Refuses, rather than defaulting or ignoring, on: a missing verb, an unknown
|
|
33
|
+
* verb, and any property that belongs to a different verb. Returns the verb so
|
|
34
|
+
* the caller can switch on a value already known to be valid.
|
|
35
|
+
*
|
|
36
|
+
* `shared` are properties every verb accepts — a session id, a budget. A
|
|
37
|
+
* property in neither `shared` nor any verb's `accepts` is not this function's
|
|
38
|
+
* to judge: the dispatch gate already refused it against the declared schema,
|
|
39
|
+
* and re-refusing it here would put the tool's property list in two places.
|
|
40
|
+
*/
|
|
41
|
+
export function selectVerb(args, key, specs, shared = []) {
|
|
42
|
+
const raw = args[key];
|
|
43
|
+
if (raw === undefined || raw === null || raw === "") {
|
|
44
|
+
throw new ToolInputError(`"${key}" is required — one of: ${specs.map((s) => s.verb).join(", ")}`);
|
|
45
|
+
}
|
|
46
|
+
if (typeof raw !== "string")
|
|
47
|
+
throw new ToolInputError(`"${key}" must be a string`);
|
|
48
|
+
const spec = specs.find((s) => s.verb === raw);
|
|
49
|
+
if (spec === undefined) {
|
|
50
|
+
throw new ToolInputError(`"${key}" must be one of: ${specs.map((s) => s.verb).join(", ")}`);
|
|
51
|
+
}
|
|
52
|
+
// Where each property that is not this verb's does belong. Built per call
|
|
53
|
+
// rather than hoisted: the specs are a handful of entries, and a module-level
|
|
54
|
+
// cache keyed on a caller-supplied array is a lifetime question this does not
|
|
55
|
+
// need to have.
|
|
56
|
+
const ownerOf = new Map();
|
|
57
|
+
for (const other of specs) {
|
|
58
|
+
if (other.verb === spec.verb)
|
|
59
|
+
continue;
|
|
60
|
+
for (const property of other.accepts) {
|
|
61
|
+
if (spec.accepts.includes(property))
|
|
62
|
+
continue;
|
|
63
|
+
// First owner wins only for the message; the refusal is the same either
|
|
64
|
+
// way, and listing every owner of a property shared by two other verbs
|
|
65
|
+
// would bury the one fact the caller needs.
|
|
66
|
+
if (!ownerOf.has(property))
|
|
67
|
+
ownerOf.set(property, other.verb);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const strays = Object.keys(args).filter((property) => property !== key && !shared.includes(property) && ownerOf.has(property));
|
|
71
|
+
if (strays.length > 0) {
|
|
72
|
+
const detail = strays.map((property) => `"${property}" belongs to ${ownerOf.get(property)}`).join("; ");
|
|
73
|
+
throw new ToolInputError(`${spec.verb} does not accept ${strays.map((p) => `"${p}"`).join(", ")} — ${detail}. ` +
|
|
74
|
+
`${spec.verb} accepts: ${[...shared, ...spec.accepts].join(", ") || "no arguments beyond the verb"}.`);
|
|
75
|
+
}
|
|
76
|
+
return spec.verb;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=verb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verb.js","sourceRoot":"","sources":["../../src/tools/verb.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `workspace` — merges `analyze`, `analyze_workspace` and `link_workspace`
|
|
3
|
+
* behind one `verb` (documents/plans/mcp-surface-consolidation.md §2, group 1).
|
|
4
|
+
* All three are `stateful-read`/`evidence`, so the merge crosses neither
|
|
5
|
+
* boundary.
|
|
6
|
+
*
|
|
7
|
+
* Dispatch only. Each verb's own `run()` body is untouched and stays in its
|
|
8
|
+
* own module (`analyze.ts` / `analyze-workspace.ts` / `link-workspace.ts`) —
|
|
9
|
+
* this file never holds a second copy of that logic, it only routes to it
|
|
10
|
+
* after `selectVerb` has re-established, per verb, the argument strength a
|
|
11
|
+
* flat union schema loses (`verb.ts`'s own header explains why that is
|
|
12
|
+
* mandatory once a schema covers more than one verb).
|
|
13
|
+
*/
|
|
14
|
+
import type { ToolDefinition } from "./kit.ts";
|
|
15
|
+
import type { AnalyzeData } from "./analyze.ts";
|
|
16
|
+
import type { AnalyzeWorkspaceData } from "./analyze-workspace.ts";
|
|
17
|
+
import type { LinkWorkspaceData } from "./link-workspace.ts";
|
|
18
|
+
/**
|
|
19
|
+
* What this tool answers with: one verb's shape, never a merged one.
|
|
20
|
+
*
|
|
21
|
+
* The merge cost this its single concrete output type, and `unknown` would have
|
|
22
|
+
* silently retired `output-shapes.test.ts`'s check that a declared shape is tied
|
|
23
|
+
* to the code producing it. A union keeps that tie: a verb added without its
|
|
24
|
+
* shape here stops compiling.
|
|
25
|
+
*/
|
|
26
|
+
export type WorkspaceData = AnalyzeData | AnalyzeWorkspaceData | LinkWorkspaceData;
|
|
27
|
+
export declare const workspaceTool: ToolDefinition;
|
|
28
|
+
//# sourceMappingURL=workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/tools/workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,UAAU,CAAC;AAM5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GACrB,WAAW,GACX,oBAAoB,GACpB,iBAAiB,CAAC;AAiFtB,eAAO,MAAM,aAAa,EAAE,cAa3B,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `workspace` — merges `analyze`, `analyze_workspace` and `link_workspace`
|
|
3
|
+
* behind one `verb` (documents/plans/mcp-surface-consolidation.md §2, group 1).
|
|
4
|
+
* All three are `stateful-read`/`evidence`, so the merge crosses neither
|
|
5
|
+
* boundary.
|
|
6
|
+
*
|
|
7
|
+
* Dispatch only. Each verb's own `run()` body is untouched and stays in its
|
|
8
|
+
* own module (`analyze.ts` / `analyze-workspace.ts` / `link-workspace.ts`) —
|
|
9
|
+
* this file never holds a second copy of that logic, it only routes to it
|
|
10
|
+
* after `selectVerb` has re-established, per verb, the argument strength a
|
|
11
|
+
* flat union schema loses (`verb.ts`'s own header explains why that is
|
|
12
|
+
* mandatory once a schema covers more than one verb).
|
|
13
|
+
*/
|
|
14
|
+
import { selectVerb } from "./verb.js";
|
|
15
|
+
import { analyzeTool } from "./analyze.js";
|
|
16
|
+
import { analyzeWorkspaceTool } from "./analyze-workspace.js";
|
|
17
|
+
import { linkWorkspaceTool } from "./link-workspace.js";
|
|
18
|
+
const VERBS = ["analyze", "index", "link"];
|
|
19
|
+
const VERB_SPECS = [
|
|
20
|
+
{ verb: "analyze", accepts: ["includeHistory", "maxCommits", "reload"] },
|
|
21
|
+
{ verb: "index", accepts: ["includeHistory", "maxCommits"] },
|
|
22
|
+
{ verb: "link", accepts: ["workspace", "repos"] },
|
|
23
|
+
];
|
|
24
|
+
const SCHEMA = {
|
|
25
|
+
type: "object",
|
|
26
|
+
properties: {
|
|
27
|
+
verb: {
|
|
28
|
+
type: "string",
|
|
29
|
+
enum: [...VERBS],
|
|
30
|
+
description: '"analyze" — read this repository into the code graph. "index" — read every repository a ' +
|
|
31
|
+
'prior "link" declared into one shared graph. "link" — declare which repositories share a ' +
|
|
32
|
+
"workspace.",
|
|
33
|
+
},
|
|
34
|
+
includeHistory: {
|
|
35
|
+
type: "boolean",
|
|
36
|
+
description: "analyze/index. Read git history for co-change coupling. Default true.",
|
|
37
|
+
},
|
|
38
|
+
maxCommits: {
|
|
39
|
+
type: "integer",
|
|
40
|
+
minimum: 1,
|
|
41
|
+
description: "analyze/index. Cap on commits read from history. Default 2000.",
|
|
42
|
+
},
|
|
43
|
+
reload: {
|
|
44
|
+
type: "boolean",
|
|
45
|
+
description: "analyze only. Re-read .descry/config.json from disk before this run, instead of the " +
|
|
46
|
+
"configuration this server started with.",
|
|
47
|
+
},
|
|
48
|
+
workspace: {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: 'link only. The workspace id to write into every repository in "repos", byte-identical.',
|
|
51
|
+
},
|
|
52
|
+
repos: {
|
|
53
|
+
type: "array",
|
|
54
|
+
minItems: 2,
|
|
55
|
+
items: {
|
|
56
|
+
type: "object",
|
|
57
|
+
properties: {
|
|
58
|
+
path: { type: "string", description: "Absolute path to the repository on disk." },
|
|
59
|
+
repo: { type: "string", description: "This repository's identity, written explicitly." },
|
|
60
|
+
},
|
|
61
|
+
required: ["path", "repo"],
|
|
62
|
+
additionalProperties: false,
|
|
63
|
+
},
|
|
64
|
+
description: "link only. Every repository that should share this workspace, including the current one " +
|
|
65
|
+
"if it should join. Only ones the user has explicitly confirmed belong together — never " +
|
|
66
|
+
"inferred.",
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
required: ["verb"],
|
|
70
|
+
additionalProperties: false,
|
|
71
|
+
};
|
|
72
|
+
const DISPATCH = {
|
|
73
|
+
analyze: analyzeTool,
|
|
74
|
+
index: analyzeWorkspaceTool,
|
|
75
|
+
link: linkWorkspaceTool,
|
|
76
|
+
};
|
|
77
|
+
async function run(args, ctx) {
|
|
78
|
+
const verb = selectVerb(args, "verb", VERB_SPECS);
|
|
79
|
+
// `ToolDefinition` erases its answer's type parameter — it has to, the
|
|
80
|
+
// registry is one array of many shapes — so the delegated call comes back as
|
|
81
|
+
// an erased answer type. The verb table is what makes the union true: every
|
|
82
|
+
// entry's own `run` is declared against one of WorkspaceData's members, and a verb
|
|
83
|
+
// added without its shape stops compiling at the union. The assertion
|
|
84
|
+
// re-applies what the table already guarantees rather than asserting
|
|
85
|
+
// something unchecked.
|
|
86
|
+
return (await DISPATCH[verb].run(args, ctx));
|
|
87
|
+
}
|
|
88
|
+
export const workspaceTool = {
|
|
89
|
+
name: "workspace",
|
|
90
|
+
class: "stateful-read",
|
|
91
|
+
tier: "evidence",
|
|
92
|
+
version: "1.0.0",
|
|
93
|
+
title: "Analyse a repository or workspace into the code graph",
|
|
94
|
+
description: "Read source into the code graph, or declare which repositories share a workspace, by verb: " +
|
|
95
|
+
'"analyze" (one repository, with its configured adapters), "index" (every repository a prior ' +
|
|
96
|
+
'"link" call declared, into one shared graph), "link" (write a workspace id into each named ' +
|
|
97
|
+
"repository's config — only after the user has explicitly confirmed they belong together).",
|
|
98
|
+
inputSchema: SCHEMA,
|
|
99
|
+
run,
|
|
100
|
+
};
|
|
101
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/tools/workspace.ts"],"names":[],"mappings":"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"}
|