@bridge_gpt/mcp-server 0.2.38 → 0.2.39

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 (85) hide show
  1. package/README.md +189 -14
  2. package/build/agent-capabilities/probe-context.js +2 -1
  3. package/build/agent-launchers/claude-executor-adapter.js +392 -0
  4. package/build/agent-launchers/executor-adapter-inspection.js +163 -0
  5. package/build/agent-launchers/executor-adapter-registry.js +90 -0
  6. package/build/agent-launchers/executor-adapter.js +136 -0
  7. package/build/agent-registry.js +28 -0
  8. package/build/agents.generated.js +1 -1
  9. package/build/claude-login.js +85 -0
  10. package/build/claude-user-config-doctor.js +59 -33
  11. package/build/commands.generated.js +12 -11
  12. package/build/conduct-epic/bridge-client.js +345 -0
  13. package/build/conduct-epic/checkpoint-store.js +423 -0
  14. package/build/conduct-epic/cli.js +1732 -0
  15. package/build/conduct-epic/lock.js +302 -0
  16. package/build/conduct-epic/pr-state.js +197 -0
  17. package/build/conduct-epic/spawn.js +101 -0
  18. package/build/conductor/bridge-api-client.js +37 -2
  19. package/build/conductor/doctor.js +11 -1
  20. package/build/conductor/install-doctor.js +184 -10
  21. package/build/conductor-bin.js +7 -7
  22. package/build/credential-store.js +10 -4
  23. package/build/credentials-cli.js +34 -19
  24. package/build/docs.generated.js +1 -1
  25. package/build/doctor.js +579 -88
  26. package/build/executor/agent-identity.js +32 -0
  27. package/build/executor/cli.js +50 -39
  28. package/build/executor/deps.js +15 -1
  29. package/build/executor/env.js +56 -45
  30. package/build/executor/index.js +9 -1
  31. package/build/executor/install-preflight.js +138 -0
  32. package/build/executor/job-errors.js +200 -0
  33. package/build/executor/job-runner.js +619 -268
  34. package/build/executor/observation.js +165 -0
  35. package/build/executor/permissions.js +163 -36
  36. package/build/executor/platform.js +54 -0
  37. package/build/executor/preflight.js +175 -67
  38. package/build/executor/process.js +39 -7
  39. package/build/executor/runner.js +19 -0
  40. package/build/executor/service-lifecycle.js +269 -0
  41. package/build/executor/service-unit.js +121 -12
  42. package/build/executor/stale-artifacts.js +70 -0
  43. package/build/executor/test-clock.js +188 -24
  44. package/build/executor/worker-command.js +22 -58
  45. package/build/executor/worker-log.js +82 -0
  46. package/build/executor/worktree-lock.js +264 -0
  47. package/build/index.js +527 -357
  48. package/build/install-bridge-conductor.js +376 -38
  49. package/build/install-bridge.js +414 -114
  50. package/build/install-doctor.js +13 -0
  51. package/build/install-reexec.js +5 -3
  52. package/build/mcp-install-state.js +130 -0
  53. package/build/mcp-profile.js +11 -2
  54. package/build/mcp-provisioning.js +15 -0
  55. package/build/merge-pull-request.js +562 -0
  56. package/build/phase-result-artifacts.js +450 -0
  57. package/build/pipeline-orchestrator.js +4 -0
  58. package/build/pipeline-utils.js +16 -0
  59. package/build/pipelines.generated.js +7 -7
  60. package/build/plane/preflight.js +18 -14
  61. package/build/plane/supervisor.js +8 -1
  62. package/build/project-root.js +34 -0
  63. package/build/readme.generated.js +1 -1
  64. package/build/run-unit-tests-launcher.js +36 -9
  65. package/build/setup-epic.js +57 -4
  66. package/build/sfcc/permissions.js +25 -6
  67. package/build/sfcc/reads-site-preference.js +6 -0
  68. package/build/sfcc/register.js +61 -23
  69. package/build/sfcc/registration-inventory.js +89 -0
  70. package/build/sfcc/setup-status.js +18 -34
  71. package/build/sfcc/tool-wrapper.js +294 -17
  72. package/build/sfcc/write-grants.js +33 -1
  73. package/build/sfcc/write-guard.js +41 -12
  74. package/build/sfcc/writes-custom-object-def.js +6 -2
  75. package/build/sfcc/writes-site-preference.js +6 -1
  76. package/build/sfcc/writes-system-object.js +11 -2
  77. package/build/sfcc/writes.js +13 -8
  78. package/build/start-tickets-prereqs.js +25 -15
  79. package/build/start-tickets.js +123 -21
  80. package/build/version.generated.js +1 -1
  81. package/build/worktree-core.js +9 -3
  82. package/docs/install/mcp-tool-integrations.md +54 -9
  83. package/docs/install/sfcc-integration.md +71 -24
  84. package/package.json +3 -3
  85. package/build/executor/worker-config-isolation.js +0 -287
