@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.
Files changed (36) hide show
  1. package/README.md +98 -28
  2. package/build/agents.generated.js +1 -1
  3. package/build/bridge-api-urls.js +31 -0
  4. package/build/commands.generated.js +5 -5
  5. package/build/conductor/epic-reconcile.js +7 -1
  6. package/build/conductor/epic-runtime.js +5 -0
  7. package/build/conductor-bundle-artifacts.js +802 -0
  8. package/build/conductor-bundle-cli.js +256 -0
  9. package/build/connect-github-api.js +365 -0
  10. package/build/connect-github.js +415 -0
  11. package/build/decision-page-schema.js +34 -5
  12. package/build/decision-page-template.js +117 -35
  13. package/build/docs.generated.js +2 -1
  14. package/build/doctor.js +148 -1
  15. package/build/env-flags.js +31 -0
  16. package/build/index.js +3467 -498
  17. package/build/init.js +7 -3
  18. package/build/install-bridge.js +624 -38
  19. package/build/install-doctor.js +64 -0
  20. package/build/mcp-host-config.js +521 -0
  21. package/build/mcp-host-targets.js +194 -0
  22. package/build/mcp-install-state.js +175 -0
  23. package/build/pipelines.generated.js +127 -132
  24. package/build/readme.generated.js +1 -1
  25. package/build/start-tickets.js +166 -18
  26. package/build/tool-surface-gating.js +396 -0
  27. package/build/version.generated.js +1 -1
  28. package/docs/install/github-app.md +80 -17
  29. package/docs/install/mcp-tool-integrations.md +2 -2
  30. package/package.json +5 -5
  31. package/pipelines/learn-repository.json +111 -119
  32. package/public/css/main.min.css +258 -65
  33. package/public/css/main.min.css.map +1 -1
  34. package/public/js/main.min.js +188 -92
  35. package/public/js/main.min.js.map +1 -1
  36. 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.24";
2
+ export const VERSION = "0.2.26";
@@ -35,14 +35,63 @@ long-lived GitHub token.
35
35
 
36
36
  ---
37
37
 
38
- ## Option A — Connect GitHub button (recommended)
38
+ ## Option A — `connect-github` from your terminal (recommended)
39
39
 
40
- This is the normal path. Bridge captures the installation automatically you never copy
41
- an ID by hand.
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
- 1. Open your project's **Get Started** page in the Bridge web UI.
44
- 2. Click **Connect GitHub**. Bridge mints a short-lived, single-use link scoped to your
45
- project and sends you to GitHub's app-install screen.
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 B.
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 B — Manual install + Installation ID (fallback)
119
+ ## Option C — Manual install + Installation ID (fallback)
64
120
 
65
- Use this if the Connect GitHub button isn't available to you, or automatic linking
66
- failed.
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 A, steps 3–5.)
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 (either option), GitHub asks which repositories the app may access:
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 B.
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:** an older placeholder app slug (`bridge-gpt-code-reviewer`) still appears as a
178
- > stale default string in the codebase. The runtime install URL and App ID always come
179
- > from `GITHUB_APP_INSTALL_URL` / `GIT_APP_ID`, so set those to the `954077` /
180
- > `bridge-gpt-ai-tools-for-sfcc` values above rather than relying on the code default.
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
- | `request_brainstorm` / `get_brainstorm` | Code index **[BLOCK] for `technical`/`discovery` modes**; **— none for `design` mode** |
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); `request_brainstorm` in `technical`/`discovery` modes | Tier-4 clarifying-questions/critique/review/prd/fsd |
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.24",
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": "^6.0.0",
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": "^6.0.3"
50
+ "typescript": "^7.0.2"
51
51
  },
52
52
  "engines": {
53
53
  "node": ">=18.0.0"