@bridge_gpt/mcp-server 0.2.34 → 0.2.37

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 (109) hide show
  1. package/README.md +490 -366
  2. package/build/agent-capabilities/probe-context.js +8 -1
  3. package/build/agent-capabilities/probes.js +7 -1
  4. package/build/agents.generated.js +1 -1
  5. package/build/base-url.js +79 -0
  6. package/build/bridge-api-urls.js +9 -0
  7. package/build/chain-orchestrator.js +93 -15
  8. package/build/claude-review-workflow.js +264 -0
  9. package/build/claude-user-config-doctor.js +317 -0
  10. package/build/cli-release.js +53 -0
  11. package/build/commands.generated.js +6 -5
  12. package/build/conductor/bridge-api-client.js +393 -4
  13. package/build/conductor/deny-enforcement-preflight.js +1 -0
  14. package/build/conductor/done-gate.js +44 -5
  15. package/build/conductor/epic-reconcile.js +6 -0
  16. package/build/conductor/install-doctor.js +462 -0
  17. package/build/conductor-bin.js +3 -3
  18. package/build/conductor-bundle-artifacts.js +37 -15
  19. package/build/credential-store.js +205 -4
  20. package/build/direct-ticket-tools.js +70 -0
  21. package/build/doctor.js +473 -81
  22. package/build/executor/cli.js +83 -6
  23. package/build/executor/credentials.js +39 -11
  24. package/build/executor/deps.js +32 -1
  25. package/build/executor/env.js +71 -28
  26. package/build/executor/heartbeat.js +138 -17
  27. package/build/executor/http-client.js +49 -8
  28. package/build/executor/index.js +4 -0
  29. package/build/executor/job-errors.js +4 -0
  30. package/build/executor/job-runner.js +530 -20
  31. package/build/executor/observation.js +130 -0
  32. package/build/executor/permissions.js +114 -8
  33. package/build/executor/preflight.js +127 -8
  34. package/build/executor/prompt-spec.js +51 -0
  35. package/build/executor/runner.js +23 -2
  36. package/build/executor/service-unit.js +876 -0
  37. package/build/executor/test-clock.js +75 -3
  38. package/build/executor/types.js +4 -18
  39. package/build/executor/worker-command.js +73 -12
  40. package/build/executor/worker-config-isolation.js +287 -0
  41. package/build/executor/worker-finalization.js +68 -14
  42. package/build/executor/worktree.js +46 -4
  43. package/build/index.js +1039 -237
  44. package/build/init.js +503 -111
  45. package/build/install-bridge-conductor.js +491 -0
  46. package/build/install-bridge.js +1188 -247
  47. package/build/install-reexec.js +233 -0
  48. package/build/launcher-config-inspection.js +351 -0
  49. package/build/mcp-host-config.js +11 -1
  50. package/build/mcp-install-state.js +32 -0
  51. package/build/mcp-invoke.js +49 -6
  52. package/build/mcp-provisioning.js +52 -13
  53. package/build/mcp-registration-doctor.js +14 -5
  54. package/build/notifications.js +553 -0
  55. package/build/pipeline-orchestrator.js +146 -4
  56. package/build/pipeline-utils.js +3 -0
  57. package/build/pipelines.generated.js +32 -13
  58. package/build/plan-execution-ledger.js +550 -0
  59. package/build/plan-phase-routing.js +272 -0
  60. package/build/plane/alembic-head.js +110 -0
  61. package/build/plane/build-freshness.js +167 -0
  62. package/build/plane/cli.js +480 -0
  63. package/build/plane/defaults.js +266 -0
  64. package/build/plane/manifest.js +377 -0
  65. package/build/plane/member-logs.js +147 -0
  66. package/build/plane/member-roster.js +147 -0
  67. package/build/plane/preflight.js +289 -0
  68. package/build/plane/shutdown.js +195 -0
  69. package/build/plane/status.js +125 -0
  70. package/build/plane/supervisor.js +569 -0
  71. package/build/plane/test-fakes.js +156 -0
  72. package/build/plane/types.js +75 -0
  73. package/build/readme.generated.js +1 -1
  74. package/build/run-unit-tests-launcher.js +259 -0
  75. package/build/setup-epic.js +772 -28
  76. package/build/sfcc/log-gate.js +38 -11
  77. package/build/sfcc/log-query.js +55 -15
  78. package/build/sfcc/ocapi-shape.js +51 -14
  79. package/build/sfcc/output.js +41 -11
  80. package/build/sfcc/permissions.js +24 -2
  81. package/build/sfcc/read-projection.js +181 -0
  82. package/build/sfcc/read-result.js +158 -0
  83. package/build/sfcc/reads-custom-object-def.js +29 -18
  84. package/build/sfcc/reads-site-preference.js +75 -29
  85. package/build/sfcc/reads-system-object.js +40 -34
  86. package/build/sfcc/sfcc-result.js +106 -0
  87. package/build/sfcc/tool-wrapper.js +56 -13
  88. package/build/sfcc/write-grants.js +45 -22
  89. package/build/sfcc/write-guard.js +21 -13
  90. package/build/sfcc/write-result.js +61 -14
  91. package/build/sfcc/write-tool-common.js +126 -32
  92. package/build/sfcc/writes-system-object.js +11 -50
  93. package/build/start-tickets-prereqs.js +129 -0
  94. package/build/start-tickets.js +17 -13
  95. package/build/ticket-backend-metadata.js +59 -0
  96. package/build/ticket-key-utils.js +92 -0
  97. package/build/tool-error-envelope.js +71 -0
  98. package/build/tool-surface-gating.js +72 -0
  99. package/build/update-status.js +102 -0
  100. package/build/upgrade-advice.js +47 -0
  101. package/build/upgrade-cli.js +412 -110
  102. package/build/version.generated.js +1 -1
  103. package/build/worktree-core.js +73 -0
  104. package/docs/CONDUCTOR.md +132 -6
  105. package/docs/install/mcp-tool-integrations.md +29 -21
  106. package/package.json +9 -6
  107. package/pipelines/implement-ticket.json +19 -4
  108. package/build/conductor/supervisor-judgment-python.js +0 -141
  109. package/build/conductor/supervisor-judgment.js +0 -215