@@ -1,3 +1,97 @@
1
+ /**
2
+ * Executor-local named error helpers (BAPI-535, TDD §7/§9).
3
+ *
4
+ * Fail-loud executor conditions carry an explicit, stable `errorKind` so the
5
+ * runner can post the right `/fail` payload without coupling the executor to the
6
+ * v1 conductor error/ledger graph (see `types.ts` for the boundary contract).
7
+ * These are the ONLY named executor failure kinds this slice introduces:
8
+ *
9
+ * - `MissingVerdictArtifact` — a `spec_review`/`smoke` job exited cleanly but its
10
+ * fixed-path `<worktree>/.conductor/result.json` was missing/unreadable/invalid
11
+ * (TDD §9: "a verdict can never be silently absent").
12
+ * - `WorktreeLostBeforePush` — a `resume` job's worktree is gone AND its branch was
13
+ * never pushed, so there is nothing to recreate from (TDD §7).
14
+ * - `BranchMismatch` — a `resume` worktree is on the wrong branch; working there
15
+ * would corrupt an unrelated branch, so abort rather than proceed (TDD §7).
16
+ * - `WorkerFinalizationMissingRemoteBranchAndPr` — an implementation-style job
17
+ * (BAPI-551) exited cleanly but produced neither a PR URL nor a pushed origin
18
+ * branch, stranding the implement gate; see `worker-finalization.ts`.
19
+ * - `WorkerFinalizationPrBaseMismatch` — an implementation-style job (BAPI-586)
20
+ * opened a PR whose base branch is not the run base, so `claude-review.yml`
21
+ * (triggered only on `branches: [main]`) never fires and the `code_review`
22
+ * gate would hang forever; see `worker-finalization.ts`.
23
+ * - `WorkerFinalizationSavedButUnfinalized` — an implementation-style job
24
+ * (BAPI-762) exited cleanly, and an origin branch exists at an authoritative
25
+ * tip that does NOT match the worker's own HEAD — durable work exists on
26
+ * origin, but not this worker's latest commit. Distinct from
27
+ * `WorkerFinalizationMissingRemoteBranchAndPr` (which covers "no evidence any
28
+ * work reached origin") because this case has positive proof of recoverable
29
+ * state: an operator can resume/finalize from the existing branch rather than
30
+ * re-running from scratch; see `worker-finalization.ts`.
31
+ * - `ContractError.WorkerConfigIsolation` — a per-job isolated Claude config
32
+ * directory could not be established (unsupported platform, unsupported auth
33
+ * layout, unseedable directory, or a missing required MCP registration), so
34
+ * the worker would have fallen back to the operator's configuration and
35
+ * inherited operator-scoped MCP servers. Fail-CLOSED (BAPI-731 WS-A);
36
+ * see `worker-config-isolation.ts`.
37
+ * - `ContractError.PreSpawnVerification` — the prepared worktree was not
38
+ * provably clean at the expected commit immediately before spawn, so the
39
+ * attempt could have committed leftover unrelated work (the F11a class).
40
+ * Fail-CLOSED, including on a DEGRADED git read: "could not verify" is
41
+ * never reported as "verified clean" (BAPI-731 WS-E).
42
+ * - `ContractError.McpSurfaceMismatch` — the worker reported, on its own
43
+ * `system`/`init` event, a set of loaded MCP servers that is not the set
44
+ * provisioned into its worktree. Either it inherited a server it was never
45
+ * granted, or a provisioned server is missing, or the event could not be read
46
+ * at all. Fail-CLOSED and mid-flight: the worker is terminated before it does
47
+ * work (BAPI-790); see `createMcpSurfaceObserver` in `observation.ts`.
48
+ * - `ContractError.RequiredMcpRegistration` — the prepared worktree's
49
+ * `.mcp.json` is absent, unreadable, malformed, or carries no `bridge-api`
50
+ * entry. Since a worker loads MCP servers strictly from that file, it would
51
+ * run with no Bridge tools and exit "cleanly" having done nothing
52
+ * (RUN-FINDINGS-2026-08-05 F2). Fail-CLOSED, pre-spawn. Renamed from the
53
+ * isolation-era kind by BAPI-790, because the condition is now about the file
54
+ * itself rather than about an isolation directory.
55
+ * - `ContractError.WorkerStartupFatal` — the worker exited non-zero having
56
+ * emitted no stream-json event whatsoever, i.e. it died before reporting its
57
+ * MCP surface. Distinguished from an ordinary `WorkerCrashed` because the
58
+ * known cause under strict MCP loading is an enterprise `managed-mcp.json`
59
+ * policy rejecting the strict flags, and the executor deliberately does NOT
60
+ * retry without them (BAPI-790).
61
+ * - `ContractError.ClaudeNotAuthenticated` — the worker's own stream-json
62
+ * terminal `result` event reports one of the two Claude CLI authentication
63
+ * failures measured and recorded in
64
+ * `docs/claude/claude-cli-config-isolation-inventory.md` (Findings 4/5): no
65
+ * credential at all (`Not logged in · Please run /login`), or a present but
66
+ * invalid/expired `CLAUDE_CODE_OAUTH_TOKEN` (`OAuth access token is
67
+ * invalid`, HTTP 401). Since BAPI-791 removed spawn-time credential
68
+ * resolution, authentication is no longer checked before spawning — it
69
+ * succeeds or fails at the real worker spawn, and a recognized failure here
70
+ * is reported with this fixed, secret-free kind instead of a generic
71
+ * `WorkerCrashed`.
72
+ * - `ContractError.ExecutorAdapterUnavailable` — the configured agent has no
73
+ * usable executor adapter (BAPI-781): unknown agent, no adapter registration,
74
+ * an unimplemented strategy, an identity mismatch against the registry, a
75
+ * missing/unsupported required capability, or a spawn shape inconsistent with
76
+ * what the adapter declared. Fail-CLOSED and pre-spawn. This exists so the
77
+ * refusal is DISTINGUISHABLE from a worker that ran and failed: the
78
+ * alternative to reporting it is defaulting to Claude's behavior for an agent
79
+ * nobody implemented, which would spawn a real worker under containment the
80
+ * operator never declared.
81
+ *
82
+ * These kinds are deliberately DISTINCT from each other so the refusals stay
83
+ * tellable apart in `executor_jobs.error_kind`.
84
+ *
85
+ * RETIRED (BAPI-790), kept exported so historical rows stay decodable and so a
86
+ * reader who greps a stored `error_kind` still lands on its definition:
87
+ * - `ContractError.WorkerConfigIsolation` and
88
+ * `ContractError.BridgeCredentialUnavailable` belonged to the per-job Claude
89
+ * config-directory isolation retired by BAPI-790. Nothing posts them now.
90
+ * - `ContractError.McpShadowing` was the BAPI-727 shadowing refusal, now an
91
+ * advisory warning — strict loading means an operator registration cannot
92
+ * shadow a worker.
93
+ */
94
+ import { normalizeMcpServerNames } from "./observation.js";
1
95
  /** Stable executor failure-kind constants (posted verbatim as `error_kind`). */
