@bridge_gpt/mcp-server 0.2.41 → 0.2.43
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 +330 -191
- package/build/agent-capabilities/cli.js +2 -1
- package/build/agent-launchers/claude-executor-adapter.js +17 -4
- package/build/agents.generated.js +2 -2
- package/build/claude-review-workflow.js +510 -45
- package/build/claude-user-config-doctor.js +42 -11
- package/build/cli-release.js +2 -1
- package/build/commands.generated.js +6 -5
- package/build/conduct-epic/bridge-client.js +354 -113
- package/build/conduct-epic/checkpoint-store.js +17 -0
- package/build/conduct-epic/cli.js +947 -99
- package/build/conduct-epic/cut-protocol.js +327 -0
- package/build/conduct-epic/spawn.js +14 -2
- package/build/conductor/bridge-api-client.js +148 -1
- package/build/conductor/cli.js +109 -1
- package/build/conductor/doctor.js +101 -16
- package/build/conductor/epic-reconcile.js +72 -19
- package/build/conductor/epic-runtime.js +15 -3
- package/build/conductor/errors.js +47 -0
- package/build/conductor/git-hooks.js +205 -11
- package/build/conductor/install-doctor.js +230 -1
- package/build/conductor/local-merge.js +130 -28
- package/build/conductor/recovery-cli.js +313 -0
- package/build/conductor/recovery-operations.js +219 -0
- package/build/conductor/tools.js +32 -3
- package/build/conductor/worker-ledger-cli.js +27 -1
- package/build/conductor-bin.js +20 -16
- package/build/credentials-cli.js +3 -2
- package/build/docs.generated.js +2 -1
- package/build/doctor.js +120 -44
- package/build/drive-epic.js +375 -0
- package/build/executor/cli.js +48 -1
- package/build/executor/env.js +21 -0
- package/build/executor/http-client.js +71 -3
- package/build/executor/index-scope.js +39 -0
- package/build/executor/job-errors.js +9 -0
- package/build/executor/job-log-registry.js +69 -0
- package/build/executor/job-runner.js +198 -29
- package/build/executor/live-worker-registry.js +83 -0
- package/build/executor/observation.js +259 -6
- package/build/executor/platform.js +147 -3
- package/build/executor/process.js +58 -14
- package/build/executor/runner.js +454 -48
- package/build/executor/test-clock.js +3 -2
- package/build/executor/worker-finalization.js +233 -56
- package/build/executor/worktree.js +8 -1
- package/build/index-scope-contract.js +96 -0
- package/build/index.js +2277 -270
- package/build/init.js +83 -22
- package/build/install-bridge-conductor.js +323 -14
- package/build/install-bridge.js +225 -47
- package/build/install-doctor.js +23 -9
- package/build/install-reexec.js +2 -1
- package/build/launcher-config-inspection.js +83 -22
- package/build/mcp-host-config.js +331 -67
- package/build/mcp-host-targets.js +45 -21
- package/build/mcp-identity.js +92 -0
- package/build/mcp-install-state.js +94 -1
- package/build/mcp-invoke.js +2 -1
- package/build/mcp-provisioning.js +45 -12
- package/build/mcp-registration-doctor.js +35 -13
- package/build/mcp-server-invocation.js +4 -2
- package/build/merge-pull-request.js +208 -9
- package/build/pipelines.generated.js +305 -15
- package/build/plane/cli.js +73 -7
- package/build/plane/defaults.js +18 -5
- package/build/plane/manifest.js +90 -0
- package/build/plane/preflight.js +100 -10
- package/build/plane/shutdown.js +71 -3
- package/build/plane/test-fakes.js +9 -1
- package/build/readme.generated.js +1 -1
- package/build/regression-check.js +3 -2
- package/build/review-tickets.js +8 -7
- package/build/run-unit-tests-launcher.js +149 -6
- package/build/schedule-run.js +3 -2
- package/build/setup-epic.js +531 -82
- package/build/sfcc/tool-wrapper.js +15 -0
- package/build/start-tickets-prereqs.js +11 -6
- package/build/start-tickets.js +91 -85
- package/build/update-check.js +3 -2
- package/build/upgrade-advice.js +2 -1
- package/build/upgrade-cli.js +50 -18
- package/build/version.generated.js +2 -1
- package/build/worktree-core.js +31 -17
- package/docs/CONDUCTOR.md +22 -0
- package/docs/install/mcp-tool-integrations.md +19 -3
- package/package.json +2 -2
- package/pipelines/greenfield-setup.json +286 -0
|
@@ -20,6 +20,20 @@ import { readdirSync } from "fs";
|
|
|
20
20
|
import { spawnSync } from "child_process";
|
|
21
21
|
import path from "path";
|
|
22
22
|
const DEFAULT_BUILD_DIR = "build";
|
|
23
|
+
// BAPI-877 — the SECOND directory the unit lane discovers. `mcp_server/scripts/`
|
|
24
|
+
// holds hand-authored ESM (`"type": "module"`) that the build itself runs:
|
|
25
|
+
// bundle-version.js, sync-agent-mirrors.js, and friends. They are NOT tsc inputs
|
|
26
|
+
// (tsconfig.json is rootDir "src" / include "src/**/*.ts"), so they compile to
|
|
27
|
+
// nothing and a `*.test.js` beside them has no build/ counterpart to discover.
|
|
28
|
+
// Before this constant existed, such a file ran in NO lane at all: not `npm
|
|
29
|
+
// test` (which walked build/ only), not the integration lane, not the pre-push
|
|
30
|
+
// gate. sync-agent-mirrors.test.js sat unrun for months that way.
|
|
31
|
+
//
|
|
32
|
+
// Discovered from source rather than from build/ for that reason, and unioned
|
|
33
|
+
// into the "normal" group — a `scripts/…` path can never match the
|
|
34
|
+
// build/integration/ prefix, so it needs no filter change to land there.
|
|
35
|
+
const SCRIPT_TEST_DIR = "scripts";
|
|
36
|
+
export const SCRIPTS_DIR_PREFIX = "scripts/";
|
|
23
37
|
// The Windows CreateProcess command-line limit is ~8191 characters. This
|
|
24
38
|
// budget stays well under it (accounting for execPath + node options +
|
|
25
39
|
// separators) so a single batch can never approach the real ceiling even on a
|
|
@@ -28,9 +42,9 @@ const DEFAULT_BUILD_DIR = "build";
|
|
|
28
42
|
export const MAX_COMMAND_LENGTH = 6000;
|
|
29
43
|
// Explicit manifest: only tests that call node:test's `mock.module()` API
|
|
30
44
|
// need --experimental-test-module-mocks. Everything else discovered under
|
|
31
|
-
// build/ is eligible for the "normal" group automatically — new
|
|
32
|
-
// need to be registered anywhere else. Add an entry here only when
|
|
33
|
-
// needs module mocking.
|
|
45
|
+
// build/ OR scripts/ is eligible for the "normal" group automatically — new
|
|
46
|
+
// tests do NOT need to be registered anywhere else. Add an entry here only when
|
|
47
|
+
// a new test needs module mocking.
|
|
34
48
|
export const MODULE_MOCK_MANIFEST = [
|
|
35
49
|
"build/attachment-download.test.js",
|
|
36
50
|
"build/attachment-upload.test.js",
|
|
@@ -40,6 +54,8 @@ export const MODULE_MOCK_MANIFEST = [
|
|
|
40
54
|
"build/conductor/git-inspection.test.js",
|
|
41
55
|
"build/conductor/paths.test.js",
|
|
42
56
|
"build/conductor/pr-ci-producer-emit-seam.test.js",
|
|
57
|
+
"build/conductor/recovery-cli.test.js",
|
|
58
|
+
"build/conductor/recovery-operations.test.js",
|
|
43
59
|
"build/conductor/security-regressions.test.js",
|
|
44
60
|
"build/conductor/store-lifecycle.test.js",
|
|
45
61
|
"build/conductor/store-queries.test.js",
|
|
@@ -57,6 +73,7 @@ export const MODULE_MOCK_MANIFEST = [
|
|
|
57
73
|
"build/index-heavy-read-truncation.test.js",
|
|
58
74
|
"build/index-output-path.test.js",
|
|
59
75
|
"build/index.review-rounds.test.js",
|
|
76
|
+
"build/plane/cli.test.js",
|
|
60
77
|
"build/recovery-formatting.test.js",
|
|
61
78
|
"build/sfcc/client.test.js",
|
|
62
79
|
"build/sfcc/permissions.test.js",
|
|
@@ -95,8 +112,24 @@ export const FORCE_EXIT_QUARANTINE = ["build/secret-safety.test.js"];
|
|
|
95
112
|
// test:smoke`) — neither runs as part of `npm test`. `measure-tools.test.js`
|
|
96
113
|
// is the one file under that directory that has always run as part of the
|
|
97
114
|
// normal unit suite.
|
|
98
|
-
const INTEGRATION_DIR_PREFIX = "build/integration/";
|
|
115
|
+
export const INTEGRATION_DIR_PREFIX = "build/integration/";
|
|
99
116
|
const INTEGRATION_DIR_ALLOWLIST = new Set(["build/integration/measure-tools.test.js"]);
|
|
117
|
+
// BAPI-848 — files under build/integration/ that belong to a DIFFERENT lane and
|
|
118
|
+
// must therefore be excluded from integration discovery:
|
|
119
|
+
//
|
|
120
|
+
// * measure-tools.test.js runs in the normal unit lane (allowlisted above)
|
|
121
|
+
// * packaged-cli-smoke.test.js runs in `npm run test:smoke`
|
|
122
|
+
//
|
|
123
|
+
// This set is the entire registration surface for the integration lane. Adding a
|
|
124
|
+
// new build/integration/*.test.js requires editing NOTHING — which is the point:
|
|
125
|
+
// the old scripts.test:integration named every file explicitly on one line, so
|
|
126
|
+
// every ticket adding an integration test had to edit a line shared with every
|
|
127
|
+
// other integration test, and a file whose name was forgotten ran in no lane at
|
|
128
|
+
// all.
|
|
129
|
+
export const INTEGRATION_DISCOVERY_EXCLUSIONS = [
|
|
130
|
+
"build/integration/measure-tools.test.js",
|
|
131
|
+
"build/integration/packaged-cli-smoke.test.js",
|
|
132
|
+
];
|
|
100
133
|
// Compiled test files that live OUTSIDE build/integration/ but still belong to
|
|
101
134
|
// the separately-invoked `npm run test:integration` lane, so the unit lane must
|
|
102
135
|
// skip them. BAPI-683 originally introduced this set as
|
|
@@ -112,6 +145,10 @@ const INTEGRATION_DIR_ALLOWLIST = new Set(["build/integration/measure-tools.test
|
|
|
112
145
|
// discovered into the unit lane automatically and needs no registration —
|
|
113
146
|
// tests/pytest/mcp/test_mcp_server_test_registration_multicomponent.py fails if
|
|
114
147
|
// a *.integration.test.ts ends up in neither lane.
|
|
148
|
+
//
|
|
149
|
+
// BAPI-877 — a `scripts/…` path must NEVER be listed here. This is not a style
|
|
150
|
+
// rule: `discoverIntegrationTestFiles` walks build/ only, so the entry would fail
|
|
151
|
+
// its own presence check below and throw on EVERY `npm run test:integration` run.
|
|
115
152
|
export const INTEGRATION_LANE_ONLY = [
|
|
116
153
|
"build/conductor/conductor-runtime.integration.test.js",
|
|
117
154
|
];
|
|
@@ -144,6 +181,55 @@ export function discoverTestFiles(options) {
|
|
|
144
181
|
results.sort();
|
|
145
182
|
return results;
|
|
146
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* BAPI-877 — hand-authored `scripts/*.test.js`, sorted and package-relative.
|
|
186
|
+
*
|
|
187
|
+
* A thin delegation rather than a second walker: `buildDir` already generalizes
|
|
188
|
+
* (the walk is directory-agnostic and `path.relative(root, …)` yields
|
|
189
|
+
* `scripts/x.test.js` for free), and duplicating the ENOENT swallow, the sort,
|
|
190
|
+
* and the separator normalization would be three chances to diverge.
|
|
191
|
+
*
|
|
192
|
+
* Deliberately does NOT apply the empty-discovery guard — `discoverUnitTestFiles`
|
|
193
|
+
* owns that, so this stays a pure query usable in isolation.
|
|
194
|
+
*/
|
|
195
|
+
export function discoverScriptTestFiles(options) {
|
|
196
|
+
return discoverTestFiles({ ...options, buildDir: SCRIPT_TEST_DIR });
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* BAPI-877 — everything the unit lane runs: compiled `build/**` plus authored
|
|
200
|
+
* `scripts/**`.
|
|
201
|
+
*
|
|
202
|
+
* WHY THE EMPTY-SCRIPTS GUARD IS SEPARATE. `selectTestGroup`'s "selected group
|
|
203
|
+
* is empty" refusal cannot fire for this: ~390 compiled files are always
|
|
204
|
+
* present, so a scripts-discovery regression would be masked and the lane would
|
|
205
|
+
* report green over zero scripts tests — the exact "coverage that exists only if
|
|
206
|
+
* someone runs it by hand" failure BAPI-877 exists to remove. Refusing here
|
|
207
|
+
* matches `runIntegrationLane` and `discoverIntegrationTestFiles`, which take the
|
|
208
|
+
* same posture for the same reason.
|
|
209
|
+
*
|
|
210
|
+
* The cost is deliberate: deleting every `scripts/*.test.js` breaks `npm test`
|
|
211
|
+
* until someone edits this file. Deleting all coverage for the build's version
|
|
212
|
+
* generator and agent-mirror synchronizer SHOULD require touching the line that
|
|
213
|
+
* says so, rather than silently shrinking the suite.
|
|
214
|
+
*
|
|
215
|
+
* WHY IT LIVES HERE and not in `runSelectedGroup`: the guard belongs on the
|
|
216
|
+
* production path only. Every test that injects its own `discoverFn` supplies a
|
|
217
|
+
* build-only fixture tree, and firing there would force `scripts/*` entries into
|
|
218
|
+
* BASELINE_NORMAL_FILES — falsifying the independent historical oracle this
|
|
219
|
+
* suite is built on.
|
|
220
|
+
*/
|
|
221
|
+
export function discoverUnitTestFiles(options) {
|
|
222
|
+
const compiled = discoverTestFiles(options);
|
|
223
|
+
const authored = discoverScriptTestFiles(options);
|
|
224
|
+
if (authored.length === 0) {
|
|
225
|
+
throw new Error(`run-unit-tests: discovered zero ${SCRIPTS_DIR_PREFIX}*.test.js under ` +
|
|
226
|
+
`"${options.root}" — refusing to run. A scripts-lane discovery regression is ` +
|
|
227
|
+
`invisible beside the compiled tests that still ran, which is the failure ` +
|
|
228
|
+
`this lane exists to prevent (BAPI-877). If ${SCRIPTS_DIR_PREFIX} genuinely ` +
|
|
229
|
+
`has no test file any more, remove this guard deliberately.`);
|
|
230
|
+
}
|
|
231
|
+
return [...compiled, ...authored].sort();
|
|
232
|
+
}
|
|
147
233
|
/** Throws if the module-mock, force-exit-quarantine, or integration-lane manifest has drifted from the discovered build output. */
|
|
148
234
|
export function validateManifest(discovered) {
|
|
149
235
|
const discoveredSet = new Set(discovered);
|
|
@@ -248,8 +334,8 @@ export function runSelectedGroup(mode, options) {
|
|
|
248
334
|
if (mode !== "normal" && mode !== "module-mocks") {
|
|
249
335
|
throw new Error(`run-unit-tests: unknown group "${mode}" (expected "normal" or "module-mocks")`);
|
|
250
336
|
}
|
|
251
|
-
const { root, execPath = process.execPath, spawnFn = spawnSync, discoverFn = (opts) =>
|
|
252
|
-
const discovered = discoverFn({ root });
|
|
337
|
+
const { root, execPath = process.execPath, spawnFn = spawnSync, discoverFn = (opts) => discoverUnitTestFiles(opts), fsImpl, log = console.log, } = options;
|
|
338
|
+
const discovered = discoverFn({ root, fsImpl });
|
|
253
339
|
const selected = selectTestGroup(mode, discovered);
|
|
254
340
|
// Split out the force-exit quarantine: those files run last, each as its own
|
|
255
341
|
// single-file spawn WITH --test-force-exit (exact tally, prompt exit despite
|
|
@@ -284,3 +370,60 @@ export function runSelectedGroup(mode, options) {
|
|
|
284
370
|
});
|
|
285
371
|
return aggregateExit;
|
|
286
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Returns the integration lane's file list: every compiled `*.test.js` under
|
|
375
|
+
* `build/integration/` except the files belonging to another lane, plus the
|
|
376
|
+
* explicitly-registered files that live outside that directory
|
|
377
|
+
* (:data:`INTEGRATION_LANE_ONLY`). Sorted and package-relative.
|
|
378
|
+
*
|
|
379
|
+
* BAPI-848. Discovery replaced a hand-maintained enumeration in
|
|
380
|
+
* `scripts.test:integration`. A directory glob in the npm script itself was NOT
|
|
381
|
+
* viable: the MCP suite runs on Windows in CI, where npm runs scripts through
|
|
382
|
+
* cmd.exe and `*` is never expanded, so the script would have been silently
|
|
383
|
+
* handed a literal path and run zero tests.
|
|
384
|
+
*/
|
|
385
|
+
export function discoverIntegrationTestFiles(options) {
|
|
386
|
+
const discovered = discoverTestFiles(options);
|
|
387
|
+
const excluded = new Set(INTEGRATION_DISCOVERY_EXCLUSIONS);
|
|
388
|
+
const fromDirectory = discovered.filter((file) => file.startsWith(INTEGRATION_DIR_PREFIX) && !excluded.has(file));
|
|
389
|
+
// The outside-directory entries stay explicit and are VALIDATED against the
|
|
390
|
+
// build output, so a renamed or deleted file fails loudly instead of silently
|
|
391
|
+
// dropping out of every lane.
|
|
392
|
+
const discoveredSet = new Set(discovered);
|
|
393
|
+
for (const entry of INTEGRATION_LANE_ONLY) {
|
|
394
|
+
if (!discoveredSet.has(entry)) {
|
|
395
|
+
throw new Error(`run-integration-tests: integration-lane entry not found in build output: ${entry} ` +
|
|
396
|
+
`(rebuild with 'npm run build', or remove it from INTEGRATION_LANE_ONLY if the file was deleted/renamed)`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
const selected = [...new Set([...fromDirectory, ...INTEGRATION_LANE_ONLY])];
|
|
400
|
+
selected.sort();
|
|
401
|
+
return selected;
|
|
402
|
+
}
|
|
403
|
+
/** Discovers, batches, and spawns the integration lane; returns an aggregate exit code. */
|
|
404
|
+
export function runIntegrationLane(options) {
|
|
405
|
+
const { root, execPath = process.execPath, spawnFn = spawnSync, discoverFn = (opts) => discoverIntegrationTestFiles(opts), log = console.log, } = options;
|
|
406
|
+
const selected = discoverFn({ root });
|
|
407
|
+
if (selected.length === 0) {
|
|
408
|
+
// Refusing beats reporting a green run over zero files — a discovery bug
|
|
409
|
+
// that silently selected nothing would look exactly like a passing suite.
|
|
410
|
+
throw new Error("run-integration-tests: discovered zero integration tests — refusing to run " +
|
|
411
|
+
"(did you forget 'npm run build'?)");
|
|
412
|
+
}
|
|
413
|
+
const nodeOptions = ["--test"];
|
|
414
|
+
const batches = partitionTestBatches(selected, { execPath, nodeOptions });
|
|
415
|
+
log(`run-integration-tests: files=${selected.length} batches=${batches.length}`);
|
|
416
|
+
let aggregateExit = 0;
|
|
417
|
+
batches.forEach((batch, index) => {
|
|
418
|
+
log(`run-integration-tests: batch ${index + 1}/${batches.length} (${batch.length} file(s))`);
|
|
419
|
+
const result = spawnFn(execPath, [...nodeOptions, ...batch], {
|
|
420
|
+
cwd: root,
|
|
421
|
+
stdio: "inherit",
|
|
422
|
+
shell: false,
|
|
423
|
+
});
|
|
424
|
+
if ((result.status ?? 1) !== 0) {
|
|
425
|
+
aggregateExit = 1;
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
return aggregateExit;
|
|
429
|
+
}
|
package/build/schedule-run.js
CHANGED
|
@@ -23,6 +23,7 @@ import { getAgentLauncher, formatValidAgentLauncherNames } from "./agent-launche
|
|
|
23
23
|
import { resolveCommandOnPath } from "./agent-launchers/claude.js";
|
|
24
24
|
import { discoverCommandCatalog, resolveSchedulableCommand, validateCommandArgv, } from "./command-catalog.js";
|
|
25
25
|
import { buildTargetCommandLine } from "./scheduled-prompt.js";
|
|
26
|
+
import { MCP_PACKAGE_NAME } from "./mcp-identity.js";
|
|
26
27
|
/**
|
|
27
28
|
* Default deps backed by real subprocesses / process state. Subprocess execution
|
|
28
29
|
* uses `execFile` (list-based, never `shell: true`) and supports
|
|
@@ -96,7 +97,7 @@ const SCHEDULE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
|
|
|
96
97
|
export function getScheduleRunUsage() {
|
|
97
98
|
return [
|
|
98
99
|
"Usage:",
|
|
99
|
-
|
|
100
|
+
` npx -y ${MCP_PACKAGE_NAME} schedule-run <create|list|cancel|doctor> [flags]`,
|
|
100
101
|
"",
|
|
101
102
|
"Schedules a local, one-shot run of ANY Bridge slash-command automation (from",
|
|
102
103
|
"the repo's .claude/commands/*.md catalog) at a chosen time using an OS-native",
|
|
@@ -659,7 +660,7 @@ export async function resolveScheduleCreateInput(options, runAtIso, deps) {
|
|
|
659
660
|
if (isTransientNpxEntryPath(cliEntryPath)) {
|
|
660
661
|
warnings.push(`The scheduled run re-enters this CLI at '${cliEntryPath}', which is inside an npx cache ` +
|
|
661
662
|
"directory. npx caches can be pruned before a future schedule fires, which would make the " +
|
|
662
|
-
|
|
663
|
+
`run fail with ENOENT. Install the CLI persistently (e.g. \`npm i -g ${MCP_PACKAGE_NAME}\`) ` +
|
|
663
664
|
"and schedule with the installed binary so the trigger path stays stable.");
|
|
664
665
|
}
|
|
665
666
|
const paths = getSchedulePaths(id, deps.homeDir, deps.platform);
|