@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,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `similar_incidents` — "have we seen this failure before?", asked about a
|
|
3
|
+
* failure that is **not yet in the graph**.
|
|
4
|
+
*
|
|
5
|
+
* ## Why this is a separate tool from `impact`'s `related` field
|
|
6
|
+
*
|
|
7
|
+
* `rootCauseSearch` — the `related` list every `impact` reply carries — walks
|
|
8
|
+
* `INCIDENT_CORRELATED`/`FIXED_BY` edges out of a node that already exists.
|
|
9
|
+
* It cannot help with a failure observed a moment ago: a stack trace and a set
|
|
10
|
+
* of touched files have no node, so there is nothing to walk from. This tool
|
|
11
|
+
* is the other direction. It takes the failure as a description and ranks the
|
|
12
|
+
* `INCIDENT` nodes the graph already holds against it, using the two signals
|
|
13
|
+
* `similarIncidents` (`@descryy/core`, DEC-274 step 2) computes from data the
|
|
14
|
+
* graph already has: file-set Jaccard over `INCIDENT_CORRELATED`, and
|
|
15
|
+
* token-set Jaccard over the incident's own text. Deterministic, no vector
|
|
16
|
+
* store, no model call.
|
|
17
|
+
*
|
|
18
|
+
* ## The disclosure this tool exists to carry, and it is not optional
|
|
19
|
+
*
|
|
20
|
+
* DEC-279 makes one sentence mandatory here, and DEC-274 is why. That
|
|
21
|
+
* measurement ran the correlation machinery over `descry-core`,
|
|
22
|
+
* `descry-runtime` and `descry-adapters` — 734, 459 and 203 commits — and
|
|
23
|
+
* found **zero `INCIDENT` nodes in all three**. Not few: zero. Only an
|
|
24
|
+
* explicit `git revert` mints an `INCIDENT` today; a fix-forward commit, which
|
|
25
|
+
* is how almost every real bug is actually fixed, mints nothing at all.
|
|
26
|
+
*
|
|
27
|
+
* So this matcher's **recall is not computable — 0/0, not 0%**. It has never
|
|
28
|
+
* been handed a real incident to find, and no number describes how many it
|
|
29
|
+
* would miss. An empty result therefore means *"no linked incident in this
|
|
30
|
+
* graph, and this graph has few or no incidents"* and must never be read as
|
|
31
|
+
* *"no similar incident exists."* That is the same *absence is not evidence*
|
|
32
|
+
* obligation `impact` already carries on every reply, and `similar-incidents.test.ts`
|
|
33
|
+
* fails if it goes missing from either the empty or the non-empty branch.
|
|
34
|
+
*
|
|
35
|
+
* ## Two different absences, and they are not the same result
|
|
36
|
+
*
|
|
37
|
+
* `ai-tool-contract.md` §1.3a splits them, and the split is the whole reason
|
|
38
|
+
* this endpoint is interesting:
|
|
39
|
+
*
|
|
40
|
+
* - **Incidents exist and none matched.** The denominator is real, the tool
|
|
41
|
+
* looked completely, and the absence is a fact about the code. `state:
|
|
42
|
+
* "empty"`, per §1.1's split.
|
|
43
|
+
* - **The graph holds zero `INCIDENT` nodes.** There is no denominator.
|
|
44
|
+
* Nothing was looked at, and the reason is Descry's producer coverage
|
|
45
|
+
* rather than anything about this repository: only `git revert` mints an
|
|
46
|
+
* `INCIDENT` and fix-forward mints nothing. Answering "empty" there would
|
|
47
|
+
* say *"this code has no similar incidents"* when the true statement is
|
|
48
|
+
* *"Descry cannot see most incidents in any codebase"* — the
|
|
49
|
+
* empty-denominator defect inside the endpoint written to demonstrate the
|
|
50
|
+
* rule against it. So it is a refusal, carried as `state: "refused"` (§1.1:
|
|
51
|
+
* `refused` is a result state, and `not analysable` is a report category —
|
|
52
|
+
* different axes, never this).
|
|
53
|
+
*
|
|
54
|
+
* §1.3a generalises it past this tool: **when a query's population is itself
|
|
55
|
+
* zero, the answer is a refusal, never an empty result.** That puts this in
|
|
56
|
+
* line with its siblings rather than apart from them — `contracts` refuses on
|
|
57
|
+
* a graph with no endpoint, `propagation` when no walked edge type touches
|
|
58
|
+
* the start node.
|
|
59
|
+
*
|
|
60
|
+
* The denominator travels in the payload either way. `incidentsInGraph` is
|
|
61
|
+
* the population and `analysed` is false only when it is zero, so a caller
|
|
62
|
+
* can tell the two absences apart **from the payload alone, with no string
|
|
63
|
+
* matching on prose** — §1's distinguishability requirement, satisfied
|
|
64
|
+
* without waiting for the wider envelope.
|
|
65
|
+
*/
|
|
66
|
+
import { similarIncidents } from "@descryy/core";
|
|
67
|
+
import { answer, briefNode, optionalInteger, optionalString, optionalStringArray, ToolInputError, } from "./kit.js";
|
|
68
|
+
const SCHEMA = {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
touchedFiles: {
|
|
72
|
+
type: "array",
|
|
73
|
+
items: { type: "string" },
|
|
74
|
+
description: "Repository-relative paths the failure touched — from a stack trace, a failing test's " +
|
|
75
|
+
"imports, or the diff being investigated. Matched against each incident's own correlated " +
|
|
76
|
+
"file set.",
|
|
77
|
+
},
|
|
78
|
+
errorMessage: {
|
|
79
|
+
type: "string",
|
|
80
|
+
description: "The failure's error or exception text. Matched against each incident's text, which today " +
|
|
81
|
+
"is always a commit subject line — real signal, but thin.",
|
|
82
|
+
},
|
|
83
|
+
minScore: {
|
|
84
|
+
type: "number",
|
|
85
|
+
minimum: 0,
|
|
86
|
+
maximum: 1,
|
|
87
|
+
description: "Drop candidates scoring below this. Default 0, meaning any signal that fired at all is " +
|
|
88
|
+
"returned — ranked, so a weak match is visible as a weak match rather than hidden.",
|
|
89
|
+
},
|
|
90
|
+
limit: { type: "integer", minimum: 1, description: "Cap on matches in the reply. Default 20." },
|
|
91
|
+
},
|
|
92
|
+
additionalProperties: false,
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* The mandatory sentence, in the form that fits each branch.
|
|
96
|
+
*
|
|
97
|
+
* Written once here rather than inline at three return sites, because the one
|
|
98
|
+
* failure mode this tool has is a branch that forgets it.
|
|
99
|
+
*/
|
|
100
|
+
function recallDisclosure(incidentsInGraph) {
|
|
101
|
+
return ((incidentsInGraph === 0
|
|
102
|
+
? "This graph holds no INCIDENT node at all, so nothing was compared. "
|
|
103
|
+
: `${incidentsInGraph} INCIDENT node(s) were available to compare against. `) +
|
|
104
|
+
"Absence is not evidence here, and the reason is measured rather than assumed: only an " +
|
|
105
|
+
"explicit git revert mints an INCIDENT, and a fix-forward commit — how almost every real bug " +
|
|
106
|
+
"is actually fixed — mints nothing. DEC-274 found zero INCIDENT nodes across three real " +
|
|
107
|
+
"repositories of 734, 459 and 203 commits. This matcher's recall is therefore not computable " +
|
|
108
|
+
"(0/0), not 0%: it has never been given a real incident to find. A failure this repository " +
|
|
109
|
+
"has genuinely hit before can be absent from these results entirely.");
|
|
110
|
+
}
|
|
111
|
+
async function run(args, ctx) {
|
|
112
|
+
const touchedFiles = optionalStringArray(args, "touchedFiles") ?? [];
|
|
113
|
+
const errorMessage = optionalString(args, "errorMessage");
|
|
114
|
+
const limit = optionalInteger(args, "limit", 1) ?? 20;
|
|
115
|
+
const rawMinScore = args["minScore"];
|
|
116
|
+
if (rawMinScore !== undefined && rawMinScore !== null) {
|
|
117
|
+
if (typeof rawMinScore !== "number" || rawMinScore < 0 || rawMinScore > 1) {
|
|
118
|
+
throw new ToolInputError('"minScore" must be a number between 0 and 1');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const minScore = typeof rawMinScore === "number" ? rawMinScore : undefined;
|
|
122
|
+
// Describing nothing and being told "0 matches" is the empty-denominator
|
|
123
|
+
// defect at the input side: the reply would be indistinguishable from a real
|
|
124
|
+
// search that found nothing.
|
|
125
|
+
if (touchedFiles.length === 0 && (errorMessage === undefined || errorMessage === "")) {
|
|
126
|
+
throw new ToolInputError('give at least one of "touchedFiles" or "errorMessage" — with neither, there is nothing to ' +
|
|
127
|
+
"compare an incident against, and an empty answer would look like a search that ran");
|
|
128
|
+
}
|
|
129
|
+
const provider = ctx.session.provider();
|
|
130
|
+
// The population, read for its own sake. `similarIncidents` scans the same
|
|
131
|
+
// set internally but returns only what matched, and the count of what did
|
|
132
|
+
// *not* match is the number this tool's honesty rests on.
|
|
133
|
+
ctx.progress("Reading the incident population");
|
|
134
|
+
const population = provider.nodesOfType("INCIDENT");
|
|
135
|
+
const incidentsInGraph = population.nodes.length;
|
|
136
|
+
const base = provider.baseStamp();
|
|
137
|
+
if (incidentsInGraph === 0) {
|
|
138
|
+
return answer({
|
|
139
|
+
headline: "No incident is recorded in this graph, so nothing was compared against the failure you " +
|
|
140
|
+
"described. This is not a finding that the failure is new.",
|
|
141
|
+
// A refusal, not an empty result — §1.3a. `not_analysable` is the value
|
|
142
|
+
// today's envelope has for it; §1.1 renames it `refused` in P2.
|
|
143
|
+
state: "refused",
|
|
144
|
+
// Whether an incident resembles a failure is a claim about names and
|
|
145
|
+
// paths, not about shapes — the same class as `history`'s co-change
|
|
146
|
+
// rows. R0 is the honest floor: an INCIDENT is minted from a commit
|
|
147
|
+
// log, which is R0 by nature rather than by degradation.
|
|
148
|
+
nameLevel: true,
|
|
149
|
+
resolutionFloor: 0,
|
|
150
|
+
commitSha: base.commitSha,
|
|
151
|
+
graphBuiltAt: base.graphBuiltAt,
|
|
152
|
+
irSchemaVersion: base.irSchemaVersion,
|
|
153
|
+
notes: [recallDisclosure(0)],
|
|
154
|
+
data: {
|
|
155
|
+
query: { touchedFiles, errorMessage: errorMessage ?? null },
|
|
156
|
+
matches: [],
|
|
157
|
+
matchesTotal: 0,
|
|
158
|
+
incidentsInGraph: 0,
|
|
159
|
+
analysed: false,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
ctx.progress(`Ranking ${incidentsInGraph} incident(s) against the failure`);
|
|
164
|
+
const ranked = similarIncidents(provider, {
|
|
165
|
+
...(touchedFiles.length === 0 ? {} : { touchedFiles }),
|
|
166
|
+
...(errorMessage === undefined ? {} : { errorMessage }),
|
|
167
|
+
}, { ...(minScore === undefined ? {} : { minScore }) });
|
|
168
|
+
const shown = ranked.data.slice(0, limit);
|
|
169
|
+
const notes = [...ranked.notes, recallDisclosure(incidentsInGraph)];
|
|
170
|
+
if (shown.length < ranked.data.length) {
|
|
171
|
+
notes.push(`${ranked.data.length - shown.length} further match(es) scored above the threshold but are ` +
|
|
172
|
+
`not listed — the reply is capped at ${limit}.`);
|
|
173
|
+
}
|
|
174
|
+
if (population.truncated) {
|
|
175
|
+
notes.push("The incident read was capped, so some INCIDENT nodes were never scored. The counts here " +
|
|
176
|
+
"are a lower bound.");
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
result: {
|
|
180
|
+
data: {
|
|
181
|
+
query: { touchedFiles, errorMessage: errorMessage ?? null },
|
|
182
|
+
matches: shown.map((match) => ({
|
|
183
|
+
incident: briefNode(match.incident),
|
|
184
|
+
fix: match.fix === null ? null : briefNode(match.fix),
|
|
185
|
+
signals: match.signals.map((s) => ({ kind: s.kind, score: Number(s.score.toFixed(4)) })),
|
|
186
|
+
score: Number(match.combinedScore.toFixed(4)),
|
|
187
|
+
})),
|
|
188
|
+
matchesTotal: ranked.data.length,
|
|
189
|
+
incidentsInGraph,
|
|
190
|
+
analysed: true,
|
|
191
|
+
},
|
|
192
|
+
stamp: ranked.stamp,
|
|
193
|
+
truncated: ranked.truncated || shown.length < ranked.data.length || population.truncated,
|
|
194
|
+
notes,
|
|
195
|
+
},
|
|
196
|
+
...(ranked.data.length === 0 ? { state: "empty" } : {}),
|
|
197
|
+
...(shown.length < ranked.data.length
|
|
198
|
+
? { truncatedDetail: { shown: shown.length, total: ranked.data.length, more: null } }
|
|
199
|
+
: {}),
|
|
200
|
+
nameLevel: true,
|
|
201
|
+
headline: ranked.data.length === 0
|
|
202
|
+
? `None of the ${incidentsInGraph} incident(s) in this graph share a file or a phrase with ` +
|
|
203
|
+
"the failure you described. That is a statement about this graph's incident record, not " +
|
|
204
|
+
"about the failure."
|
|
205
|
+
: `${ranked.data.length} of ${incidentsInGraph} recorded incident(s) resemble this failure; ` +
|
|
206
|
+
`closest: ${shown[0].incident.name}` +
|
|
207
|
+
`${shown[0].fix === null ? "" : ` (fixed by: ${shown[0].fix.name})`}.`,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
export const similarIncidentsTool = {
|
|
211
|
+
name: "similar_incidents",
|
|
212
|
+
class: "read",
|
|
213
|
+
tier: "evidence",
|
|
214
|
+
version: "1.0.0",
|
|
215
|
+
title: "Past incidents that resemble a failure happening now",
|
|
216
|
+
description: "Given the files a failure touched and/or its error text, rank the incidents already recorded " +
|
|
217
|
+
"in the graph by how much they resemble it, and name which signal fired for each — file " +
|
|
218
|
+
"overlap, message similarity, or both. Use this for a failure that has no graph node yet (a " +
|
|
219
|
+
"stack trace, a red test); use \"impact\" instead for incidents linked to a symbol that " +
|
|
220
|
+
"already exists. Deterministic graph and text matching only; no embedding search runs. Two " +
|
|
221
|
+
"absences and they are different answers: an empty result means this graph's recorded " +
|
|
222
|
+
"incidents were compared and none matched, while a refusal means the graph holds no incident " +
|
|
223
|
+
"at all — common, because only an explicit git revert mints one and a fix-forward commit " +
|
|
224
|
+
"mints nothing. Neither is evidence that the failure is new.",
|
|
225
|
+
inputSchema: SCHEMA,
|
|
226
|
+
run,
|
|
227
|
+
};
|
|
228
|
+
//# sourceMappingURL=similar-incidents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"similar-incidents.js","sourceRoot":"","sources":["../../src/tools/similar-incidents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `validate` — §15's static validation engine, currently its env/config check.
|
|
3
|
+
*
|
|
4
|
+
* The architecture calls this one *"cheapest and most reliable — ship first"*,
|
|
5
|
+
* and it is the first tool here whose output is a statement about the user's
|
|
6
|
+
* code rather than a measurement of the graph.
|
|
7
|
+
*
|
|
8
|
+
* ## Two things this tool refuses to do, and both are the point
|
|
9
|
+
*
|
|
10
|
+
* 1. **It does not report a variable that is read and never declared, by
|
|
11
|
+
* default.** Measured on two real repositories, that rule produces 18 wrong
|
|
12
|
+
* findings on one and 107 on the other. A finding needs a read that asserts
|
|
13
|
+
* *requirement* — no fallback at the read site — and a declaration surface
|
|
14
|
+
* complete enough for an absence to mean something. See `validation/env.ts`.
|
|
15
|
+
*
|
|
16
|
+
* 2. **It does not return `ok` with an empty list when no adapter supplied
|
|
17
|
+
* reads.** That is `refused` with the reason and the exact `attrs` key
|
|
18
|
+
* it needs, because "no missing variables" is a false statement when the code
|
|
19
|
+
* was never read.
|
|
20
|
+
*
|
|
21
|
+
* The declaration half runs regardless: configuration files are read straight
|
|
22
|
+
* from the repository, which needs no adapter and no resolution.
|
|
23
|
+
*/
|
|
24
|
+
import type { ConfigGraph, ConfigReadSite, EnvClaim, EnvEvidence, EnvFindingKind, EnvReport, RollbackFinding, RollbackReport } from "@descryy/core";
|
|
25
|
+
import type { ResolutionLevel } from "@descryy/ir";
|
|
26
|
+
import { type ToolDefinition } from "./kit.ts";
|
|
27
|
+
/**
|
|
28
|
+
* One environment/configuration finding.
|
|
29
|
+
*
|
|
30
|
+
* `claim` is the axis that matters: a `defect` is a statement about the code, a
|
|
31
|
+
* `lead` is something to look at. A variable read with no fallback and
|
|
32
|
+
* declared nowhere is the first; a variable set in one file and documented in
|
|
33
|
+
* no example file is the second, and reporting it as the first is how this
|
|
34
|
+
* check produced 18 and 107 wrong findings on two real repositories before the
|
|
35
|
+
* distinction existed.
|
|
36
|
+
*/
|
|
37
|
+
export interface EnvFindingReport {
|
|
38
|
+
readonly kind: EnvFindingKind;
|
|
39
|
+
readonly name: string;
|
|
40
|
+
readonly claim: EnvClaim;
|
|
41
|
+
readonly detail: string;
|
|
42
|
+
/** Every location the finding rests on. Never empty. */
|
|
43
|
+
readonly evidence: readonly EnvEvidence[];
|
|
44
|
+
readonly resolution: ResolutionLevel;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A variable and how much of the repository stands behind it.
|
|
48
|
+
*
|
|
49
|
+
* Only variables whose dependent set could actually be computed appear —
|
|
50
|
+
* §15.3's third check feeding the first. An unknown count is not a zero, so it
|
|
51
|
+
* is left out rather than reported as none.
|
|
52
|
+
*/
|
|
53
|
+
export interface ConfigDependencyReport {
|
|
54
|
+
readonly name: string;
|
|
55
|
+
/** A lower bound, never a total. */
|
|
56
|
+
readonly dependents: number | null;
|
|
57
|
+
/** True when the traversal's budget stopped it short. */
|
|
58
|
+
readonly truncated: boolean;
|
|
59
|
+
/** Up to three read sites. */
|
|
60
|
+
readonly readAt: readonly ConfigReadSite[];
|
|
61
|
+
/** A few dependent files, for a reader who wants to look. */
|
|
62
|
+
readonly sample: readonly string[];
|
|
63
|
+
}
|
|
64
|
+
export interface ValidateData {
|
|
65
|
+
readonly findings: readonly EnvFindingReport[];
|
|
66
|
+
/** The count before `maxFindings` capped it — P27's disclosed remainder (§4 technique 5). */
|
|
67
|
+
readonly findingsTotal: number;
|
|
68
|
+
readonly surfaces: EnvReport["surfaces"];
|
|
69
|
+
readonly reads: EnvReport["reads"];
|
|
70
|
+
/** Null when no read existed at all, so the coverage guard could not be evaluated. */
|
|
71
|
+
readonly coverage: EnvReport["coverage"];
|
|
72
|
+
/** Declared and read nowhere. A dead-configuration lead, not a finding. */
|
|
73
|
+
readonly declaredNeverRead: number;
|
|
74
|
+
/**
|
|
75
|
+
* False when no adapter supplied environment reads.
|
|
76
|
+
*
|
|
77
|
+
* The whole point of the field: with it false, "no missing variables" would
|
|
78
|
+
* be a statement about code that was never read, so the call is degraded
|
|
79
|
+
* rather than clean.
|
|
80
|
+
*/
|
|
81
|
+
readonly readsAvailable: boolean;
|
|
82
|
+
readonly configGraph: {
|
|
83
|
+
readonly counts: ConfigGraph["counts"];
|
|
84
|
+
/** True when the graph carried at least one resolved import edge. */
|
|
85
|
+
readonly importsAvailable: boolean;
|
|
86
|
+
/** The ten most-depended-on variables that had a computable dependent set. */
|
|
87
|
+
readonly mostDependedOn: readonly ConfigDependencyReport[];
|
|
88
|
+
};
|
|
89
|
+
readonly rollback: {
|
|
90
|
+
readonly findings: readonly RollbackFinding[];
|
|
91
|
+
/** The count before `maxFindings` capped it — P27's disclosed remainder (§4 technique 5). */
|
|
92
|
+
readonly findingsTotal: number;
|
|
93
|
+
readonly examined: RollbackReport["examined"];
|
|
94
|
+
/** Operations this check declined to report, by reason. The size of what it did not say. */
|
|
95
|
+
readonly withheld: RollbackReport["withheld"];
|
|
96
|
+
/** False when no source supplied migration operations. */
|
|
97
|
+
readonly ran: boolean;
|
|
98
|
+
/** Named in plain words when `ran` is false. */
|
|
99
|
+
readonly blockers: readonly string[];
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export declare const validateTool: ToolDefinition;
|
|
103
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAUH,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,WAAW,EACX,cAAc,EACd,SAAS,EACT,eAAe,EACf,cAAc,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAA0D,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAGvG;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;CACtC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC/C,6FAA6F;IAC7F,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IACnC,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACzC,2EAA2E;IAC3E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE;QACpB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QACvC,qEAAqE;QACrE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;QACnC,8EAA8E;QAC9E,QAAQ,CAAC,cAAc,EAAE,SAAS,sBAAsB,EAAE,CAAC;KAC5D,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;QAC9C,6FAA6F;QAC7F,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;QAC9C,4FAA4F;QAC5F,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;QAC9C,0DAA0D;QAC1D,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;QACtB,gDAAgD;QAChD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;KACtC,CAAC;CACH;AA4JD,eAAO,MAAM,YAAY,EAAE,cAgB1B,CAAC"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `validate` — §15's static validation engine, currently its env/config check.
|
|
3
|
+
*
|
|
4
|
+
* The architecture calls this one *"cheapest and most reliable — ship first"*,
|
|
5
|
+
* and it is the first tool here whose output is a statement about the user's
|
|
6
|
+
* code rather than a measurement of the graph.
|
|
7
|
+
*
|
|
8
|
+
* ## Two things this tool refuses to do, and both are the point
|
|
9
|
+
*
|
|
10
|
+
* 1. **It does not report a variable that is read and never declared, by
|
|
11
|
+
* default.** Measured on two real repositories, that rule produces 18 wrong
|
|
12
|
+
* findings on one and 107 on the other. A finding needs a read that asserts
|
|
13
|
+
* *requirement* — no fallback at the read site — and a declaration surface
|
|
14
|
+
* complete enough for an absence to mean something. See `validation/env.ts`.
|
|
15
|
+
*
|
|
16
|
+
* 2. **It does not return `ok` with an empty list when no adapter supplied
|
|
17
|
+
* reads.** That is `refused` with the reason and the exact `attrs` key
|
|
18
|
+
* it needs, because "no missing variables" is a false statement when the code
|
|
19
|
+
* was never read.
|
|
20
|
+
*
|
|
21
|
+
* The declaration half runs regardless: configuration files are read straight
|
|
22
|
+
* from the repository, which needs no adapter and no resolution.
|
|
23
|
+
*/
|
|
24
|
+
import { buildConfigGraph, checkEnvironment, checkRollbackReadiness, scanConfigSurfaces, scanMigrations, } from "@descryy/core";
|
|
25
|
+
import { optionalInteger, optionalStringArray } from "./kit.js";
|
|
26
|
+
const SCHEMA = {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
files: {
|
|
30
|
+
type: "array",
|
|
31
|
+
items: { type: "string" },
|
|
32
|
+
description: "Restrict the code side to these repo-relative files — the scoped-subgraph run. " +
|
|
33
|
+
"Configuration files are always read in full, because a declaration is repository-wide.",
|
|
34
|
+
},
|
|
35
|
+
coverageFloor: {
|
|
36
|
+
type: "number",
|
|
37
|
+
minimum: 0,
|
|
38
|
+
maximum: 1,
|
|
39
|
+
description: "Fraction of required variables the repository must declare somewhere before any " +
|
|
40
|
+
"missing-variable finding is emitted. Default 0.6. Lowering it trades precision for " +
|
|
41
|
+
"recall on a repository whose configuration lives outside the code.",
|
|
42
|
+
},
|
|
43
|
+
maxFindings: {
|
|
44
|
+
type: "integer",
|
|
45
|
+
minimum: 1,
|
|
46
|
+
description: "Cap on findings returned. Default 25; overflow is disclosed, not dropped.",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
additionalProperties: false,
|
|
50
|
+
};
|
|
51
|
+
async function run(args, ctx) {
|
|
52
|
+
const files = optionalStringArray(args, "files");
|
|
53
|
+
const maxFindings = optionalInteger(args, "maxFindings", 1);
|
|
54
|
+
const rawFloor = args["coverageFloor"];
|
|
55
|
+
const coverageFloor = typeof rawFloor === "number" && rawFloor >= 0 && rawFloor <= 1 ? rawFloor : undefined;
|
|
56
|
+
ctx.progress("Reading configuration files");
|
|
57
|
+
const scan = scanConfigSurfaces(ctx.session.repoPath);
|
|
58
|
+
ctx.progress("Cross-checking against environment reads in the graph");
|
|
59
|
+
const provider = ctx.session.provider();
|
|
60
|
+
const checked = checkEnvironment(provider, scan, {
|
|
61
|
+
...(files === undefined ? {} : { files }),
|
|
62
|
+
...(maxFindings === undefined ? {} : { maxFindings }),
|
|
63
|
+
...(coverageFloor === undefined ? {} : { coverageFloor }),
|
|
64
|
+
});
|
|
65
|
+
ctx.progress("Tracing what depends on each configuration variable");
|
|
66
|
+
const configGraph = buildConfigGraph(provider, scan);
|
|
67
|
+
ctx.progress("Reading migrations for destructive operations");
|
|
68
|
+
const rollback = checkRollbackReadiness(provider, scanMigrations(ctx.session.repoPath), {
|
|
69
|
+
...(files === undefined ? {} : { files }),
|
|
70
|
+
...(maxFindings === undefined ? {} : { maxFindings }),
|
|
71
|
+
});
|
|
72
|
+
const report = checked.data;
|
|
73
|
+
const defects = report.findings.filter((f) => f.claim === "defect").length;
|
|
74
|
+
const leads = report.findings.length - defects;
|
|
75
|
+
// Nothing was compared at all: no configuration files, no reads, and no
|
|
76
|
+
// migration. Any one of them alone is a real answer; none of them is not.
|
|
77
|
+
const nothingToCheck = report.surfaces.length === 0 && !report.readsAvailable && !rollback.data.ran;
|
|
78
|
+
// MK-7: the leading clause a caller reads first, graded on the axis that
|
|
79
|
+
// actually matters — `claim`. A lead or a rollback finding is worth a look;
|
|
80
|
+
// a defect is the thing this tool exists to catch. Never blur the two into
|
|
81
|
+
// one count, the exact failure `EnvFindingReport.claim`'s own doc names.
|
|
82
|
+
const otherFindings = leads + rollback.data.findings.length;
|
|
83
|
+
const verdict = defects > 0
|
|
84
|
+
? `${defects} defect(s) found`
|
|
85
|
+
: otherFindings > 0
|
|
86
|
+
? `No defects; ${otherFindings} lead(s)/rollback finding(s) to review`
|
|
87
|
+
: "Clean";
|
|
88
|
+
return {
|
|
89
|
+
result: {
|
|
90
|
+
...checked,
|
|
91
|
+
data: {
|
|
92
|
+
findings: report.findings.map((f) => ({
|
|
93
|
+
kind: f.kind,
|
|
94
|
+
name: f.name,
|
|
95
|
+
claim: f.claim,
|
|
96
|
+
detail: f.detail,
|
|
97
|
+
evidence: f.evidence,
|
|
98
|
+
resolution: f.resolution,
|
|
99
|
+
})),
|
|
100
|
+
findingsTotal: report.findingsTotal,
|
|
101
|
+
surfaces: report.surfaces,
|
|
102
|
+
reads: report.reads,
|
|
103
|
+
coverage: report.coverage,
|
|
104
|
+
declaredNeverRead: report.declaredNeverRead,
|
|
105
|
+
readsAvailable: report.readsAvailable,
|
|
106
|
+
// §15.3's third check feeds the first: a variable read by a module forty
|
|
107
|
+
// others import is a different sentence from one read by a single
|
|
108
|
+
// script. Only variables whose dependent set could be computed are
|
|
109
|
+
// carried — an unknown count is not a zero and is not worth a row.
|
|
110
|
+
configGraph: {
|
|
111
|
+
counts: configGraph.data.counts,
|
|
112
|
+
importsAvailable: configGraph.data.importsAvailable,
|
|
113
|
+
mostDependedOn: configGraph.data.variables
|
|
114
|
+
.filter((v) => v.dependents !== null && v.dependents > 0)
|
|
115
|
+
.slice(0, 10)
|
|
116
|
+
.map((v) => ({
|
|
117
|
+
name: v.name,
|
|
118
|
+
dependents: v.dependents,
|
|
119
|
+
truncated: v.dependentsTruncated,
|
|
120
|
+
readAt: v.readAt.slice(0, 3),
|
|
121
|
+
sample: v.dependentSample,
|
|
122
|
+
})),
|
|
123
|
+
},
|
|
124
|
+
rollback: {
|
|
125
|
+
findings: rollback.data.findings,
|
|
126
|
+
findingsTotal: rollback.data.findingsTotal,
|
|
127
|
+
examined: rollback.data.examined,
|
|
128
|
+
withheld: rollback.data.withheld,
|
|
129
|
+
ran: rollback.data.ran,
|
|
130
|
+
blockers: rollback.data.blockers,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
// Both checks' disclosures reach the reader. Dropping one half's notes
|
|
134
|
+
// because the other half had something to say is the silent-degradation
|
|
135
|
+
// failure rule 7 exists to prevent.
|
|
136
|
+
notes: [...checked.notes, ...rollback.notes, ...configGraph.notes],
|
|
137
|
+
truncated: checked.truncated || rollback.truncated || configGraph.truncated,
|
|
138
|
+
stamp: {
|
|
139
|
+
...checked.stamp,
|
|
140
|
+
resolutionFloor: Math.min(checked.stamp.resolutionFloor, rollback.stamp.resolutionFloor, configGraph.stamp.resolutionFloor),
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
// A missing environment variable is §11A.5's canonical name-level fact —
|
|
144
|
+
// the variable exists or it does not — which is the one claim R2 supports at
|
|
145
|
+
// class A. The shape of its value is never asserted here.
|
|
146
|
+
nameLevel: true,
|
|
147
|
+
...(nothingToCheck ? { state: "refused" } : {}),
|
|
148
|
+
headline: nothingToCheck
|
|
149
|
+
? "No configuration files, environment reads or migrations were found, so there was " +
|
|
150
|
+
"nothing to check."
|
|
151
|
+
: `${verdict}. ${report.surfaces.length} configuration file(s) declare ` +
|
|
152
|
+
`${countDeclared(report.surfaces)} variable(s); ` +
|
|
153
|
+
`${report.reads.required} variable(s) are read through an accessor that fails when unset; ` +
|
|
154
|
+
`${rollback.data.examined.operations} destructive migration operation(s) examined.`,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function countDeclared(surfaces) {
|
|
158
|
+
return surfaces.reduce((total, s) => total + s.declared, 0);
|
|
159
|
+
}
|
|
160
|
+
export const validateTool = {
|
|
161
|
+
name: "validate",
|
|
162
|
+
class: "read",
|
|
163
|
+
tier: "conclusion",
|
|
164
|
+
version: "1.0.0",
|
|
165
|
+
title: "Environment and configuration checks",
|
|
166
|
+
description: "Cross-check the environment variables the code requires against the ones this repository " +
|
|
167
|
+
"declares. Reports a variable only when the code reads it with no fallback and no " +
|
|
168
|
+
"configuration file declares it, and only when the repository's declaration surface is " +
|
|
169
|
+
"complete enough for that absence to mean something — a variable supplied by a secrets " +
|
|
170
|
+
"manager or a platform is disclosed with a count, never reported as missing. Also reports " +
|
|
171
|
+
"variables set in one configuration file and documented in no example file, stated as a lead " +
|
|
172
|
+
"rather than a defect.",
|
|
173
|
+
inputSchema: SCHEMA,
|
|
174
|
+
run,
|
|
175
|
+
};
|
|
176
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `verification_status` — §4 technique 6: *"Coverage is a separate axis and
|
|
3
|
+
* a separate call. Appending it everywhere pays on every call; a tool pays
|
|
4
|
+
* once, when the client is actually reporting."*
|
|
5
|
+
*
|
|
6
|
+
* Wraps `packages/core/src/query/verification-status.ts`'s
|
|
7
|
+
* `computeVerificationStatus` — the module's own header calls itself "the
|
|
8
|
+
* static half only" and says building the `ScopeItem[]` from a caller's refs
|
|
9
|
+
* is "the caller's job, done above this boundary." This tool is that caller.
|
|
10
|
+
*
|
|
11
|
+
* ## Real capability lookup, without ever naming a language up here
|
|
12
|
+
*
|
|
13
|
+
* `computeVerificationStatus`'s `ScopeItem.capabilities`, when supplied,
|
|
14
|
+
* lets a `notExercised` reason describe a real declared gap rather than a
|
|
15
|
+
* generic absence. The first design attempted here guessed a language from
|
|
16
|
+
* a ref's file extension and matched it against a `language` tag on a
|
|
17
|
+
* configured source — and `npm run lint` caught it immediately:
|
|
18
|
+
* `descry-boundary/no-language-vocabulary` and `no-language-branch` both
|
|
19
|
+
* fired, because `packages/*\/src/**` (this file included, not just
|
|
20
|
+
* `packages/core`) is bound by architecture principle 7 — nothing above the
|
|
21
|
+
* Canonical IR may name or dispatch on a language, full stop. A hardcoded
|
|
22
|
+
* extension table and a `.get(guessedLanguage)` lookup are exactly the
|
|
23
|
+
* "lookup dispatch" shape that rule exists to catch, not a false positive.
|
|
24
|
+
*
|
|
25
|
+
* The fix moves the decision below the boundary, where it belongs:
|
|
26
|
+
* `LanguageAdapter` (`@descryy/ir`) gained an optional
|
|
27
|
+
* `ownsPath(path): boolean` — the adapter decides, using whatever
|
|
28
|
+
* language-specific logic it wants, entirely inside `descry-adapters`,
|
|
29
|
+
* which is not bound by this repo's lint. This tool never sees or compares
|
|
30
|
+
* a language string; it just asks every loaded, configured adapter "do you
|
|
31
|
+
* own this path," and attaches whichever one says yes. An unresolved ref's
|
|
32
|
+
* `language` therefore stays `null` here always — this tool does not
|
|
33
|
+
* determine one, and does not need to: `computeVerificationStatus`'s reason
|
|
34
|
+
* text already reads correctly either way (see its own module header),
|
|
35
|
+
* naming an adapter as registered without ever naming which language it is
|
|
36
|
+
* for.
|
|
37
|
+
*
|
|
38
|
+
* A configured source that fails to import cannot be asked at all — this
|
|
39
|
+
* tool's own `notes` disclose that plainly, the same register `analyze.ts`
|
|
40
|
+
* already uses for a source that will not import.
|
|
41
|
+
*
|
|
42
|
+
* ## Resolving a ref: node id first, then file
|
|
43
|
+
*
|
|
44
|
+
* A ref that is a real node id resolves directly (`getNode`). Otherwise it
|
|
45
|
+
* is tried as a file path (`findNodes({ file: ref })`, the same reader
|
|
46
|
+
* `lookup.ts`'s `resolveOneNode` already uses for symbol/file matching): the
|
|
47
|
+
* file's own `FILE`-typed node stands in when one exists, else the node
|
|
48
|
+
* with the *weakest* resolution in that file — the same "report the
|
|
49
|
+
* weakest link" convention `resolutionFloor` uses elsewhere in this
|
|
50
|
+
* package, since a file is only as verified as its least-resolved member.
|
|
51
|
+
* A ref that resolves neither way is `notExercised`.
|
|
52
|
+
*/
|
|
53
|
+
import type { ResolutionLevel } from "@descryy/ir";
|
|
54
|
+
import { type ToolDefinition } from "./kit.ts";
|
|
55
|
+
export interface VerificationStatusExercisedItem {
|
|
56
|
+
readonly ref: string;
|
|
57
|
+
readonly resolution: ResolutionLevel;
|
|
58
|
+
}
|
|
59
|
+
export interface VerificationStatusData {
|
|
60
|
+
readonly checked: readonly string[];
|
|
61
|
+
readonly exercised: readonly VerificationStatusExercisedItem[];
|
|
62
|
+
readonly notExercised: readonly {
|
|
63
|
+
readonly scope: string;
|
|
64
|
+
readonly reason: string;
|
|
65
|
+
}[];
|
|
66
|
+
}
|
|
67
|
+
export declare const verificationStatusTool: ToolDefinition;
|
|
68
|
+
//# sourceMappingURL=verification-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-status.d.ts","sourceRoot":"","sources":["../../src/tools/verification-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAIH,OAAO,KAAK,EAA4B,eAAe,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAqBlB,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;CACtC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,SAAS,+BAA+B,EAAE,CAAC;IAC/D,QAAQ,CAAC,YAAY,EAAE,SAAS;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvF;AAoHD,eAAO,MAAM,sBAAsB,EAAE,cAgBpC,CAAC"}
|