2
96
  export const MissingVerdictArtifact = "MissingVerdictArtifact";
3
97
  export const WorktreeLostBeforePush = "WorktreeLostBeforePush";
@@ -8,6 +102,112 @@ export const WorkerFinalizationSavedButUnfinalized = "WorkerFinalizationSavedBut
8
102
  export const WorkerConfigIsolation = "ContractError.WorkerConfigIsolation";
9
103
  export const PreSpawnVerification = "ContractError.PreSpawnVerification";
10
104
  export const BridgeCredentialUnavailable = "ContractError.BridgeCredentialUnavailable";
105
+ export const McpSurfaceMismatch = "ContractError.McpSurfaceMismatch";
106
+ export const WorkerStartupFatal = "ContractError.WorkerStartupFatal";
107
+ export const RequiredMcpRegistration = "ContractError.RequiredMcpRegistration";
108
+ export const ClaudeNotAuthenticated = "ContractError.ClaudeNotAuthenticated";
109
+ export const WorktreeBusy = "ContractError.WorktreeBusy";
110
+ export const ExecutorAdapterUnavailable = "ContractError.ExecutorAdapterUnavailable";
111
+ /**
112
+ * BAPI-814/D1: a previous attempt's `.conductor/result.json` / `critique.md`
113
+ * could not be removed before the worker spawned. Fail-closed on purpose — the
114
+ * alternative is running an attempt that may read a stale verdict as its own.
115
+ */
116
+ export const StaleArtifactCleanupFailed = "ContractError.StaleArtifactCleanupFailed";
117
+ /** Rendered in place of an empty name list, so "none" is never ambiguous. */
118
+ export const EMPTY_MCP_SERVER_NAME_MARKER = "none";
119
+ /** Bound the rendered name lists so a pathological registration cannot spam a job row. */
120
+ const MCP_SURFACE_NAME_LIMIT = 20;
121
+ /**
122
+ * Render a name list for a containment diagnostic: already-normalized names,
123
+ * comma-joined, bounded, with a fixed marker for the empty case.
124
+ *
125
+ * NAMES ONLY, and that is a hard constraint rather than a stylistic one. This
126
+ * text is posted to the server as `error_message` and stored on the job row, so
127
+ * anything else that could ride along — a registration command, an argv array, an
128
+ * env block, the `.mcp.json` path (which contains a username), or a raw stream
129
+ * line — would turn a containment failure into a disclosure.
130
+ */
131
+ function formatMcpServerNameList(names) {
132
+ // Normalized HERE rather than trusted from the caller. Both call sites already
133
+ // pass normalized sets, but determinism is the property that makes two job rows
134
+ // comparable, and a guarantee that depends on every caller remembering to
135
+ // normalize is not a guarantee.
136
+ const normalized = normalizeMcpServerNames(names);
137
+ if (normalized.length === 0)
138
+ return EMPTY_MCP_SERVER_NAME_MARKER;
139
+ const shown = normalized.slice(0, MCP_SURFACE_NAME_LIMIT);
140
+ const suffix = normalized.length > shown.length ? `, +${normalized.length - shown.length} more` : "";
141
+ return `${shown.join(", ")}${suffix}`;
142
+ }
143
+ /**
144
+ * The fixed message posted with {@link McpSurfaceMismatch}.
145
+ *
146
+ * Deterministic for a given pair of name sets: both sides arrive already sorted
147
+ * and deduplicated from `normalizeMcpServerNames`, so the same mismatch always
148
+ * renders the same text and an operator can compare two job rows directly.
149
+ */
150
+ export function formatMcpSurfaceMismatch(expected, observed) {
151
+ return ("worker MCP surface mismatch: the worker reported loading a different set of MCP servers " +
152
+ "than its worktree provisions, so it was terminated before doing work. " +
153
+ `Expected: ${formatMcpServerNameList(expected)}. Observed: ${formatMcpServerNameList(observed)}. ` +
154
+ "An observed set of 'none' means the init event's server list could not be read at all. " +
155
+ "Check that the installed Claude CLI supports --strict-mcp-config and that nothing adds MCP " +
156
+ "servers outside the worktree registration.");
157
+ }
158
+ /**
159
+ * The fixed message posted with {@link WorkerStartupFatal}.
160
+ *
161
+ * States only what was OBSERVED — a non-zero exit with no stream-json output —
162
+ * and names enterprise managed MCP policy as the known cause to check, without
163
+ * claiming to have identified it. That distinction is deliberate: the enterprise
164
+ * `managed-mcp.json` fatal signature has not been measured on any host available
165
+ * to this repository (see inventory Finding 6), so asserting it would be a guess
166
+ * printed as a diagnosis.
167
+ */
168
+ export const WORKER_STARTUP_FATAL_MESSAGE = "the worker exited before reporting its MCP surface: it produced no stream-json output at all " +
169
+ "and exited non-zero, which is a fatal startup failure rather than a failure during work. The " +
170
+ "known cause under strict MCP loading is an enterprise managed MCP policy (managed-mcp.json) " +
171
+ "rejecting --strict-mcp-config; also verify the installed Claude CLI supports the strict MCP " +
172
+ "flags. The executor does not retry without them, because falling back to unscoped loading " +
173
+ "would silently restore full inheritance of the operator's MCP servers.";
174
+ /**
175
+ * The fixed message posted with {@link ClaudeNotAuthenticated}.
176
+ *
177
+ * Names only the two remediation paths, never the raw stream-json content that
178
+ * triggered classification — the adapter's detector returns a verdict and a
179
+ * reason code, never the matched line. The headless alternative names the
180
+ * environment variable only, never a value.
181
+ */
182
+ export const CLAUDE_NOT_AUTHENTICATED_MESSAGE = "the worker could not authenticate as the Claude CLI. Run `claude login` on this host; on a " +
183
+ "headless host with no interactive login available, export CLAUDE_CODE_OAUTH_TOKEN yourself " +
184
+ "before starting the executor.";
185
+ /**
186
+ * The fixed message posted with {@link WorktreeBusy} (BAPI-793).
187
+ *
188
+ * FIXED, and carrying no identity at all — not the worktree path, not the
189
+ * conflicting job's id, not a claim token. This string is stored on the job row
190
+ * and read back by anyone with access to the run, while the worktree path
191
+ * contains an operator's username and the claim token is a fencing credential.
192
+ * The attributable detail (this job, the conflicting job, ticket, repo, worktree
193
+ * basename) goes to the executor's OWN stderr instead, where it stays on the
194
+ * host that already has all of it.
195
+ */
196
+ export const WORKTREE_BUSY_MESSAGE = "another executor job already holds this ticket's worktree, so no worker was started for this " +
197
+ "job. Two workers in one working tree corrupt each other's edits, index, and commits, so the " +
198
+ "second claim is refused rather than allowed in. The refusal is expected when two jobs exist " +
199
+ "for one ticket; the job that holds the worktree continues normally, and this one is safe to " +
200
+ "retry once it finishes. See the executor's stderr for the conflicting job id.";
201
+ // The Claude-specific matcher that used to live here moved into the Claude
202
+ // executor adapter as `classifyClaudeAuthFailure` (BAPI-781). Recognizing one
203
+ // CLI's not-logged-in output is precisely a per-agent capability, and leaving it
204
+ // in a generic error module meant every future agent's auth failure would have
205
+ // to be recognized by Claude's shape or not at all.
206
+ //
207
+ // The ERROR KIND and the fixed message above stay here on purpose: mapping a
208
+ // classification onto a stable executor failure remains executor-owned, so an
209
+ // adapter cannot invent its own error kinds or its own operator-facing
210
+ // remediation text.
11
211
  /** Bound a failure message so no unbounded/secret-bearing text is posted. */
12
212
  const ERROR_MESSAGE_MAX_CHARS = 300;
13
213
  /**