@@ -0,0 +1,259 @@
1
+ /**
2
+ * BAPI-683 — bounded, cross-platform launcher for the MCP server's compiled
3
+ * `node:test` suite.
4
+ *
5
+ * The previous `scripts.test` invocation enumerated every compiled test file
6
+ * as an explicit `node --test` command-line argument. Windows' CreateProcess
7
+ * command-line length limit (~8191 chars) made that argv too long once the
8
+ * suite grew past ~200 files (`The command line is too long.`, exit 1, before
9
+ * any test ran) — Linux/macOS have a much larger limit, so the same script
10
+ * kept passing there. This module discovers compiled test files at runtime
11
+ * and spawns them in size-bounded batches instead of expanding them ahead of
12
+ * time in package.json, so no single child invocation can approach the
13
+ * Windows ceiling regardless of how many test files exist.
14
+ *
15
+ * `scripts/run-unit-tests.js` is the thin CLI entrypoint that imports this
16
+ * compiled module; the logic lives here (under src/, built by tsc) so it can
17
+ * be unit-tested with node:test like every other module in this package.
18
+ */
19
+ import { readdirSync } from "fs";
20
+ import { spawnSync } from "child_process";
21
+ import path from "path";
22
+ const DEFAULT_BUILD_DIR = "build";
23
+ // The Windows CreateProcess command-line limit is ~8191 characters. This
24
+ // budget stays well under it (accounting for execPath + node options +
25
+ // separators) so a single batch can never approach the real ceiling even on a
26
+ // longer install path. Kept OS-independent so batching is deterministic and
27
+ // stable across every CI runner and locally.
28
+ export const MAX_COMMAND_LENGTH = 6000;
29
+ // Explicit manifest: only tests that call node:test's `mock.module()` API
30
+ // need --experimental-test-module-mocks. Everything else discovered under
31
+ // build/ is eligible for the "normal" group automatically — new tests do NOT
32
+ // need to be registered anywhere else. Add an entry here only when a new test
33
+ // needs module mocking.
34
+ export const MODULE_MOCK_MANIFEST = [
35
+ "build/attachment-download.test.js",
36
+ "build/attachment-upload.test.js",
37
+ "build/automation-progress.test.js",
38
+ "build/conductor/cli-git-hooks.test.js",
39
+ "build/conductor/cli.test.js",
40
+ "build/conductor/git-inspection.test.js",
41
+ "build/conductor/paths.test.js",
42
+ "build/conductor/pr-ci-producer-emit-seam.test.js",
43
+ "build/conductor/security-regressions.test.js",
44
+ "build/conductor/store-lifecycle.test.js",
45
+ "build/conductor/store-queries.test.js",
46
+ "build/conductor/tools-done-gate.test.js",
47
+ "build/conductor/tools.test.js",
48
+ "build/connect-github-api.test.js",
49
+ "build/connect-github-dispatch.static.test.js",
50
+ "build/connect-github-handoff.test.js",
51
+ "build/connect-github.test.js",
52
+ "build/council-wait-recovery.test.js",
53
+ "build/index-artifacts.test.js",
54
+ "build/index-brainstorm-filenames.test.js",
55
+ "build/index-generate-decision-page.integration.test.js",
56
+ "build/index-generate-decision-page.test.js",
57
+ "build/index-heavy-read-truncation.test.js",
58
+ "build/index-output-path.test.js",
59
+ "build/index.review-rounds.test.js",
60
+ "build/recovery-formatting.test.js",
61
+ "build/sfcc/client.test.js",
62
+ "build/sfcc/permissions.test.js",
63
+ "build/sfcc/read-boundary.test.js",
64
+ "build/sfcc/reads-custom-object-def.test.js",
65
+ "build/sfcc/reads-site-preference.test.js",
66
+ "build/sfcc/reads-system-object.test.js",
67
+ "build/sfcc/register.test.js",
68
+ "build/sfcc/setup-status.test.js",
69
+ "build/sfcc/tool-wrapper.test.js",
70
+ "build/sfcc/write-gate-rejection.test.js",
71
+ "build/sfcc/writes-custom-object-def.test.js",
72
+ "build/sfcc/writes-site-preference.test.js",
73
+ "build/sfcc/writes-system-object.test.js",
74
+ "build/ticket-wait-recovery.test.js",
75
+ "build/visual-diff.attachment-adapter.test.js",
76
+ "build/visual-diff.registration.test.js",
77
+ "build/wait-for-result.test.js",
78
+ ];
79
+ // Files that must run as their own single-file `node --test --test-force-exit`
80
+ // invocation instead of joining a multi-file batch. --test-force-exit makes
81
+ // the runner exit before it finishes aggregating per-subprocess summaries, so
82
+ // a multi-file batch run with it reports a nondeterministic (undercounted)
83
+ // test tally — failures still surface and still set exit 1, but the count
84
+ // cannot be trusted as a completeness signal. Batched invocations therefore
85
+ // run WITHOUT the flag; only the files listed here get it, each alone, where
86
+ // the tally stays exact. build/secret-safety.test.js is quarantined because it
87
+ // leaks a handle that holds the event loop ~60s after its tests finish (they
88
+ // run in ~147ms). Do NOT add --test-force-exit to batched invocations, and do
89
+ // NOT remove a file from this quarantine, until its underlying handle leak is
90
+ // fixed.
91
+ export const FORCE_EXIT_QUARANTINE = ["build/secret-safety.test.js"];
92
+ // build/integration/** is the separately-invoked MCP_INTEGRATION=1 suite (run
93
+ // via `npm run test:integration`) plus the packaged-CLI smoke test (`npm run
94
+ // test:smoke`) — neither runs as part of `npm test`. `measure-tools.test.js`
95
+ // is the one file under that directory that has always run as part of the
96
+ // normal unit suite.
97
+ const INTEGRATION_DIR_PREFIX = "build/integration/";
98
+ const INTEGRATION_DIR_ALLOWLIST = new Set(["build/integration/measure-tools.test.js"]);
99
+ // Pre-existing compiled test files that were not wired into ANY script before
100
+ // this launcher existed (discovered while building it). BAPI-683 preserves
101
+ // the exact current running test set rather than silently picking these up —
102
+ // see docs/BAPI-683-mcp-ci-windows-npm-test-launcher.md for the follow-up.
103
+ const KNOWN_UNREGISTERED_ORPHANS = new Set([
104
+ "build/conductor/conductor-runtime.integration.test.js",
105
+ "build/sfcc/register-site-preference.integration.test.js",
106
+ ]);
107
+ /** Recursively lists compiled `*.test.js` files under `<root>/<buildDir>`, sorted and package-relative. */
108
+ export function discoverTestFiles(options) {
109
+ const { root, buildDir = DEFAULT_BUILD_DIR, fsImpl = { readdirSync } } = options;
110
+ const absoluteBuildDir = path.join(root, buildDir);
111
+ const results = [];
112
+ const walk = (dir) => {
113
+ let entries;
114
+ try {
115
+ entries = fsImpl.readdirSync(dir, { withFileTypes: true });
116
+ }
117
+ catch (err) {
118
+ if (err?.code === "ENOENT")
119
+ return;
120
+ throw err;
121
+ }
122
+ for (const entry of entries) {
123
+ const full = path.join(dir, entry.name);
124
+ if (entry.isDirectory()) {
125
+ walk(full);
126
+ }
127
+ else if (entry.name.endsWith(".test.js")) {
128
+ results.push(path.relative(root, full).split(path.sep).join("/"));
129
+ }
130
+ }
131
+ };
132
+ walk(absoluteBuildDir);
133
+ results.sort();
134
+ return results;
135
+ }
136
+ /** Throws if the module-mock or force-exit-quarantine manifest has drifted from the discovered build output. */
137
+ export function validateManifest(discovered) {
138
+ const discoveredSet = new Set(discovered);
139
+ const seen = new Set();
140
+ for (const entry of MODULE_MOCK_MANIFEST) {
141
+ if (seen.has(entry)) {
142
+ throw new Error(`run-unit-tests: duplicate module-mock manifest entry: ${entry}`);
143
+ }
144
+ seen.add(entry);
145
+ if (!discoveredSet.has(entry)) {
146
+ throw new Error(`run-unit-tests: module-mock manifest entry not found in build output: ${entry} ` +
147
+ `(rebuild with 'npm run build', or remove it from MODULE_MOCK_MANIFEST if the file was deleted/renamed)`);
148
+ }
149
+ }
150
+ for (const entry of FORCE_EXIT_QUARANTINE) {
151
+ if (seen.has(entry)) {
152
+ throw new Error(`run-unit-tests: quarantine entry duplicated or also present in the module-mock manifest: ${entry}`);
153
+ }
154
+ seen.add(entry);
155
+ if (!discoveredSet.has(entry)) {
156
+ throw new Error(`run-unit-tests: force-exit quarantine entry not found in build output: ${entry} ` +
157
+ `(rebuild with 'npm run build', or remove it from FORCE_EXIT_QUARANTINE if the file was deleted/renamed)`);
158
+ }
159
+ }
160
+ }
161
+ /** Selects and validates the requested group's file list from the discovered inventory. */
162
+ export function selectTestGroup(mode, discovered) {
163
+ if (mode !== "normal" && mode !== "module-mocks") {
164
+ throw new Error(`run-unit-tests: unknown group "${mode}" (expected "normal" or "module-mocks")`);
165
+ }
166
+ validateManifest(discovered);
167
+ const moduleMockSet = new Set(MODULE_MOCK_MANIFEST);
168
+ const normal = discovered.filter((file) => {
169
+ if (moduleMockSet.has(file))
170
+ return false;
171
+ if (file.startsWith(INTEGRATION_DIR_PREFIX) && !INTEGRATION_DIR_ALLOWLIST.has(file))
172
+ return false;
173
+ if (KNOWN_UNREGISTERED_ORPHANS.has(file))
174
+ return false;
175
+ return true;
176
+ });
177
+ const overlap = normal.filter((file) => moduleMockSet.has(file));
178
+ if (overlap.length > 0) {
179
+ throw new Error(`run-unit-tests: file(s) present in both normal and module-mock groups: ${overlap.join(", ")}`);
180
+ }
181
+ const selected = mode === "normal" ? normal : [...MODULE_MOCK_MANIFEST];
182
+ if (selected.length === 0) {
183
+ throw new Error(`run-unit-tests: selected group "${mode}" is empty — refusing to run zero tests`);
184
+ }
185
+ return selected;
186
+ }
187
+ /**
188
+ * Greedily packs sorted file paths into batches whose serialized
189
+ * `execPath ...nodeOptions ...files` command length stays within `maxLength`.
190
+ * A single file that cannot fit even alone is rejected rather than spawned.
191
+ */
192
+ export function partitionTestBatches(files, options = {}) {
193
+ const { execPath = process.execPath, nodeOptions = [], maxLength = MAX_COMMAND_LENGTH } = options;
194
+ const prefixLength = [execPath, ...nodeOptions].join(" ").length;
195
+ const batches = [];
196
+ let current = [];
197
+ let currentLength = prefixLength;
198
+ for (const file of files) {
199
+ const addition = 1 + file.length; // separating space + path
200
+ if (prefixLength + addition > maxLength) {
201
+ throw new Error(`run-unit-tests: "${file}" alone exceeds the command-length budget ` +
202
+ `(${prefixLength + addition} > ${maxLength} chars) — cannot batch it safely`);
203
+ }
204
+ if (current.length > 0 && currentLength + addition > maxLength) {
205
+ batches.push(current);
206
+ current = [];
207
+ currentLength = prefixLength;
208
+ }
209
+ current.push(file);
210
+ currentLength += addition;
211
+ }
212
+ if (current.length > 0) {
213
+ batches.push(current);
214
+ }
215
+ return batches;
216
+ }
217
+ /** Discovers, selects, batches, and spawns the requested test group; returns an aggregate exit code. */
218
+ export function runSelectedGroup(mode, options) {
219
+ // Validate the mode before touching the filesystem or spawning anything —
220
+ // an unknown group must fail fast with no discovery/spawn side effects.
221
+ if (mode !== "normal" && mode !== "module-mocks") {
222
+ throw new Error(`run-unit-tests: unknown group "${mode}" (expected "normal" or "module-mocks")`);
223
+ }
224
+ const { root, execPath = process.execPath, spawnFn = spawnSync, discoverFn = (opts) => discoverTestFiles(opts), log = console.log, } = options;
225
+ const discovered = discoverFn({ root });
226
+ const selected = selectTestGroup(mode, discovered);
227
+ // Split out the force-exit quarantine: those files run last, each as its own
228
+ // single-file spawn WITH --test-force-exit (exact tally, prompt exit despite
229
+ // the leaked handle). Every batched spawn runs WITHOUT the flag so its test
230
+ // tally stays deterministic — see FORCE_EXIT_QUARANTINE above.
231
+ const quarantineSet = new Set(FORCE_EXIT_QUARANTINE);
232
+ const batchable = selected.filter((file) => !quarantineSet.has(file));
233
+ const quarantined = selected.filter((file) => quarantineSet.has(file));
234
+ const extraFlags = mode === "module-mocks" ? ["--experimental-test-module-mocks"] : [];
235
+ const nodeOptions = [...extraFlags, "--test"];
236
+ const batches = partitionTestBatches(batchable, { execPath, nodeOptions });
237
+ log(`run-unit-tests: group="${mode}" files=${selected.length} batches=${batches.length}` +
238
+ (quarantined.length > 0 ? ` quarantined=${quarantined.length}` : ""));
239
+ let aggregateExit = 0;
240
+ const spawn = (args) => {
241
+ const result = spawnFn(execPath, args, {
242
+ cwd: root,
243
+ stdio: "inherit",
244
+ shell: false,
245
+ });
246
+ if ((result.status ?? 1) !== 0) {
247
+ aggregateExit = 1;
248
+ }
249
+ };
250
+ batches.forEach((batch, index) => {
251
+ log(`run-unit-tests: batch ${index + 1}/${batches.length} (${batch.length} file(s))`);
252
+ spawn([...nodeOptions, ...batch]);
253
+ });
254
+ quarantined.forEach((file, index) => {
255
+ log(`run-unit-tests: quarantined ${index + 1}/${quarantined.length} ${file} (single-file, --test-force-exit)`);
256
+ spawn([...nodeOptions, "--test-force-exit", file]);
257
+ });
258
+ return aggregateExit;
259
+ }