@bridge_gpt/mcp-server 0.2.24 → 0.2.26
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/README.md +98 -28
- package/build/agents.generated.js +1 -1
- package/build/bridge-api-urls.js +31 -0
- package/build/commands.generated.js +5 -5
- package/build/conductor/epic-reconcile.js +7 -1
- package/build/conductor/epic-runtime.js +5 -0
- package/build/conductor-bundle-artifacts.js +802 -0
- package/build/conductor-bundle-cli.js +256 -0
- package/build/connect-github-api.js +365 -0
- package/build/connect-github.js +415 -0
- package/build/decision-page-schema.js +34 -5
- package/build/decision-page-template.js +117 -35
- package/build/docs.generated.js +2 -1
- package/build/doctor.js +148 -1
- package/build/env-flags.js +31 -0
- package/build/index.js +3467 -498
- package/build/init.js +7 -3
- package/build/install-bridge.js +624 -38
- package/build/install-doctor.js +64 -0
- package/build/mcp-host-config.js +521 -0
- package/build/mcp-host-targets.js +194 -0
- package/build/mcp-install-state.js +175 -0
- package/build/pipelines.generated.js +127 -132
- package/build/readme.generated.js +1 -1
- package/build/start-tickets.js +166 -18
- package/build/tool-surface-gating.js +396 -0
- package/build/version.generated.js +1 -1
- package/docs/install/github-app.md +80 -17
- package/docs/install/mcp-tool-integrations.md +2 -2
- package/package.json +5 -5
- package/pipelines/learn-repository.json +111 -119
- package/public/css/main.min.css +258 -65
- package/public/css/main.min.css.map +1 -1
- package/public/js/main.min.js +188 -92
- package/public/js/main.min.js.map +1 -1
- package/smoke-test/SMOKE-TEST.md +4 -4
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tool-surface-gating — the fail-open MCP tool-surface capability consumer
|
|
3
|
+
* (BAPI-641).
|
|
4
|
+
*
|
|
5
|
+
* This module owns the client-side half of dynamic capability gating. The
|
|
6
|
+
* backend `GET /jira/mcp/tool-surface` route (BAPI-640) reports the set of
|
|
7
|
+
* physical tool IDs it would hard-block for a repo right now. This module:
|
|
8
|
+
*
|
|
9
|
+
* 1. probes that endpoint under one absolute 500 ms deadline (`probeToolSurface`),
|
|
10
|
+
* always resolving to a result union — never rejecting;
|
|
11
|
+
* 2. installs a custom `tools/list` handler that delegates to the SDK's own
|
|
12
|
+
* handler and then SUBTRACTS the capability-hidden tool names, intersected
|
|
13
|
+
* with the locally advertised profile surface (`createToolSurfaceGate`);
|
|
14
|
+
* 3. re-probes on a jittered 12–18 s poll and emits `tools/list_changed` only
|
|
15
|
+
* when the effective visible-name set actually changes.
|
|
16
|
+
*
|
|
17
|
+
* Design invariants:
|
|
18
|
+
* - FAIL-OPEN. A timeout, unreachable backend, non-2xx, malformed payload,
|
|
19
|
+
* `complete: false`, or unsupported schema all advertise the FULL profile
|
|
20
|
+
* surface (empty hidden set). The backend, not this module, is the
|
|
21
|
+
* authoritative enforcement boundary.
|
|
22
|
+
* - NEVER `.disable()`. Capability gating only subtracts from `tools/list`
|
|
23
|
+
* projection. It must NEVER call `.disable()` or mutate the SDK `enabled`
|
|
24
|
+
* flag, because doing so would ALSO block `tools/call` and the in-process
|
|
25
|
+
* `TOOL_HANDLERS` dispatch — preventing a stale client call from reaching
|
|
26
|
+
* the authoritative backend refusal.
|
|
27
|
+
* - SECRET-SAFE. Logs and result unions carry only stable reason/subtype
|
|
28
|
+
* vocabulary, secret-free tool IDs, counts, and catalog revisions — never
|
|
29
|
+
* URLs, headers, response bodies, credentials, or raw exceptions.
|
|
30
|
+
*/
|
|
31
|
+
import { getMethodLiteral } from "@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Protocol + timing constants
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
/** The `/mcp/tool-surface` surface-contract versions this consumer recognizes. */
|
|
36
|
+
export const RECOGNIZED_TOOL_SURFACE_SCHEMA_VERSIONS = new Set([1]);
|
|
37
|
+
/** The single recognized schema version (convenience export for tests). */
|
|
38
|
+
export const TOOL_SURFACE_SCHEMA_VERSION = 1;
|
|
39
|
+
/** Absolute end-to-end deadline for one probe (header resolve + fetch + parse). */
|
|
40
|
+
export const TOOL_SURFACE_PROBE_DEADLINE_MS = 500;
|
|
41
|
+
/** Inclusive lower bound of the recurring-poll jitter window. */
|
|
42
|
+
export const TOOL_SURFACE_POLL_MIN_MS = 12_000;
|
|
43
|
+
/** Inclusive upper bound of the recurring-poll jitter window. */
|
|
44
|
+
export const TOOL_SURFACE_POLL_MAX_MS = 18_000;
|
|
45
|
+
function timeoutResult() {
|
|
46
|
+
return { reason: "timeout", blockedTools: new Set() };
|
|
47
|
+
}
|
|
48
|
+
function malformedResult(subtype) {
|
|
49
|
+
return { reason: "malformed", subtype, blockedTools: new Set() };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Validate a parsed JSON body against the exact backend contract. Returns a
|
|
53
|
+
* `blocked` decision for a valid, complete, recognized response (including one
|
|
54
|
+
* with zero blocked tools) or a fail-open `malformed` decision with a sanitized
|
|
55
|
+
* subtype. An unfamiliar `catalog_revision` is INFORMATIONAL and never a
|
|
56
|
+
* fail-open trigger.
|
|
57
|
+
*/
|
|
58
|
+
export function validateToolSurfacePayload(body) {
|
|
59
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) {
|
|
60
|
+
return malformedResult("invalid-shape");
|
|
61
|
+
}
|
|
62
|
+
const p = body;
|
|
63
|
+
if (typeof p.schema_version !== "number" ||
|
|
64
|
+
!Number.isInteger(p.schema_version)) {
|
|
65
|
+
return malformedResult("invalid-shape");
|
|
66
|
+
}
|
|
67
|
+
if (!RECOGNIZED_TOOL_SURFACE_SCHEMA_VERSIONS.has(p.schema_version)) {
|
|
68
|
+
return malformedResult("unsupported-schema");
|
|
69
|
+
}
|
|
70
|
+
if (typeof p.complete !== "boolean") {
|
|
71
|
+
return malformedResult("invalid-shape");
|
|
72
|
+
}
|
|
73
|
+
if (typeof p.evaluated_tool_count !== "number" ||
|
|
74
|
+
!Number.isInteger(p.evaluated_tool_count) ||
|
|
75
|
+
p.evaluated_tool_count < 0) {
|
|
76
|
+
return malformedResult("invalid-shape");
|
|
77
|
+
}
|
|
78
|
+
if (typeof p.catalog_revision !== "string") {
|
|
79
|
+
return malformedResult("invalid-shape");
|
|
80
|
+
}
|
|
81
|
+
if (!Array.isArray(p.blocked_tools) ||
|
|
82
|
+
!p.blocked_tools.every((t) => typeof t === "string")) {
|
|
83
|
+
return malformedResult("invalid-shape");
|
|
84
|
+
}
|
|
85
|
+
if (!p.complete) {
|
|
86
|
+
return malformedResult("incomplete");
|
|
87
|
+
}
|
|
88
|
+
// A complete response MUST carry a non-empty catalog revision.
|
|
89
|
+
if (p.catalog_revision.length === 0) {
|
|
90
|
+
return malformedResult("invalid-shape");
|
|
91
|
+
}
|
|
92
|
+
// Insertion-preserving set; duplicates collapse harmlessly. Unknown physical
|
|
93
|
+
// IDs remain valid at the probe boundary — the later projection intersects
|
|
94
|
+
// them with the locally advertised surface.
|
|
95
|
+
const blockedTools = new Set(p.blocked_tools);
|
|
96
|
+
return {
|
|
97
|
+
reason: "blocked",
|
|
98
|
+
catalogRevision: p.catalog_revision,
|
|
99
|
+
evaluatedToolCount: p.evaluated_tool_count,
|
|
100
|
+
blockedTools,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Issue ONE authenticated GET to the tool-surface endpoint and classify the
|
|
105
|
+
* result under a single absolute deadline that covers async header resolution,
|
|
106
|
+
* the fetch, response-body consumption, JSON parsing, and validation.
|
|
107
|
+
*
|
|
108
|
+
* This function NEVER rejects: every failure — timeout, lifecycle abort, network
|
|
109
|
+
* error, non-2xx, invalid JSON, invalid shape, incomplete evaluation, or
|
|
110
|
+
* unsupported schema — resolves to a fail-open result union. That contract lets
|
|
111
|
+
* the non-awaited startup probe run without risking an unhandled rejection.
|
|
112
|
+
*/
|
|
113
|
+
export async function probeToolSurface(options) {
|
|
114
|
+
const deadlineMs = options.deadlineMs ?? TOOL_SURFACE_PROBE_DEADLINE_MS;
|
|
115
|
+
// Combined abort controller: the deadline timer OR the lifecycle signal aborts
|
|
116
|
+
// an in-flight fetch. Composing manually (rather than AbortSignal.any) keeps
|
|
117
|
+
// the runtime floor low and the abort wiring explicit.
|
|
118
|
+
const controller = new AbortController();
|
|
119
|
+
const onLifecycleAbort = () => controller.abort();
|
|
120
|
+
if (options.abortSignal) {
|
|
121
|
+
if (options.abortSignal.aborted)
|
|
122
|
+
controller.abort();
|
|
123
|
+
else
|
|
124
|
+
options.abortSignal.addEventListener("abort", onLifecycleAbort, {
|
|
125
|
+
once: true,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
let timer;
|
|
129
|
+
const deadlinePromise = new Promise((resolve) => {
|
|
130
|
+
timer = setTimeout(() => {
|
|
131
|
+
controller.abort();
|
|
132
|
+
resolve(timeoutResult());
|
|
133
|
+
}, deadlineMs);
|
|
134
|
+
});
|
|
135
|
+
// Resolve promptly to timeout on any abort, regardless of which async phase is
|
|
136
|
+
// pending (header resolution can never begin a fetch, so it needs this too).
|
|
137
|
+
const abortPromise = new Promise((resolve) => {
|
|
138
|
+
if (controller.signal.aborted) {
|
|
139
|
+
resolve(timeoutResult());
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
controller.signal.addEventListener("abort", () => resolve(timeoutResult()), {
|
|
143
|
+
once: true,
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
const workPromise = (async () => {
|
|
147
|
+
try {
|
|
148
|
+
const headers = await options.resolveHeaders();
|
|
149
|
+
if (controller.signal.aborted)
|
|
150
|
+
return timeoutResult();
|
|
151
|
+
const resp = await options.fetchFn(options.url, {
|
|
152
|
+
method: "GET",
|
|
153
|
+
headers,
|
|
154
|
+
signal: controller.signal,
|
|
155
|
+
});
|
|
156
|
+
if (!resp.ok)
|
|
157
|
+
return malformedResult("non-2xx");
|
|
158
|
+
let parsed;
|
|
159
|
+
try {
|
|
160
|
+
parsed = await resp.json();
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
if (controller.signal.aborted)
|
|
164
|
+
return timeoutResult();
|
|
165
|
+
return malformedResult("invalid-json");
|
|
166
|
+
}
|
|
167
|
+
return validateToolSurfacePayload(parsed);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// Abort (deadline or lifecycle) surfaces here as a rejected fetch. Any
|
|
171
|
+
// other rejection is a network-class failure. Raw exception text is never
|
|
172
|
+
// propagated into the result.
|
|
173
|
+
if (controller.signal.aborted)
|
|
174
|
+
return timeoutResult();
|
|
175
|
+
return malformedResult("network");
|
|
176
|
+
}
|
|
177
|
+
})();
|
|
178
|
+
try {
|
|
179
|
+
return await Promise.race([workPromise, deadlinePromise, abortPromise]);
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
if (timer)
|
|
183
|
+
clearTimeout(timer);
|
|
184
|
+
if (options.abortSignal) {
|
|
185
|
+
options.abortSignal.removeEventListener("abort", onLifecycleAbort);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const defaultScheduler = {
|
|
190
|
+
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
191
|
+
clearTimeout: (handle) => clearTimeout(handle),
|
|
192
|
+
random: () => Math.random(),
|
|
193
|
+
};
|
|
194
|
+
/** Log a gating decision with secret-free fields only. */
|
|
195
|
+
function logDecision(logger, result, hiddenCount, hiddenNames) {
|
|
196
|
+
const revision = result.reason === "blocked" ? result.catalogRevision : "n/a";
|
|
197
|
+
const subtype = result.reason === "malformed" ? result.subtype : "n/a";
|
|
198
|
+
logger(`tool-surface gating: reason=${result.reason} subtype=${subtype} ` +
|
|
199
|
+
`hidden=${hiddenCount} revision=${revision} ` +
|
|
200
|
+
`hidden_tools=[${hiddenNames.join(", ")}]`);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Build the capability gate. The gate wraps the SDK `tools/list` handler so the
|
|
204
|
+
* FIRST list awaits the stored startup probe, atomically applies the resulting
|
|
205
|
+
* hidden-set snapshot, delegates to the SDK handler, and filters ONLY the
|
|
206
|
+
* capability-hidden names out of the returned tools (preserving every SDK tool
|
|
207
|
+
* definition object, its order, and all non-`tools` response properties).
|
|
208
|
+
*/
|
|
209
|
+
export function createToolSurfaceGate(options) {
|
|
210
|
+
const { startupProbe, advertised, originalListHandler, freshProbe, notify, logger, lifecycleController, } = options;
|
|
211
|
+
const scheduler = options.scheduler ?? defaultScheduler;
|
|
212
|
+
const advertisedNames = new Set(advertised.map((r) => r.name));
|
|
213
|
+
// Immutable-replacement state. `hiddenNames` is always swapped as a whole
|
|
214
|
+
// snapshot so a list request or poll completion never observes a partial set.
|
|
215
|
+
let hiddenNames = new Set();
|
|
216
|
+
// The last visible-name set actually served to a client, or null before the
|
|
217
|
+
// first list. Notifications are suppressed until a client has been served.
|
|
218
|
+
let lastServedVisible = null;
|
|
219
|
+
let catalogRevision = null;
|
|
220
|
+
let startupApplied = false;
|
|
221
|
+
let timer;
|
|
222
|
+
let closed = false;
|
|
223
|
+
/** Derive the effective hidden set: backend IDs ∩ advertised names. */
|
|
224
|
+
function deriveHidden(result) {
|
|
225
|
+
if (result.reason !== "blocked" || result.blockedTools.size === 0) {
|
|
226
|
+
return new Set();
|
|
227
|
+
}
|
|
228
|
+
const hidden = new Set();
|
|
229
|
+
for (const id of result.blockedTools) {
|
|
230
|
+
if (advertisedNames.has(id))
|
|
231
|
+
hidden.add(id);
|
|
232
|
+
}
|
|
233
|
+
return hidden;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Derive the visible-name set: advertised registrations that are BOTH
|
|
237
|
+
* currently SDK-enabled AND not capability-hidden. This intersects profile
|
|
238
|
+
* registration (advertised), current enabled state, and capability hiding.
|
|
239
|
+
*/
|
|
240
|
+
function deriveVisible(hidden) {
|
|
241
|
+
const visible = new Set();
|
|
242
|
+
for (const reg of advertised) {
|
|
243
|
+
if (!reg.isEnabled())
|
|
244
|
+
continue;
|
|
245
|
+
if (hidden.has(reg.name))
|
|
246
|
+
continue;
|
|
247
|
+
visible.add(reg.name);
|
|
248
|
+
}
|
|
249
|
+
return visible;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Apply a probe decision as an immutable snapshot: swap `hiddenNames`, log,
|
|
253
|
+
* and track catalog-revision transitions. Does NOT notify — callers decide.
|
|
254
|
+
*/
|
|
255
|
+
function applyDecision(result) {
|
|
256
|
+
const nextHidden = deriveHidden(result);
|
|
257
|
+
hiddenNames = nextHidden;
|
|
258
|
+
logDecision(logger, result, nextHidden.size, Array.from(nextHidden));
|
|
259
|
+
if (result.reason === "blocked" && result.catalogRevision !== catalogRevision) {
|
|
260
|
+
if (catalogRevision !== null) {
|
|
261
|
+
logger(`tool-surface gating: catalog_revision ${catalogRevision} -> ${result.catalogRevision}`);
|
|
262
|
+
}
|
|
263
|
+
catalogRevision = result.catalogRevision;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/** Project the SDK list result, subtracting only capability-hidden names. */
|
|
267
|
+
function projectList(original) {
|
|
268
|
+
const tools = original.tools.filter((tool) => !hiddenNames.has(tool.name));
|
|
269
|
+
return { ...original, tools };
|
|
270
|
+
}
|
|
271
|
+
const handleList = async (request, extra) => {
|
|
272
|
+
// First list awaits the SAME stored startup promise, then applies its
|
|
273
|
+
// snapshot exactly once (concurrent first calls both await; only the first
|
|
274
|
+
// to run after resolution applies — JS runs applyDecision without preemption).
|
|
275
|
+
const startupResult = await startupProbe;
|
|
276
|
+
if (!startupApplied) {
|
|
277
|
+
startupApplied = true;
|
|
278
|
+
applyDecision(startupResult);
|
|
279
|
+
}
|
|
280
|
+
const original = await originalListHandler(request, extra);
|
|
281
|
+
const projected = projectList(original);
|
|
282
|
+
// Record the first served visible-name baseline (from what we actually
|
|
283
|
+
// serve). Subsequent lists refresh it so poll-driven notifications compare
|
|
284
|
+
// against the latest served surface.
|
|
285
|
+
lastServedVisible = new Set(projected.tools.map((t) => t.name));
|
|
286
|
+
return projected;
|
|
287
|
+
};
|
|
288
|
+
/** One poll cycle: fresh probe, apply, notify only on a real visible change. */
|
|
289
|
+
async function pollOnce() {
|
|
290
|
+
let result;
|
|
291
|
+
try {
|
|
292
|
+
result = await freshProbe();
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
// freshProbe is contracted never to reject, but stay fail-open regardless.
|
|
296
|
+
result = timeoutResult();
|
|
297
|
+
}
|
|
298
|
+
if (closed)
|
|
299
|
+
return;
|
|
300
|
+
const previousVisibleServed = lastServedVisible;
|
|
301
|
+
applyDecision(result);
|
|
302
|
+
const nextVisible = deriveVisible(hiddenNames);
|
|
303
|
+
// Suppress notifications before any client has received its first list.
|
|
304
|
+
if (previousVisibleServed === null)
|
|
305
|
+
return;
|
|
306
|
+
if (!setsEqual(previousVisibleServed, nextVisible)) {
|
|
307
|
+
// The served surface changes; update the baseline BEFORE notifying so a
|
|
308
|
+
// notification-driven re-list compares against the new baseline.
|
|
309
|
+
lastServedVisible = nextVisible;
|
|
310
|
+
try {
|
|
311
|
+
notify();
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
// A notification failure must not revert state or stop future polls.
|
|
315
|
+
logger("tool-surface gating: notification failed (suppressed)");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/** Schedule the next poll after the previous one settles (recursive setTimeout). */
|
|
320
|
+
function scheduleNext() {
|
|
321
|
+
if (closed)
|
|
322
|
+
return;
|
|
323
|
+
const span = TOOL_SURFACE_POLL_MAX_MS - TOOL_SURFACE_POLL_MIN_MS;
|
|
324
|
+
const delay = Math.round(TOOL_SURFACE_POLL_MIN_MS + scheduler.random() * span);
|
|
325
|
+
timer = scheduler.setTimeout(() => {
|
|
326
|
+
// Run one probe to completion, THEN schedule the next — never overlapping.
|
|
327
|
+
void pollOnce().finally(() => {
|
|
328
|
+
scheduleNext();
|
|
329
|
+
});
|
|
330
|
+
}, delay);
|
|
331
|
+
// Do not let the poll timer keep the process alive.
|
|
332
|
+
if (timer && typeof timer.unref === "function")
|
|
333
|
+
timer.unref();
|
|
334
|
+
}
|
|
335
|
+
function startPolling() {
|
|
336
|
+
if (closed)
|
|
337
|
+
return;
|
|
338
|
+
scheduleNext();
|
|
339
|
+
}
|
|
340
|
+
function close() {
|
|
341
|
+
if (closed)
|
|
342
|
+
return;
|
|
343
|
+
closed = true;
|
|
344
|
+
if (timer) {
|
|
345
|
+
scheduler.clearTimeout(timer);
|
|
346
|
+
timer = undefined;
|
|
347
|
+
}
|
|
348
|
+
if (!lifecycleController.signal.aborted)
|
|
349
|
+
lifecycleController.abort();
|
|
350
|
+
}
|
|
351
|
+
return { handleList, startPolling, close };
|
|
352
|
+
}
|
|
353
|
+
/** Value-equality for two string sets. */
|
|
354
|
+
function setsEqual(a, b) {
|
|
355
|
+
if (a.size !== b.size)
|
|
356
|
+
return false;
|
|
357
|
+
for (const v of a) {
|
|
358
|
+
if (!b.has(v))
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
/** Fixed, sanitized boot error (never includes map contents or config). */
|
|
364
|
+
const COMPAT_ERROR = "tool-surface gating: incompatible MCP SDK — the tools/list handler could not be resolved for override.";
|
|
365
|
+
/**
|
|
366
|
+
* Install the custom `tools/list` handler over the SDK's, returning the captured
|
|
367
|
+
* original handler for delegation. Resolves the method literal from the schema
|
|
368
|
+
* and asserts it is exactly `tools/list`; asserts a present, callable existing
|
|
369
|
+
* handler; then overwrites via `setRequestHandler`. Throws the fixed sanitized
|
|
370
|
+
* boot error (no private map contents, config, or credentials) on any mismatch.
|
|
371
|
+
*/
|
|
372
|
+
export function installToolSurfaceListOverride(protocolServer, listSchema, customHandler) {
|
|
373
|
+
let method;
|
|
374
|
+
try {
|
|
375
|
+
method = getMethodLiteral(listSchema);
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
throw new Error(COMPAT_ERROR);
|
|
379
|
+
}
|
|
380
|
+
if (method !== "tools/list") {
|
|
381
|
+
throw new Error(COMPAT_ERROR);
|
|
382
|
+
}
|
|
383
|
+
const handlers = protocolServer?._requestHandlers;
|
|
384
|
+
if (!handlers || typeof handlers.get !== "function") {
|
|
385
|
+
throw new Error(COMPAT_ERROR);
|
|
386
|
+
}
|
|
387
|
+
const original = handlers.get(method);
|
|
388
|
+
if (typeof original !== "function") {
|
|
389
|
+
throw new Error(COMPAT_ERROR);
|
|
390
|
+
}
|
|
391
|
+
// Overwrite in place. We deliberately do NOT rely on removeRequestHandler's
|
|
392
|
+
// return value and do not remove the handler first — setRequestHandler
|
|
393
|
+
// replaces the existing entry.
|
|
394
|
+
protocolServer.setRequestHandler(listSchema, customHandler);
|
|
395
|
+
return original;
|
|
396
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit manually. Regenerate with: npm run build
|
|
2
|
-
export const VERSION = "0.2.
|
|
2
|
+
export const VERSION = "0.2.26";
|
|
@@ -35,14 +35,63 @@ long-lived GitHub token.
|
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
38
|
-
## Option A —
|
|
38
|
+
## Option A — `connect-github` from your terminal (recommended)
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
If you already have a Bridge API key configured (you ran `install-bridge`), you can
|
|
41
|
+
connect GitHub without opening the Bridge web UI at all:
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
```bash
|
|
44
|
+
npx -y @bridge_gpt/mcp-server@latest connect-github --repo <repo_name>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Omit `--repo` and the command infers the project from the current directory, asking you
|
|
48
|
+
to confirm.
|
|
49
|
+
|
|
50
|
+
What happens:
|
|
51
|
+
|
|
52
|
+
1. The command opens the GitHub App install screen in your browser.
|
|
53
|
+
2. On GitHub, choose the **account or organization** that owns the repository, pick the
|
|
54
|
+
repositories under **Repository access** (see [Choosing
|
|
55
|
+
repositories](#choosing-repositories)), and click **Install**.
|
|
56
|
+
3. GitHub returns to a page that just says *"GitHub connection received — return to your
|
|
57
|
+
terminal."* That page is intentionally blank of detail; your terminal is where the
|
|
58
|
+
flow continues.
|
|
59
|
+
4. Back in the terminal, the command shows the repositories your installation covers and
|
|
60
|
+
asks which one to connect. **Every connection is confirmed by hand** — even when the
|
|
61
|
+
installation contains exactly one repository. There is no `--yes` flag.
|
|
62
|
+
5. Choose one, and it prints the connected `owner/repo`.
|
|
63
|
+
|
|
64
|
+
**You are never asked for a GitHub token, password, or installation ID.** You
|
|
65
|
+
authenticate to GitHub in your own browser; the terminal only ever carries a short-lived
|
|
66
|
+
Bridge-issued handle. Bridge never sees a GitHub credential.
|
|
67
|
+
|
|
68
|
+
**If you decline at the confirmation prompt**, nothing is connected and nothing is
|
|
69
|
+
changed — re-run the command whenever you like.
|
|
70
|
+
|
|
71
|
+
**If it times out or fails**, no connection is made. Re-run the command; the request
|
|
72
|
+
expires after about 15 minutes, so a stale attempt is never left half-applied.
|
|
73
|
+
|
|
74
|
+
### Organization approval
|
|
75
|
+
|
|
76
|
+
If an organization owns the repository and you are not an owner, GitHub sends an
|
|
77
|
+
**approval request** to an owner instead of installing the app. That approval happens
|
|
78
|
+
entirely on GitHub's side and **does not return to your terminal**, so `connect-github`
|
|
79
|
+
cannot wait for it — the original request expires. This is a real limitation, not a bug.
|
|
80
|
+
|
|
81
|
+
Once an owner has approved the install, finish the connection with
|
|
82
|
+
[Option C](#option-c--manual-install--installation-id-fallback) below.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Option B — Connect GitHub button (web UI)
|
|
87
|
+
|
|
88
|
+
Bridge captures the installation automatically — you never copy an ID by hand.
|
|
89
|
+
|
|
90
|
+
1. Open your project's **Get Started** page in the Bridge web UI. The page opens directly
|
|
91
|
+
on the GitHub connection task — connecting your repository is what the page is for.
|
|
92
|
+
2. In the **1. Connect GitHub** panel, click **Connect GitHub**. Bridge mints a
|
|
93
|
+
short-lived, single-use link scoped to your project and sends you to GitHub's
|
|
94
|
+
app-install screen.
|
|
46
95
|
3. On GitHub, choose the **account or organization** that owns the repository.
|
|
47
96
|
4. Under **Repository access**, choose **Only select repositories** and pick the repo(s)
|
|
48
97
|
you want Bridge to cover (or **All repositories**). See
|
|
@@ -54,16 +103,26 @@ an ID by hand.
|
|
|
54
103
|
installation covers exactly one repo — or one repo clearly matches your project —
|
|
55
104
|
Bridge binds it for you; otherwise it shows a short **repository picker** so you can
|
|
56
105
|
confirm which repo maps to this project.
|
|
106
|
+
7. The outcome appears in the **1. Connect GitHub** panel itself — you should see
|
|
107
|
+
**GitHub connected** naming the repository Bridge linked.
|
|
57
108
|
|
|
58
109
|
That's it — no manual ID entry. If the automatic link fails for any reason, Bridge tells
|
|
59
|
-
you and points you to Option
|
|
110
|
+
you in that same panel and points you to Option C.
|
|
111
|
+
|
|
112
|
+
Connecting an editor over MCP is **optional** and is not a prerequisite for any of the
|
|
113
|
+
above. If you need it, the Get Started page keeps that setup in a collapsed
|
|
114
|
+
**"Need to connect an editor to the MCP?"** drawer below the GitHub panel — open it only
|
|
115
|
+
if you want it.
|
|
60
116
|
|
|
61
117
|
---
|
|
62
118
|
|
|
63
|
-
## Option
|
|
119
|
+
## Option C — Manual install + Installation ID (fallback)
|
|
64
120
|
|
|
65
|
-
|
|
66
|
-
|
|
121
|
+
This is the **advanced fallback**, not the normal path — use it only if neither the
|
|
122
|
+
`connect-github` command (Option A) nor the one-click **Connect GitHub** button (Option B)
|
|
123
|
+
is available to you (for example an org admin-approval or GitHub Marketplace install), or
|
|
124
|
+
if automatic linking failed. Get Started links to it from the manual-fallback note under
|
|
125
|
+
the GitHub panel.
|
|
67
126
|
|
|
68
127
|
### 1. Install the app
|
|
69
128
|
|
|
@@ -72,7 +131,7 @@ selecting the repository/repositories you want Bridge to access:
|
|
|
72
131
|
|
|
73
132
|
<https://github.com/apps/bridge-gpt-ai-tools-for-sfcc/installations/new>
|
|
74
133
|
|
|
75
|
-
(Same repository-selection and permissions-review screen as Option
|
|
134
|
+
(Same repository-selection and permissions-review screen as Option B, steps 3–5.)
|
|
76
135
|
|
|
77
136
|
### 2. Find the Installation ID
|
|
78
137
|
|
|
@@ -99,7 +158,7 @@ settings.
|
|
|
99
158
|
|
|
100
159
|
## Choosing repositories
|
|
101
160
|
|
|
102
|
-
When installing (
|
|
161
|
+
When installing (any option), GitHub asks which repositories the app may access:
|
|
103
162
|
|
|
104
163
|
- **All repositories** — the app can access every current and future repo on the account.
|
|
105
164
|
- **Only select repositories** — pick specific repos from the **Select repositories**
|
|
@@ -139,7 +198,7 @@ After linking, confirm Bridge can act on the repo:
|
|
|
139
198
|
a VCS connection.)
|
|
140
199
|
|
|
141
200
|
If a GitHub-dependent tool refuses, the installation isn't linked to that project yet —
|
|
142
|
-
re-run Option A, or set the Installation ID via Option
|
|
201
|
+
re-run Option A, or set the Installation ID via Option C.
|
|
143
202
|
|
|
144
203
|
## Managing or removing the app
|
|
145
204
|
|
|
@@ -174,10 +233,14 @@ installation. Webhook endpoints used by the integration include the code-review
|
|
|
174
233
|
(e.g. `https://<deployment-host>/github/code-review`); configure these on the app to match
|
|
175
234
|
your deployment host.
|
|
176
235
|
|
|
177
|
-
> **Note:**
|
|
178
|
-
>
|
|
179
|
-
>
|
|
180
|
-
> `
|
|
236
|
+
> **Note:** the install URL is published from two independent places, and only one reads
|
|
237
|
+
> the environment. `GITHUB_APP_INSTALL_URL` drives the get-started **Connect GitHub**
|
|
238
|
+
> button. The setup *instructions* — the install-instructions API, the capability report's
|
|
239
|
+
> `configure_in`, and the generated README region — come from the `GITHUB_APP_INSTALL_URL`
|
|
240
|
+
> constant in `api/library/config/integration_instructions.py`, which is **not**
|
|
241
|
+
> env-overridable. Setting the env var alone will not correct the instructions. Keep the
|
|
242
|
+
> two in sync; after editing the constant, regenerate the README with
|
|
243
|
+
> `python scripts/sync_integration_readme.py`.
|
|
181
244
|
|
|
182
245
|
## See also
|
|
183
246
|
|
|
@@ -163,7 +163,7 @@ by tier.
|
|
|
163
163
|
| `generate_image` | — none beyond an image provider |
|
|
164
164
|
| `visual_diff` | — none (`LOCAL` render + pixel diff; needs a reachable `target_url`) |
|
|
165
165
|
| `request_deep_research` / `get_deep_research` | Deep-research flag **[BLOCK]** (403 if `deep_research_enabled` off) |
|
|
166
|
-
| `
|
|
166
|
+
| `request_council` / `get_council` | Code index **[BLOCK] for `technical`/`discovery` modes**; **— none for `design` mode** |
|
|
167
167
|
|
|
168
168
|
### VCS & CI
|
|
169
169
|
|
|
@@ -279,7 +279,7 @@ sandbox-only and destructive.
|
|
|
279
279
|
| **Ticket backend** (jira mode) | `create_ticket`, `get_ticket(s)`, `update_ticket_description`, `update_jira_status`, `get_jira_transitions`, and every AI generator (they read the ticket) | — |
|
|
280
280
|
| **Jira (only)** | `get_comments`, `add_comment`, `attachment`, `estimate_epic` | — |
|
|
281
281
|
| **Version control (VCS)** | `create_pull_request`, `resolve_ci_checks`, `poll_ci_checks`, `materialize_fresh_base`, `parse_repository`, `regenerate_directory_map`, `wait_for_done_gate`; **Tier-3** `request_plan_generation`/`get_plan`, `request_architecture`/`get_architecture`, `request_reimplement_context`/`get_reimplement_context`, `create_doc`(tdd/architecture) | **Tier-4** `request_clarifying_questions`, `request_ticket_critique`, `request_ticket_review`, `request_prd`, `create_doc`(prd/fsd) |
|
|
282
|
-
| **Code index** (succeeded parse) | Tier-3 plan/architecture/reimplement/`create_doc`(tdd/architecture); `
|
|
282
|
+
| **Code index** (succeeded parse) | Tier-3 plan/architecture/reimplement/`create_doc`(tdd/architecture); `request_council` in `technical`/`discovery` modes | Tier-4 clarifying-questions/critique/review/prd/fsd |
|
|
283
283
|
| **SFCC OCAPI** | `check_permissions` + all 16 SFCC read/write tools | — |
|
|
284
284
|
| **SFCC WebDAV logs** | `sfcc_log_query` | — |
|
|
285
285
|
| **Deep-research flag** | `request_deep_research`, `get_deep_research` | — |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bridge_gpt/mcp-server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.26",
|
|
4
4
|
"description": "Bridge API MCP server — exposes Jira endpoints as MCP tools for Claude Code agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"check:version-generated": "node scripts/bundle-version.js && node scripts/check-version-generated.js",
|
|
28
28
|
"postbuild": "node scripts/prepend-shebang.cjs",
|
|
29
29
|
"start": "node build/index.js",
|
|
30
|
-
"test": "node --test --test-force-exit build/pipeline-utils.test.js build/backend-warnings.test.js build/update-check.test.js build/cli-upgrade.test.js build/decision-page-schema.test.js build/decision-page-template.test.js build/bundle-pipelines.test.js build/instructions-contract.test.js build/pipeline-orchestrator-persistence.test.js build/pipeline-orchestrator-execution.test.js build/pipeline-orchestrator-integration.test.js build/index-static.test.js build/config-fields.static.test.js build/execute-plan-instructions.static.test.js build/index-resolvers.test.js build/index-project-root.test.js build/index-pipelines.test.js build/index.test.js build/bridge-config.test.js build/credential-store.test.js build/agent-config-credential-migration.test.js build/mcp-invoke.test.js build/mcp-provisioning.test.js build/mcp-server-invocation.test.js build/third-party-mcp-targets.test.js build/git-ignore-utils.test.js build/credential-materialization.test.js build/mcp-registration-doctor.test.js build/secret-safety.test.js build/base-ref.test.js build/pr-base-contract.test.js build/start-tickets.test.js build/review-tickets.test.js build/start-tickets-base-branch.test.js build/agent-registry.test.js build/agent-registry.model-routing.test.js build/start-tickets.shell-model-routing.test.js build/start-tickets.bridge-api-model-routing.test.js build/start-tickets.tier-fetch-model-routing.test.js build/start-tickets.resolve-model-routing.test.js build/start-tickets.orchestrate-model-routing.test.js build/start-tickets.routing-diagnostics.test.js build/start-tickets-repo.test.js build/start-tickets-credential-invariants.static.test.js build/credentials-cli.test.js build/start-tickets-prereqs.test.js build/regression-check.test.js build/doctor.test.js build/install-doctor.test.js build/install-bridge.test.js build/install-bridge-invite.test.js build/install-bridge-prompt.test.js build/init.test.js build/resolveUploadAttachment.test.js build/package-static.test.js build/chain-utils.test.js build/chain-orchestrator.test.js build/scheduler-backends/types.test.js build/scheduler-backends/escaping.test.js build/scheduler-backends/launchd.test.js build/scheduler-backends/task-scheduler.test.js build/scheduler-backends/systemd-user.test.js build/scheduler-backends/at-fallback.test.js build/scheduler-backends/index.test.js build/command-catalog.test.js build/scheduled-prompt.test.js build/agent-launchers/claude.test.js build/agent-launchers/cursor.test.js build/agent-launchers/index.test.js build/schedule-store.test.js build/schedule-run.test.js build/setup-epic.test.js build/agent-capabilities/cli.test.js build/agent-capabilities/runner.test.js build/agent-capabilities/probes.test.js build/agent-capabilities/probe-context.test.js build/agent-capabilities/reporter.test.js build/conductor/taxonomy-and-errors.test.js build/conductor/github-mergeability.test.js build/conductor/merge-conflict-routing.test.js build/conductor/redaction-normalization.test.js build/conductor/claude-hook.test.js build/conductor/git-ci-types.test.js build/conductor/done-gate.test.js build/conductor/git-ci-taxonomy-payload.test.js build/conductor/bridge-api-client.test.js build/conductor/plan.test.js build/conductor/producer-ledger.test.js build/conductor/spec-review-producer.test.js build/conductor/git-producer.test.js build/conductor/git-hooks.test.js build/conductor/store-migration.test.js build/conductor/pr-discovery.test.js build/conductor/pr-ci-producer.test.js build/conductor/pr-review-producer.test.js build/conductor/doctor.test.js build/conductor/deny-enforcement-preflight.test.js build/conductor/errors.test.js build/conductor/store.test.js build/conductor/index-poll-ci-producer.test.js build/start-tickets-conductor.test.js build/start-tickets-conductor.spawn.test.js build/start-tickets-conductor-node-propagation.test.js build/start-tickets.non-mutating-base.test.js build/start-tickets-live-source-guard.test.js build/conductor/worker-ledger-cli.test.js build/conductor/supervisor-config.test.js build/conductor/supervisor-ledger.test.js build/conductor/supervisor-state-reducer.test.js build/conductor/supervisor-housekeeping-projection.test.js build/conductor/supervisor-escalation.test.js build/conductor/supervisor-retired-judgment.static.test.js build/conductor/supervisor-runtime.test.js build/conductor/supervisor-store-projection.test.js build/conductor/supervisor-cli.test.js build/conductor/supervisor-start-tickets.test.js build/conductor/supervisor-message-relay.test.js build/conductor/supervisor-state-message-events.test.js build/conductor/store-message-relay.test.js build/start-tickets-message-relay.test.js build/conductor/event-accessors.test.js build/conductor/merge-ledger.test.js build/conductor/deterministic-completion.static.test.js build/conductor/deterministic-completion.integration.test.js build/conductor/local-merge.test.js build/conductor/local-merge.static.test.js build/conductor/supervisor-merge.test.js build/conductor/bridge-api-merge-client.test.js build/conductor/bridge-api-epic-client.test.js build/conductor/supervisor-merge-runtime-state.test.js build/conductor/epic-state.test.js build/executor/claude-settings.test.js build/executor/cli.test.js build/executor/credentials.test.js build/executor/echo-acceptance.test.js build/executor/env.test.js build/executor/base-branch.test.js build/executor/heartbeat.test.js build/executor/http-client.test.js build/executor/job-runner.test.js build/executor/job-runner.payload-timeout.test.js build/executor/worker-finalization.test.js build/executor/job-runner.static.test.js build/executor/prompt-spec.test.js build/executor/job-types.test.js build/executor/recovery-job.static.test.js build/executor/observation.test.js build/executor/permissions.test.js build/executor/preflight.test.js build/executor/process.test.js build/executor/results.test.js build/executor/runner.test.js build/executor/terminal-mutation.test.js build/executor/worker-command.test.js build/executor/worktree-core.test.js build/executor/worktree.test.js build/executor/job-errors.test.js build/executor/worktree-inspection.test.js build/executor/resume-pre-spawn.test.js build/executor/verdict-artifact.test.js build/executor/worker-log.test.js build/executor/job-log-registry.test.js build/executor/viewer-tabs.test.js build/executor/watch-cli.test.js build/executor/merge-job.test.js build/executor/job-runner.merge.test.js build/executor/worktree-gc.test.js build/executor/runner.job-behaviors.test.js build/conductor/cli-freeze.test.js build/conductor/epic-reconcile.test.js build/conductor/epic-runtime.test.js build/conductor/epic-tick-sequence.test.js build/conductor/epic-runtime-post-action.test.js build/conductor/file-scope-guard.test.js build/conductor/file-scope-guard.integration.test.js build/mcp-profile.test.js build/mcp-profile-registration.test.js build/tools-budget.test.js build/visual-diff-worker.test.js build/visual-diff.test.js build/estimate-epic.test.js build/integration/measure-tools.test.js build/sfcc/config.test.js build/sfcc/ocapi-shape.test.js build/sfcc/output.test.js build/sfcc/credentials.test.js build/sfcc/ocapi-write-faults.test.js build/sfcc/write-guard.test.js build/sfcc/write-grants.test.js build/sfcc/write-result.test.js build/sfcc/writes.test.js build/sfcc/writes-system-object-payloads.test.js build/sfcc/writes-payloads.test.js build/sfcc/log-gate.test.js build/sfcc/log-query.test.js && node --experimental-test-module-mocks --test --test-force-exit build/index-heavy-read-truncation.test.js build/index-artifacts.test.js build/index.review-rounds.test.js build/index-brainstorm-filenames.test.js build/index-output-path.test.js build/index-generate-decision-page.test.js build/index-generate-decision-page.integration.test.js build/visual-diff.registration.test.js build/visual-diff.attachment-adapter.test.js build/attachment-download.test.js build/attachment-upload.test.js build/conductor/paths.test.js build/conductor/store-lifecycle.test.js build/conductor/store-queries.test.js build/conductor/tools.test.js build/conductor/cli.test.js build/conductor/security-regressions.test.js build/conductor/git-inspection.test.js build/conductor/tools-done-gate.test.js build/conductor/pr-ci-producer-emit-seam.test.js build/conductor/cli-git-hooks.test.js build/sfcc/client.test.js build/sfcc/tool-wrapper.test.js build/sfcc/setup-status.test.js build/sfcc/permissions.test.js build/sfcc/register.test.js build/sfcc/reads-system-object.test.js build/sfcc/reads-custom-object-def.test.js build/sfcc/reads-site-preference.test.js build/sfcc/writes-system-object.test.js build/sfcc/writes-custom-object-def.test.js build/sfcc/writes-site-preference.test.js",
|
|
31
|
-
"test:integration": "node --test build/integration/refresh-main.integration.test.js build/integration/start-tickets.integration.test.js build/integration/doctor.integration.test.js build/integration/agent-capabilities.integration.test.js build/integration/conductor-producer.integration.test.js build/integration/conductor-message-relay.integration.test.js build/integration/executor-http-runner.integration.test.js build/integration/executor-job-behaviors.integration.test.js build/integration/executor-recovery-jobs.integration.test.js build/integration/executor-spec-review-prompt.integration.test.js build/integration/resume-pre-spawn.git.integration.test.js build/integration/worker-finalization-origin.integration.test.js build/integration/post-remediation-merge-ci-wait.integration.test.js build/integration/executor-merge-supervision.integration.test.js build/integration/attachment-binary-roundtrip.integration.test.js build/integration/dependent-ticket-fresh-base.integration.test.js build/integration/execute-plan-instructions.integration.test.js build/integration/install-bridge-repo-resolution.integration.test.js",
|
|
30
|
+
"test": "node --test --test-force-exit build/pipeline-utils.test.js build/backend-warnings.test.js build/update-check.test.js build/cli-upgrade.test.js build/decision-page-schema.test.js build/decision-page-template.test.js build/bundle-pipelines.test.js build/instructions-contract.test.js build/pipeline-orchestrator-persistence.test.js build/pipeline-orchestrator-execution.test.js build/pipeline-orchestrator-integration.test.js build/index-static.test.js build/config-fields.static.test.js build/request-brainstorm.static.test.js build/execute-plan-instructions.static.test.js build/index-resolvers.test.js build/index-project-root.test.js build/index-pipelines.test.js build/index.test.js build/bridge-config.test.js build/credential-store.test.js build/agent-config-credential-migration.test.js build/mcp-invoke.test.js build/mcp-provisioning.test.js build/mcp-server-invocation.test.js build/third-party-mcp-targets.test.js build/git-ignore-utils.test.js build/credential-materialization.test.js build/mcp-registration-doctor.test.js build/mcp-host-targets.test.js build/mcp-install-state.test.js build/mcp-host-config.test.js build/secret-safety.test.js build/base-ref.test.js build/pr-base-contract.test.js build/start-tickets.test.js build/review-tickets.test.js build/start-tickets-base-branch.test.js build/agent-registry.test.js build/agent-registry.model-routing.test.js build/start-tickets.shell-model-routing.test.js build/start-tickets.bridge-api-model-routing.test.js build/start-tickets.tier-fetch-model-routing.test.js build/start-tickets.resolve-model-routing.test.js build/start-tickets.orchestrate-model-routing.test.js build/start-tickets.routing-diagnostics.test.js build/start-tickets-repo.test.js build/start-tickets-credential-invariants.static.test.js build/credentials-cli.test.js build/start-tickets-prereqs.test.js build/regression-check.test.js build/doctor.test.js build/install-doctor.test.js build/install-bridge.test.js build/install-bridge-invite.test.js build/install-bridge-prompt.test.js build/install-bridge-tools.test.js build/init.test.js build/init-docs.test.js build/resolveUploadAttachment.test.js build/package-static.test.js build/chain-utils.test.js build/chain-orchestrator.test.js build/scheduler-backends/types.test.js build/scheduler-backends/escaping.test.js build/scheduler-backends/launchd.test.js build/scheduler-backends/task-scheduler.test.js build/scheduler-backends/systemd-user.test.js build/scheduler-backends/at-fallback.test.js build/scheduler-backends/index.test.js build/command-catalog.test.js build/scheduled-prompt.test.js build/agent-launchers/claude.test.js build/agent-launchers/cursor.test.js build/agent-launchers/index.test.js build/schedule-store.test.js build/schedule-run.test.js build/setup-epic.test.js build/conductor-bundle-artifacts.test.js build/conductor-bundle-cli.test.js build/agent-capabilities/cli.test.js build/agent-capabilities/runner.test.js build/agent-capabilities/probes.test.js build/agent-capabilities/probe-context.test.js build/agent-capabilities/reporter.test.js build/conductor/taxonomy-and-errors.test.js build/conductor/github-mergeability.test.js build/conductor/merge-conflict-routing.test.js build/conductor/redaction-normalization.test.js build/conductor/claude-hook.test.js build/conductor/git-ci-types.test.js build/conductor/done-gate.test.js build/conductor/git-ci-taxonomy-payload.test.js build/conductor/bridge-api-client.test.js build/conductor/plan.test.js build/conductor/producer-ledger.test.js build/conductor/spec-review-producer.test.js build/conductor/git-producer.test.js build/conductor/git-hooks.test.js build/conductor/store-migration.test.js build/conductor/pr-discovery.test.js build/conductor/pr-ci-producer.test.js build/conductor/pr-review-producer.test.js build/conductor/doctor.test.js build/conductor/deny-enforcement-preflight.test.js build/conductor/errors.test.js build/conductor/store.test.js build/conductor/index-poll-ci-producer.test.js build/start-tickets-conductor.test.js build/start-tickets-conductor.spawn.test.js build/start-tickets-conductor-node-propagation.test.js build/start-tickets.non-mutating-base.test.js build/start-tickets-live-source-guard.test.js build/conductor/worker-ledger-cli.test.js build/conductor/supervisor-config.test.js build/conductor/supervisor-ledger.test.js build/conductor/supervisor-state-reducer.test.js build/conductor/supervisor-housekeeping-projection.test.js build/conductor/supervisor-escalation.test.js build/conductor/supervisor-retired-judgment.static.test.js build/conductor/supervisor-runtime.test.js build/conductor/supervisor-store-projection.test.js build/conductor/supervisor-cli.test.js build/conductor/supervisor-start-tickets.test.js build/conductor/supervisor-message-relay.test.js build/conductor/supervisor-state-message-events.test.js build/conductor/store-message-relay.test.js build/start-tickets-message-relay.test.js build/conductor/event-accessors.test.js build/conductor/merge-ledger.test.js build/conductor/deterministic-completion.static.test.js build/conductor/deterministic-completion.integration.test.js build/conductor/local-merge.test.js build/conductor/local-merge.static.test.js build/conductor/supervisor-merge.test.js build/conductor/bridge-api-merge-client.test.js build/conductor/bridge-api-epic-client.test.js build/conductor/supervisor-merge-runtime-state.test.js build/conductor/epic-state.test.js build/executor/claude-settings.test.js build/executor/cli.test.js build/executor/credentials.test.js build/executor/echo-acceptance.test.js build/executor/env.test.js build/executor/base-branch.test.js build/executor/heartbeat.test.js build/executor/http-client.test.js build/executor/job-runner.test.js build/executor/job-runner.payload-timeout.test.js build/executor/worker-finalization.test.js build/executor/job-runner.static.test.js build/executor/prompt-spec.test.js build/executor/job-types.test.js build/executor/recovery-job.static.test.js build/executor/observation.test.js build/executor/permissions.test.js build/executor/preflight.test.js build/executor/process.test.js build/executor/results.test.js build/executor/runner.test.js build/executor/terminal-mutation.test.js build/executor/worker-command.test.js build/executor/worktree-core.test.js build/executor/worktree.test.js build/executor/job-errors.test.js build/executor/worktree-inspection.test.js build/executor/resume-pre-spawn.test.js build/executor/verdict-artifact.test.js build/executor/worker-log.test.js build/executor/job-log-registry.test.js build/executor/viewer-tabs.test.js build/executor/watch-cli.test.js build/executor/merge-job.test.js build/executor/job-runner.merge.test.js build/executor/worktree-gc.test.js build/executor/runner.job-behaviors.test.js build/conductor/cli-freeze.test.js build/conductor/epic-reconcile.test.js build/conductor/epic-runtime.test.js build/conductor/epic-tick-sequence.test.js build/conductor/epic-runtime-post-action.test.js build/conductor/file-scope-guard.test.js build/conductor/file-scope-guard.integration.test.js build/mcp-profile.test.js build/mcp-profile-registration.test.js build/env-flags.test.js build/bridge-api-urls.test.js build/tool-surface-gating.test.js build/tools-budget.test.js build/visual-diff-worker.test.js build/visual-diff.test.js build/estimate-epic.test.js build/integration/measure-tools.test.js build/sfcc/config.test.js build/sfcc/ocapi-shape.test.js build/sfcc/output.test.js build/sfcc/credentials.test.js build/sfcc/ocapi-write-faults.test.js build/sfcc/write-guard.test.js build/sfcc/write-grants.test.js build/sfcc/write-result.test.js build/sfcc/writes.test.js build/sfcc/writes-system-object-payloads.test.js build/sfcc/writes-payloads.test.js build/sfcc/log-gate.test.js build/sfcc/log-query.test.js && node --experimental-test-module-mocks --test --test-force-exit build/index-heavy-read-truncation.test.js build/index-artifacts.test.js build/automation-progress.test.js build/index.review-rounds.test.js build/index-brainstorm-filenames.test.js build/index-output-path.test.js build/index-generate-decision-page.test.js build/index-generate-decision-page.integration.test.js build/visual-diff.registration.test.js build/visual-diff.attachment-adapter.test.js build/attachment-download.test.js build/attachment-upload.test.js build/conductor/paths.test.js build/conductor/store-lifecycle.test.js build/conductor/store-queries.test.js build/conductor/tools.test.js build/conductor/cli.test.js build/conductor/security-regressions.test.js build/conductor/git-inspection.test.js build/conductor/tools-done-gate.test.js build/conductor/pr-ci-producer-emit-seam.test.js build/conductor/cli-git-hooks.test.js build/sfcc/client.test.js build/sfcc/tool-wrapper.test.js build/sfcc/setup-status.test.js build/sfcc/permissions.test.js build/sfcc/register.test.js build/sfcc/reads-system-object.test.js build/sfcc/reads-custom-object-def.test.js build/sfcc/reads-site-preference.test.js build/sfcc/writes-system-object.test.js build/sfcc/writes-custom-object-def.test.js build/sfcc/writes-site-preference.test.js build/connect-github.test.js",
|
|
31
|
+
"test:integration": "node --test build/integration/refresh-main.integration.test.js build/integration/start-tickets.integration.test.js build/integration/start-tickets-tier-handoff.integration.test.js build/integration/doctor.integration.test.js build/integration/agent-capabilities.integration.test.js build/integration/conductor-producer.integration.test.js build/integration/conductor-message-relay.integration.test.js build/integration/executor-http-runner.integration.test.js build/integration/executor-job-behaviors.integration.test.js build/integration/executor-recovery-jobs.integration.test.js build/integration/executor-spec-review-prompt.integration.test.js build/integration/resume-pre-spawn.git.integration.test.js build/integration/worker-finalization-origin.integration.test.js build/integration/post-remediation-merge-ci-wait.integration.test.js build/integration/executor-merge-supervision.integration.test.js build/integration/attachment-binary-roundtrip.integration.test.js build/integration/dependent-ticket-fresh-base.integration.test.js build/integration/execute-plan-instructions.integration.test.js build/integration/conductor-bundle-artifacts.integration.test.js build/integration/install-bridge-repo-resolution.integration.test.js build/integration/capability-report-contract.integration.test.js build/integration/request-brainstorm-general.integration.test.js",
|
|
32
32
|
"test:smoke": "node --test build/integration/packaged-cli-smoke.test.js",
|
|
33
33
|
"prepublishOnly": "node scripts/bundle-assets.js && npm run build && node scripts/verify-shebang.cjs"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
37
|
-
"pixelmatch": "^
|
|
37
|
+
"pixelmatch": "^7.2.0",
|
|
38
38
|
"pngjs": "^7.0.0",
|
|
39
39
|
"zod": "^4.4.3"
|
|
40
40
|
},
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@types/node": "^26.0.1",
|
|
48
48
|
"@types/pngjs": "^6.0.5",
|
|
49
49
|
"esbuild": "^0.28.1",
|
|
50
|
-
"typescript": "^
|
|
50
|
+
"typescript": "^7.0.2"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=18.0.0"
|