@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,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `contracts` — "does the caller agree with the thing it is calling?"
|
|
3
|
+
*
|
|
4
|
+
* §13, in two halves that fail independently.
|
|
5
|
+
*
|
|
6
|
+
* **The path half runs today.** A call that reaches no route, a route nothing
|
|
7
|
+
* calls. Name-level facts, so R2 evidence supports them at class A.
|
|
8
|
+
*
|
|
9
|
+
* **The shape half needs both producers to attach something they do not attach
|
|
10
|
+
* yet**, and it names exactly what — see `engine.ts`. It reports
|
|
11
|
+
* `refused` with those names rather than an empty mismatch list, because
|
|
12
|
+
* "no contract mismatches found" is a false statement when nothing was compared.
|
|
13
|
+
*
|
|
14
|
+
* ## Why the tool is `ok` when only the path half ran
|
|
15
|
+
*
|
|
16
|
+
* The path half produced a real answer over real evidence. Marking the whole
|
|
17
|
+
* call `refused` because a second check did not run would hide a genuine
|
|
18
|
+
* finding behind a caveat about a different question. The shape half's status is
|
|
19
|
+
* carried in `data.shapes.ran` and in the blockers, where a reader can act on it.
|
|
20
|
+
*
|
|
21
|
+
* The one case that *is* `refused` outright: no endpoints in the graph.
|
|
22
|
+
* Then neither half looked at anything.
|
|
23
|
+
*/
|
|
24
|
+
import { checkContracts } from "@descryy/core";
|
|
25
|
+
import { briefNode, optionalInteger, optionalStringArray, } from "./kit.js";
|
|
26
|
+
const SCHEMA = {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
paths: {
|
|
30
|
+
type: "array",
|
|
31
|
+
items: { type: "string" },
|
|
32
|
+
description: "Restrict the report to endpoints whose normalised path template contains one of these " +
|
|
33
|
+
"substrings, e.g. \"/orders\".",
|
|
34
|
+
},
|
|
35
|
+
pathsOnly: {
|
|
36
|
+
type: "boolean",
|
|
37
|
+
description: "Skip the shape comparison. Faster, and the honest choice for a pre-push run on a graph " +
|
|
38
|
+
"with no type checker behind it.",
|
|
39
|
+
},
|
|
40
|
+
maxFindings: {
|
|
41
|
+
type: "integer",
|
|
42
|
+
minimum: 1,
|
|
43
|
+
description: "Cap on path findings returned. Default 25; overflow is disclosed, not dropped.",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
additionalProperties: false,
|
|
47
|
+
};
|
|
48
|
+
async function run(args, ctx) {
|
|
49
|
+
const filters = optionalStringArray(args, "paths");
|
|
50
|
+
const maxFindings = optionalInteger(args, "maxFindings", 1);
|
|
51
|
+
const pathsOnly = args["pathsOnly"] === true;
|
|
52
|
+
ctx.progress("Matching callers against routes");
|
|
53
|
+
const checked = checkContracts(ctx.session.provider(), {
|
|
54
|
+
...(maxFindings === undefined ? {} : { maxFindings }),
|
|
55
|
+
...(pathsOnly ? { pathsOnly: true } : {}),
|
|
56
|
+
});
|
|
57
|
+
const { paths, shapes } = checked.data;
|
|
58
|
+
const notes = [...checked.notes];
|
|
59
|
+
// Filtering happens after the check rather than before it, so the counts a
|
|
60
|
+
// reader sees — how many endpoints exist, how many joined — describe the whole
|
|
61
|
+
// graph. A denominator that silently shrinks with the filter would make a
|
|
62
|
+
// narrow query look like a healthy repository.
|
|
63
|
+
const matches = (template) => filters === undefined || filters.some((f) => template.includes(f));
|
|
64
|
+
const findings = paths.findings.filter((f) => matches(f.pathTemplate));
|
|
65
|
+
const mismatches = shapes.mismatches.filter((m) => matches(String(m.endpoint.attrs["pathTemplate"] ?? m.endpoint.name)));
|
|
66
|
+
if (filters !== undefined) {
|
|
67
|
+
notes.push(`Filtered to endpoints matching ${filters.map((f) => `"${f}"`).join(", ")}. The counts ` +
|
|
68
|
+
"below describe the whole graph; the lists describe the filter.");
|
|
69
|
+
}
|
|
70
|
+
const total = findings.length + mismatches.length;
|
|
71
|
+
const nothingToCheck = paths.checked.endpoints === 0;
|
|
72
|
+
// MK-7: the leading clause. Every path finding and shape mismatch here is a
|
|
73
|
+
// real defect — `contracts.ts`'s own header on `nearMiss` is what keeps a
|
|
74
|
+
// mere typo-shaped call out of this count, so a nonzero total is never a
|
|
75
|
+
// "maybe".
|
|
76
|
+
const verdict = total === 0 ? "Clean at path level" : `${total} contract mismatch(es) found`;
|
|
77
|
+
return {
|
|
78
|
+
result: {
|
|
79
|
+
...checked,
|
|
80
|
+
data: {
|
|
81
|
+
findings: findings.map((f) => ({
|
|
82
|
+
kind: f.kind,
|
|
83
|
+
method: f.method,
|
|
84
|
+
path: f.pathTemplate,
|
|
85
|
+
detail: f.detail,
|
|
86
|
+
resolution: f.resolution,
|
|
87
|
+
...(f.nearMiss === null
|
|
88
|
+
? {}
|
|
89
|
+
: { nearMiss: { kind: f.nearMiss.kind, against: f.nearMiss.against } }),
|
|
90
|
+
callers: f.callers.slice(0, 5).map(briefNode),
|
|
91
|
+
routes: f.routes.slice(0, 5).map(briefNode),
|
|
92
|
+
})),
|
|
93
|
+
shapeMismatches: mismatches.map((m) => ({
|
|
94
|
+
endpoint: m.endpoint.name,
|
|
95
|
+
direction: m.direction,
|
|
96
|
+
reader: briefNode(m.reader),
|
|
97
|
+
writer: briefNode(m.writer),
|
|
98
|
+
differences: m.differences,
|
|
99
|
+
resolution: m.resolution,
|
|
100
|
+
})),
|
|
101
|
+
checked: paths.checked,
|
|
102
|
+
shapes: {
|
|
103
|
+
ran: shapes.ran,
|
|
104
|
+
comparable: shapes.comparable,
|
|
105
|
+
consumerOnly: shapes.consumerOnly,
|
|
106
|
+
providerOnly: shapes.providerOnly,
|
|
107
|
+
unroledDtos: shapes.unroledDtos,
|
|
108
|
+
blockers: shapes.blockers,
|
|
109
|
+
},
|
|
110
|
+
unmatchedWithoutNearMiss: paths.unmatchedWithoutNearMiss,
|
|
111
|
+
},
|
|
112
|
+
notes,
|
|
113
|
+
},
|
|
114
|
+
// A path finding is a claim about names — this route exists, that one does
|
|
115
|
+
// not — which R2 fully supports. A shape mismatch is not, and `engine.ts`
|
|
116
|
+
// caps each one individually; this flag governs the answer's own headline
|
|
117
|
+
// claim, which is the path half.
|
|
118
|
+
nameLevel: true,
|
|
119
|
+
...(nothingToCheck ? { state: "refused" } : {}),
|
|
120
|
+
headline: nothingToCheck
|
|
121
|
+
? "No API endpoints are in the graph, so there is no contract to check."
|
|
122
|
+
: `${verdict}. ${paths.checked.joined} of ${paths.checked.endpoints} endpoint(s) have both ` +
|
|
123
|
+
`a caller and a route${shapes.ran ? "" : "; request and response shapes were not compared"}.`,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export const contractsTool = {
|
|
127
|
+
name: "contracts",
|
|
128
|
+
class: "read",
|
|
129
|
+
tier: "conclusion",
|
|
130
|
+
version: "1.0.0",
|
|
131
|
+
title: "Frontend/backend contract mismatches",
|
|
132
|
+
description: "Match every API caller against the route that serves it. Reports calls that reach no route " +
|
|
133
|
+
"and routes nothing calls, and — when both sides declare a shape — fields one side reads that " +
|
|
134
|
+
"the other does not send. A call with nothing resembling it on the provider side is disclosed " +
|
|
135
|
+
"as unanalysed rather than reported as broken, because the usual cause is a service outside " +
|
|
136
|
+
"this graph. Shape comparison requires R3 and is reported as not-run, with the reason, when " +
|
|
137
|
+
"the producers do not supply shapes.",
|
|
138
|
+
inputSchema: SCHEMA,
|
|
139
|
+
run,
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/tools/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAW/C,OAAO,EACL,SAAS,EACT,eAAe,EACf,mBAAmB,GAIpB,MAAM,UAAU,CAAC;AAiFlB,MAAM,MAAM,GAAG;IACb,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,KAAK,EAAE;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzB,WAAW,EACT,wFAAwF;gBACxF,+BAA+B;SAClC;QACD,SAAS,EAAE;YACT,IAAI,EAAE,SAAS;YACf,WAAW,EACT,yFAAyF;gBACzF,iCAAiC;SACpC;QACD,WAAW,EAAE;YACX,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,WAAW,EAAE,gFAAgF;SAC9F;KACF;IACD,oBAAoB,EAAE,KAAK;CACnB,CAAC;AAEX,KAAK,UAAU,GAAG,CAChB,IAA6B,EAC7B,GAAgB;IAEhB,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAE7C,GAAG,CAAC,QAAQ,CAAC,iCAAiC,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE;QACrD,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACrD,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1C,CAAC,CAAC;IAEH,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IACvC,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAEjC,2EAA2E;IAC3E,+EAA+E;IAC/E,0EAA0E;IAC1E,+CAA+C;IAC/C,MAAM,OAAO,GAAG,CAAC,QAAgB,EAAW,EAAE,CAC5C,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAChD,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CACrE,CAAC;IAEF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CACR,kCAAkC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe;YACtF,gEAAgE,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAClD,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,KAAK,CAAC,CAAC;IAErD,4EAA4E;IAC5E,0EAA0E;IAC1E,yEAAyE;IACzE,WAAW;IACX,MAAM,OAAO,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,GAAG,KAAK,8BAA8B,CAAC;IAE7F,OAAO;QACL,MAAM,EAAE;YACN,GAAG,OAAO;YACV,IAAI,EAAE;gBACJ,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC7B,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,IAAI,EAAE,CAAC,CAAC,YAAY;oBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,UAAU,EAAE,CAAC,CAAC,UAAU;oBACxB,GAAG,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI;wBACrB,CAAC,CAAC,EAAE;wBACJ,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;oBACzE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;oBAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;iBAC5C,CAAC,CAAC;gBACH,eAAe,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACtC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;oBACzB,SAAS,EAAE,CAAC,CAAC,SAAS;oBACtB,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;oBAC3B,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;oBAC3B,WAAW,EAAE,CAAC,CAAC,WAAW;oBAC1B,UAAU,EAAE,CAAC,CAAC,UAAU;iBACzB,CAAC,CAAC;gBACH,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,MAAM,EAAE;oBACN,GAAG,EAAE,MAAM,CAAC,GAAG;oBACf,UAAU,EAAE,MAAM,CAAC,UAAU;oBAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,WAAW,EAAE,MAAM,CAAC,WAAW;oBAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;iBAC1B;gBACD,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;aACzD;YACD,KAAK;SACN;QACD,2EAA2E;QAC3E,0EAA0E;QAC1E,0EAA0E;QAC1E,iCAAiC;QACjC,SAAS,EAAE,IAAI;QACf,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,QAAQ,EAAE,cAAc;YACtB,CAAC,CAAC,sEAAsE;YACxE,CAAC,CAAC,GAAG,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,MAAM,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,yBAAyB;gBAC1F,uBAAuB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iDAAiD,GAAG;KAClG,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAmB;IAC3C,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,OAAO;IAChB,KAAK,EAAE,sCAAsC;IAC7C,WAAW,EACT,6FAA6F;QAC7F,+FAA+F;QAC/F,+FAA+F;QAC/F,6FAA6F;QAC7F,6FAA6F;QAC7F,qCAAqC;IACvC,WAAW,EAAE,MAA4C;IACzD,GAAG;CACJ,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cross-pr` — "what does this change collide with, that reading the diff alone
|
|
3
|
+
* would not show?"
|
|
4
|
+
*
|
|
5
|
+
* §14's multi-PR engine, at the protocol level. Four checks exist behind it and
|
|
6
|
+
* **two of them can run today**, for a reason worth stating rather than
|
|
7
|
+
* discovering: a check is available exactly when something already produces its
|
|
8
|
+
* input.
|
|
9
|
+
*
|
|
10
|
+
* | check | § | input | today |
|
|
11
|
+
* | --- | --- | --- | --- |
|
|
12
|
+
* | hidden dependency | 14.8 | `CHANGES_WITH` edges, already in the graph | **runs** |
|
|
13
|
+
* | overlap scoring | 14.3 | stored PR scopes | **runs, over whatever is stored** |
|
|
14
|
+
* | superseded | 14.5 | git blob ids at head and at base's tip | **runs** |
|
|
15
|
+
* | migration heads | 14.6 | migration revision + parents | needs a producer |
|
|
16
|
+
*
|
|
17
|
+
* §14.8 is first because it is the one that costs nothing: the edges already
|
|
18
|
+
* exist, it needs no per-PR storage, and it works at R0 in any language with no
|
|
19
|
+
* adapter beyond file paths. For a repository whose language has no adapter at
|
|
20
|
+
* all, this is the check that still fires.
|
|
21
|
+
*
|
|
22
|
+
* ## Why the two that cannot run are declared rather than omitted
|
|
23
|
+
*
|
|
24
|
+
* `contracts.ts` set this precedent and the reasoning transfers unchanged: a
|
|
25
|
+
* tool that silently offers three of five checks lets a caller read "nothing
|
|
26
|
+
* found" as "nothing there". Both blocked checks name the producer they are
|
|
27
|
+
* waiting for, so the gap is actionable rather than mysterious.
|
|
28
|
+
*
|
|
29
|
+
* ## Everything here is Class C and that is not a defect to be fixed
|
|
30
|
+
*
|
|
31
|
+
* Co-change is evidence about **people**, not program structure — a pair that
|
|
32
|
+
* moved together two hundred times is a stronger hint and is still a hint. The
|
|
33
|
+
* checks compute their own reliability rather than being told it, and each
|
|
34
|
+
* finding carries the sentence that must travel with it. A caller rendering
|
|
35
|
+
* these as defects has broken principle 4 at the last gate.
|
|
36
|
+
*/
|
|
37
|
+
import type { DiffType, HiddenDependencyReport, IncomparablePair, NodeVerdict, OverlapFinding, SupersededReport } from "@descryy/core";
|
|
38
|
+
import type { ReliabilityClass } from "@descryy/ir";
|
|
39
|
+
import { type BriefNode, type ToolDefinition } from "./kit.ts";
|
|
40
|
+
/**
|
|
41
|
+
* A check whose input no producer writes yet.
|
|
42
|
+
*
|
|
43
|
+
* Declared rather than omitted, and `needs` says what would have to exist —
|
|
44
|
+
* a tool silently offering three of four checks lets a caller read "nothing
|
|
45
|
+
* found" as "nothing there".
|
|
46
|
+
*/
|
|
47
|
+
export interface BlockedCheck {
|
|
48
|
+
readonly check: string;
|
|
49
|
+
/** The architecture section that specifies it. */
|
|
50
|
+
readonly section: string;
|
|
51
|
+
readonly question: string;
|
|
52
|
+
readonly needs: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A file that historically moves with the change and was not touched this time.
|
|
56
|
+
*
|
|
57
|
+
* Class C, always, and `disclosure` is the sentence that must travel with it:
|
|
58
|
+
* co-change is evidence about **people**, not program structure. A caller
|
|
59
|
+
* rendering this as a defect has broken principle 4 at the last gate.
|
|
60
|
+
*/
|
|
61
|
+
export interface HiddenDependencyFinding extends BriefNode {
|
|
62
|
+
readonly coupledTo: readonly {
|
|
63
|
+
readonly file: string | null;
|
|
64
|
+
readonly support: number;
|
|
65
|
+
}[];
|
|
66
|
+
readonly strongestSupport: number;
|
|
67
|
+
readonly reliability: ReliabilityClass;
|
|
68
|
+
readonly disclosure: string;
|
|
69
|
+
}
|
|
70
|
+
export interface HiddenDependencyCheck {
|
|
71
|
+
/** False when no changed file had a single CHANGES_WITH edge: the history was not read. */
|
|
72
|
+
readonly ran: boolean;
|
|
73
|
+
readonly findings: readonly HiddenDependencyFinding[];
|
|
74
|
+
/** The count before `limit` capped it — P27's disclosed remainder (§4 technique 5). */
|
|
75
|
+
readonly findingsTotal: number;
|
|
76
|
+
readonly checked: HiddenDependencyReport["checked"];
|
|
77
|
+
/** Changed paths with no FILE node. Nothing looked at them. */
|
|
78
|
+
readonly unresolvedChanged: readonly string[];
|
|
79
|
+
}
|
|
80
|
+
export interface OverlapCheck {
|
|
81
|
+
/** False when fewer than two stored scopes exist: no pair could be compared. */
|
|
82
|
+
readonly ran: boolean;
|
|
83
|
+
readonly scopesCompared: number;
|
|
84
|
+
readonly findings: readonly OverlapFinding[];
|
|
85
|
+
/** The count before `limit` capped it — P27's disclosed remainder (§4 technique 5). */
|
|
86
|
+
readonly findingsTotal: number;
|
|
87
|
+
/** Pairs refused before comparison. An incomparable pair and a clean pair look identical otherwise. */
|
|
88
|
+
readonly incomparable: readonly IncomparablePair[];
|
|
89
|
+
readonly checked: OverlapReportChecked;
|
|
90
|
+
}
|
|
91
|
+
/** Named separately because `OverlapReport` itself is not re-exported field by field. */
|
|
92
|
+
export type OverlapReportChecked = {
|
|
93
|
+
readonly scopes: number;
|
|
94
|
+
readonly pairs: number;
|
|
95
|
+
readonly pairsOverlapping: number;
|
|
96
|
+
readonly belowThreshold: number;
|
|
97
|
+
readonly incomparable: number;
|
|
98
|
+
};
|
|
99
|
+
export interface SupersededCheck {
|
|
100
|
+
/** False when there was nothing to compare — not the same as "not superseded". */
|
|
101
|
+
readonly ran: boolean;
|
|
102
|
+
readonly verdict: boolean;
|
|
103
|
+
readonly counts: SupersededReport["counts"];
|
|
104
|
+
readonly reliability: ReliabilityClass;
|
|
105
|
+
readonly disclosure: string;
|
|
106
|
+
/** Everything not already on base, so a reader sees what is left rather than what matched. */
|
|
107
|
+
readonly remaining: readonly {
|
|
108
|
+
/** Undefined for a comparison whose candidate carried no path. */
|
|
109
|
+
readonly file: string | undefined;
|
|
110
|
+
readonly diffType: DiffType;
|
|
111
|
+
readonly verdict: NodeVerdict;
|
|
112
|
+
}[];
|
|
113
|
+
}
|
|
114
|
+
/** git rejected the range: no check ran, and `blocked` is all there is to say. */
|
|
115
|
+
export interface CrossPrGitFailure {
|
|
116
|
+
readonly blocked: readonly BlockedCheck[];
|
|
117
|
+
}
|
|
118
|
+
/** The diff is empty. A real answer: there is nothing to collide with. */
|
|
119
|
+
export interface CrossPrEmptyDiff extends CrossPrGitFailure {
|
|
120
|
+
readonly changedFiles: number;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The full answer — three checks that can run, one that cannot.
|
|
124
|
+
*
|
|
125
|
+
* Each check carries its own `ran`, because one check producing a real answer
|
|
126
|
+
* is a real answer and burying it behind a caveat about a different question
|
|
127
|
+
* is what `contracts.ts` refuses for the same reason.
|
|
128
|
+
*/
|
|
129
|
+
export interface CrossPrReport extends CrossPrEmptyDiff {
|
|
130
|
+
readonly resolvedNodes: number;
|
|
131
|
+
readonly hiddenDependencies: HiddenDependencyCheck;
|
|
132
|
+
readonly overlaps: OverlapCheck;
|
|
133
|
+
readonly superseded: SupersededCheck;
|
|
134
|
+
}
|
|
135
|
+
export type CrossPrData = CrossPrGitFailure | CrossPrEmptyDiff | CrossPrReport;
|
|
136
|
+
export declare const crossPrTool: ToolDefinition;
|
|
137
|
+
//# sourceMappingURL=cross-pr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-pr.d.ts","sourceRoot":"","sources":["../../src/tools/cross-pr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cross-pr` — "what does this change collide with, that reading the diff alone
|
|
3
|
+
* would not show?"
|
|
4
|
+
*
|
|
5
|
+
* §14's multi-PR engine, at the protocol level. Four checks exist behind it and
|
|
6
|
+
* **two of them can run today**, for a reason worth stating rather than
|
|
7
|
+
* discovering: a check is available exactly when something already produces its
|
|
8
|
+
* input.
|
|
9
|
+
*
|
|
10
|
+
* | check | § | input | today |
|
|
11
|
+
* | --- | --- | --- | --- |
|
|
12
|
+
* | hidden dependency | 14.8 | `CHANGES_WITH` edges, already in the graph | **runs** |
|
|
13
|
+
* | overlap scoring | 14.3 | stored PR scopes | **runs, over whatever is stored** |
|
|
14
|
+
* | superseded | 14.5 | git blob ids at head and at base's tip | **runs** |
|
|
15
|
+
* | migration heads | 14.6 | migration revision + parents | needs a producer |
|
|
16
|
+
*
|
|
17
|
+
* §14.8 is first because it is the one that costs nothing: the edges already
|
|
18
|
+
* exist, it needs no per-PR storage, and it works at R0 in any language with no
|
|
19
|
+
* adapter beyond file paths. For a repository whose language has no adapter at
|
|
20
|
+
* all, this is the check that still fires.
|
|
21
|
+
*
|
|
22
|
+
* ## Why the two that cannot run are declared rather than omitted
|
|
23
|
+
*
|
|
24
|
+
* `contracts.ts` set this precedent and the reasoning transfers unchanged: a
|
|
25
|
+
* tool that silently offers three of five checks lets a caller read "nothing
|
|
26
|
+
* found" as "nothing there". Both blocked checks name the producer they are
|
|
27
|
+
* waiting for, so the gap is actionable rather than mysterious.
|
|
28
|
+
*
|
|
29
|
+
* ## Everything here is Class C and that is not a defect to be fixed
|
|
30
|
+
*
|
|
31
|
+
* Co-change is evidence about **people**, not program structure — a pair that
|
|
32
|
+
* moved together two hundred times is a stronger hint and is still a hint. The
|
|
33
|
+
* checks compute their own reliability rather than being told it, and each
|
|
34
|
+
* finding carries the sentence that must travel with it. A caller rendering
|
|
35
|
+
* these as defects has broken principle 4 at the last gate.
|
|
36
|
+
*/
|
|
37
|
+
import { changedFiles, findHiddenDependencies, findOverlaps, findSuperseded, nodesInFiles, ScopeStore, supersededCandidates, } from "@descryy/core";
|
|
38
|
+
import { answer, briefNode, optionalInteger, optionalString, requiredString, } from "./kit.js";
|
|
39
|
+
const SCHEMA = {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
base: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "The branch this change would merge into. Required — there is no defensible default, and " +
|
|
45
|
+
"guessing one silently changes which diff the answer describes.",
|
|
46
|
+
},
|
|
47
|
+
head: { type: "string", description: "The tip being reviewed. Default HEAD." },
|
|
48
|
+
limit: { type: "integer", minimum: 1, description: "Cap on findings per check. Default 10." },
|
|
49
|
+
},
|
|
50
|
+
required: ["base"],
|
|
51
|
+
additionalProperties: false,
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Checks whose input no producer writes yet.
|
|
55
|
+
*
|
|
56
|
+
* Named here rather than in prose so the reply carries them as data a caller
|
|
57
|
+
* can act on. Each says what would have to exist, not merely that it does not.
|
|
58
|
+
*/
|
|
59
|
+
const BLOCKED = [
|
|
60
|
+
{
|
|
61
|
+
check: "migration-heads",
|
|
62
|
+
section: "14.6",
|
|
63
|
+
question: "Would merging these changes leave more than one migration head?",
|
|
64
|
+
needs: "a producer emitting each migration's revision and declared parents. The check is " +
|
|
65
|
+
"framework-agnostic by design — a revision, its parents and which change adds it is the " +
|
|
66
|
+
"shape every migration tool has — so this is one adapter, not one per framework.",
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
async function run(args, ctx) {
|
|
70
|
+
const base = requiredString(args, "base");
|
|
71
|
+
const head = optionalString(args, "head") ?? "HEAD";
|
|
72
|
+
const limit = optionalInteger(args, "limit", 1) ?? 10;
|
|
73
|
+
const { session } = ctx;
|
|
74
|
+
const stamp = session.provider().baseStamp();
|
|
75
|
+
const envelope = {
|
|
76
|
+
resolutionFloor: 0,
|
|
77
|
+
commitSha: stamp.commitSha,
|
|
78
|
+
graphBuiltAt: stamp.graphBuiltAt,
|
|
79
|
+
irSchemaVersion: stamp.irSchemaVersion,
|
|
80
|
+
// A file's presence or absence in a diff, and which symbols two changes both
|
|
81
|
+
// name, are name-level facts. Both still cap at C on R0 evidence — the
|
|
82
|
+
// carve-out that lifts a name-level fact to A begins at R2.
|
|
83
|
+
nameLevel: true,
|
|
84
|
+
};
|
|
85
|
+
ctx.progress(`Diffing ${base}...${head}`, 1, 3);
|
|
86
|
+
let files;
|
|
87
|
+
try {
|
|
88
|
+
files = await changedFiles(session.repoPath, base, head);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
return answer({
|
|
92
|
+
...envelope,
|
|
93
|
+
headline: `Could not diff ${base}...${head}.`,
|
|
94
|
+
state: "refused",
|
|
95
|
+
data: { blocked: BLOCKED },
|
|
96
|
+
notes: [
|
|
97
|
+
`git rejected the range: ${error.message.trim()}.`,
|
|
98
|
+
"No check ran, which is not a finding that this change collides with nothing.",
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (files.length === 0) {
|
|
103
|
+
return answer({
|
|
104
|
+
...envelope,
|
|
105
|
+
headline: "The diff is empty.",
|
|
106
|
+
data: { changedFiles: 0, blocked: BLOCKED },
|
|
107
|
+
notes: ["An empty diff is a real answer: there is nothing to collide with."],
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
ctx.progress(`Resolving ${files.length} changed file(s)`, 2, 3);
|
|
111
|
+
const resolved = nodesInFiles(session.store().driver, files);
|
|
112
|
+
// §14.8 — the historically coupled file that was NOT touched.
|
|
113
|
+
ctx.progress("Reading co-change history", 3, 3);
|
|
114
|
+
const hidden = findHiddenDependencies(session.provider(), resolved.nodes.map((n) => n.id), resolved.missing, { limit });
|
|
115
|
+
// §14.3 — overlap against every scope computed on this same graph. Nothing
|
|
116
|
+
// writes `pr_scopes` yet, so this ordinarily finds fewer than two and says so;
|
|
117
|
+
// the check reports that as "no pair could be compared", never as "no
|
|
118
|
+
// conflicts", which is the distinction it exists to hold.
|
|
119
|
+
const scopes = stamp.commitSha === null
|
|
120
|
+
? []
|
|
121
|
+
: new ScopeStore(session.store().driver).loadForGraph(session.config.repo, stamp.commitSha);
|
|
122
|
+
const overlaps = findOverlaps(scopes, { limit });
|
|
123
|
+
// §14.5 — is this work already on base? Producer and check both in core: git
|
|
124
|
+
// computes the content hashes, so nothing here reads code.
|
|
125
|
+
ctx.progress("Comparing against base");
|
|
126
|
+
const produced = await supersededCandidates(session.repoPath, base, head);
|
|
127
|
+
const superseded = findSuperseded(produced.candidates, {
|
|
128
|
+
fingerprintBasis: produced.fingerprintBasis,
|
|
129
|
+
});
|
|
130
|
+
const notes = [...hidden.notes, ...overlaps.notes, ...produced.notes, ...superseded.notes];
|
|
131
|
+
if (stamp.commitSha === null) {
|
|
132
|
+
notes.push("The graph carries no commit sha, so no stored PR scope could be matched to it. Overlap " +
|
|
133
|
+
"scoring did not run — scopes are only comparable against the graph they were computed on.");
|
|
134
|
+
}
|
|
135
|
+
notes.push(`${BLOCKED.length} of the four multi-PR checks did not run because nothing produces their ` +
|
|
136
|
+
`input yet: ${BLOCKED.map((b) => b.check).join(", ")}. Each is listed in "blocked" with ` +
|
|
137
|
+
"what it is waiting for. Their absence is not a clean result.");
|
|
138
|
+
// `refused` only when NOTHING looked at anything. One check producing a
|
|
139
|
+
// real answer is a real answer, and burying it behind a caveat about a
|
|
140
|
+
// different question is what `contracts.ts` refuses for the same reason.
|
|
141
|
+
const anythingRan = hidden.data.analysed || scopes.length >= 2 || superseded.analysed;
|
|
142
|
+
// MK-7: the leading clause, worded to never read as a defect claim — this
|
|
143
|
+
// file's own header is explicit that every finding here is Class C evidence
|
|
144
|
+
// about people, not program structure, and "N found" would read exactly
|
|
145
|
+
// like the graded verdict `validate`/`contracts` give their real defects.
|
|
146
|
+
const hintCount = hidden.data.findings.length + overlaps.findings.length;
|
|
147
|
+
const verdict = hintCount === 0 ? "No collisions detected" : `${hintCount} potential collision(s) to review`;
|
|
148
|
+
return {
|
|
149
|
+
result: {
|
|
150
|
+
data: {
|
|
151
|
+
changedFiles: files.length,
|
|
152
|
+
resolvedNodes: resolved.nodes.length,
|
|
153
|
+
hiddenDependencies: {
|
|
154
|
+
ran: hidden.data.analysed,
|
|
155
|
+
findings: hidden.data.findings.map((f) => ({
|
|
156
|
+
...briefNode(f.node),
|
|
157
|
+
coupledTo: f.coupledTo.map((c) => ({ file: c.node.file, support: c.support })),
|
|
158
|
+
strongestSupport: f.strongestSupport,
|
|
159
|
+
reliability: f.reliability,
|
|
160
|
+
disclosure: f.disclosure,
|
|
161
|
+
})),
|
|
162
|
+
findingsTotal: hidden.data.findingsTotal,
|
|
163
|
+
checked: hidden.data.checked,
|
|
164
|
+
unresolvedChanged: hidden.data.unresolvedChanged,
|
|
165
|
+
},
|
|
166
|
+
overlaps: {
|
|
167
|
+
ran: scopes.length >= 2,
|
|
168
|
+
scopesCompared: scopes.length,
|
|
169
|
+
findings: overlaps.findings,
|
|
170
|
+
findingsTotal: overlaps.findingsTotal,
|
|
171
|
+
incomparable: overlaps.incomparable,
|
|
172
|
+
checked: overlaps.checked,
|
|
173
|
+
},
|
|
174
|
+
superseded: {
|
|
175
|
+
ran: superseded.analysed,
|
|
176
|
+
verdict: superseded.superseded,
|
|
177
|
+
counts: superseded.counts,
|
|
178
|
+
reliability: superseded.reliability,
|
|
179
|
+
disclosure: superseded.disclosure,
|
|
180
|
+
remaining: superseded.comparisons
|
|
181
|
+
.filter((c) => c.verdict !== "already-in-base")
|
|
182
|
+
.map((c) => ({ file: c.file, diffType: c.diffType, verdict: c.verdict })),
|
|
183
|
+
},
|
|
184
|
+
blocked: BLOCKED,
|
|
185
|
+
},
|
|
186
|
+
stamp: hidden.stamp,
|
|
187
|
+
truncated: hidden.truncated,
|
|
188
|
+
notes,
|
|
189
|
+
},
|
|
190
|
+
...(anythingRan ? {} : { state: "refused" }),
|
|
191
|
+
nameLevel: true,
|
|
192
|
+
headline: anythingRan
|
|
193
|
+
? `${verdict}. ${hidden.data.findings.length} historically coupled file(s) were not touched; ` +
|
|
194
|
+
`${overlaps.findings.length} overlapping change pair(s) scored above the conflict ` +
|
|
195
|
+
`threshold; ${superseded.superseded ? "this change's work is already on base" : `${superseded.counts.alreadyInBase} of ${superseded.counts.total} touched file(s) already match base`}. ` +
|
|
196
|
+
`${BLOCKED.length} of four checks could not run.`
|
|
197
|
+
: "No multi-PR check was able to run on this change. That is a statement about the " +
|
|
198
|
+
"evidence available, not about the change.",
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
export const crossPrTool = {
|
|
202
|
+
name: "cross_pr",
|
|
203
|
+
class: "read",
|
|
204
|
+
tier: "conclusion",
|
|
205
|
+
version: "1.0.0",
|
|
206
|
+
title: "Cross-change collisions",
|
|
207
|
+
description: "What this change collides with that reading its diff alone would not show: files it " +
|
|
208
|
+
"historically moves with and did not touch this time (§14.8), other in-flight changes " +
|
|
209
|
+
"editing the same important nodes (§14.3), and whether the work is already on base by " +
|
|
210
|
+
"another route (§14.5). Findings are Class C hints about how people edit this repository, " +
|
|
211
|
+
"never claims about what breaks. The remaining check — migration head conflicts — is " +
|
|
212
|
+
"declared with what it is waiting for rather than silently omitted.",
|
|
213
|
+
inputSchema: SCHEMA,
|
|
214
|
+
run,
|
|
215
|
+
};
|
|
216
|
+
//# sourceMappingURL=cross-pr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-pr.js","sourceRoot":"","sources":["../../src/tools/cross-pr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `get_git_diff` — §18's "other useful Git tool": a live textual diff
|
|
3
|
+
* between two refs. P27's disclosed remainder — `ai-layer-plan.md` §3's
|
|
4
|
+
* re-derivation found `history.ts`'s own header already stating why it
|
|
5
|
+
* cannot be stretched into this shape: it is scoped to the stored
|
|
6
|
+
* `CHANGES_WITH` ledger, not a live `git diff`. `changedFiles`
|
|
7
|
+
* (`cross-pr.ts`) answers "which files changed" as a bare path list; this
|
|
8
|
+
* answers "what changed in them" — per-file status and line counts always,
|
|
9
|
+
* plus the unified-diff patch text when it is cheap enough to hand to a
|
|
10
|
+
* model (§4: the client's context window is not this tool's to spend).
|
|
11
|
+
*/
|
|
12
|
+
import type { GitDiffFile } from "@descryy/core";
|
|
13
|
+
import { type ToolDefinition } from "./kit.ts";
|
|
14
|
+
export type GitDiffEntry = GitDiffFile;
|
|
15
|
+
/**
|
|
16
|
+
* One shape for all three states (`ok` / `empty` / `refused`) — unlike
|
|
17
|
+
* `cross-pr`'s union, a git-rejected range and a genuinely empty diff carry
|
|
18
|
+
* the identical fields here (`files: []`, `filesTotal: 0`); `state` and
|
|
19
|
+
* `disclosures` are what tell them apart, not the payload's shape.
|
|
20
|
+
*/
|
|
21
|
+
export interface GitDiffData {
|
|
22
|
+
readonly base: string;
|
|
23
|
+
readonly head: string;
|
|
24
|
+
/** Capped by `limit`; `filesTotal` is the uncapped count. Empty on a git failure. */
|
|
25
|
+
readonly files: readonly GitDiffEntry[];
|
|
26
|
+
readonly filesTotal: number;
|
|
27
|
+
}
|
|
28
|
+
export declare const gitDiffTool: ToolDefinition;
|
|
29
|
+
//# sourceMappingURL=git-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-diff.d.ts","sourceRoot":"","sources":["../../src/tools/git-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAKlB,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAsGD,eAAO,MAAM,WAAW,EAAE,cAczB,CAAC"}
|