@bridge_gpt/mcp-server 0.2.66 → 0.2.68

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 (171) hide show
  1. package/README.md +421 -83
  2. package/build/agent-capabilities/probes.js +15 -5
  3. package/build/agent-launchers/claude-executor-adapter.js +70 -16
  4. package/build/agent-launchers/executor-adapter.js +7 -4
  5. package/build/agents.generated.js +22 -2
  6. package/build/bitbucket-workspace-remote.js +136 -0
  7. package/build/bootstrap-project-identity.js +24 -0
  8. package/build/bounded-wait.js +67 -10
  9. package/build/bridge-permissions.js +829 -0
  10. package/build/claude-settings.js +18 -0
  11. package/build/cli-help.js +21 -0
  12. package/build/command-assets-doctor.js +24 -70
  13. package/build/command-provisioning.js +29 -5
  14. package/build/commands.generated.js +12 -12
  15. package/build/conductor/bridge-api-client.js +857 -1
  16. package/build/conductor/bring-up-facts.js +1 -1
  17. package/build/conductor/command-drift-production.js +92 -0
  18. package/build/conductor/command-drift.js +89 -0
  19. package/build/conductor/doctor.js +72 -29
  20. package/build/conductor/epic-branch-ci-inspection.js +1375 -0
  21. package/build/conductor/epic-implementer-cli.js +98 -28
  22. package/build/conductor/errors.js +4 -3
  23. package/build/conductor/gate-discovery.js +890 -0
  24. package/build/conductor/guided-repair.js +6 -2
  25. package/build/conductor/hook-runtime-qualification.js +1 -1
  26. package/build/conductor/install-doctor.js +15 -3
  27. package/build/conductor/json-output.js +63 -0
  28. package/build/conductor/merge-execution-contract.js +27 -8
  29. package/build/conductor/merge-execution-eligibility.js +3 -2
  30. package/build/conductor/pr-ci-producer.js +1 -1
  31. package/build/conductor/readiness-cli.js +113 -12
  32. package/build/conductor/readiness-sections.js +410 -9
  33. package/build/conductor/readiness.js +388 -33
  34. package/build/conductor/recovery-cli.js +310 -12
  35. package/build/conductor/recovery-operations.js +167 -3
  36. package/build/conductor/repair-contract.js +54 -3
  37. package/build/conductor/repository-workflow-remedy.js +125 -0
  38. package/build/conductor/tools.js +2 -2
  39. package/build/conductor-bundle-artifacts.js +8 -0
  40. package/build/connect-bitbucket-api.js +41 -6
  41. package/build/connect-bitbucket.js +106 -33
  42. package/build/credential-store.js +207 -47
  43. package/build/docs.generated.js +62 -3
  44. package/build/doctor.js +92 -1
  45. package/build/drive-epic-key.js +6 -5
  46. package/build/drive-epic.js +129 -61
  47. package/build/epic-coherence-input.js +2 -1
  48. package/build/epic-coherence-input.test-fixtures.js +4 -3
  49. package/build/epic-implementer-bin.js +1379 -28
  50. package/build/epic-implementer-bundle-cli.js +2 -2
  51. package/build/epic-workarounds-path.js +39 -0
  52. package/build/executor/cli.js +33 -2
  53. package/build/executor/completion-contract.js +66 -10
  54. package/build/executor/completion-supervision.js +4 -0
  55. package/build/executor/deps.js +4 -1
  56. package/build/executor/env.js +19 -0
  57. package/build/executor/gate-qualification-job.js +499 -0
  58. package/build/executor/guarded-fast-forward-push.js +129 -0
  59. package/build/executor/heartbeat.js +1 -1
  60. package/build/executor/http-client.js +20 -0
  61. package/build/executor/integration-job.js +122 -8
  62. package/build/executor/job-errors.js +33 -1
  63. package/build/executor/job-runner.js +813 -87
  64. package/build/executor/likely-tests.js +290 -0
  65. package/build/executor/live-worker-registry.js +1 -1
  66. package/build/executor/observation.js +37 -3
  67. package/build/executor/packaged-recipe.js +106 -0
  68. package/build/executor/permissions.js +115 -28
  69. package/build/executor/platform.js +1 -1
  70. package/build/executor/preflight.js +112 -26
  71. package/build/executor/process-containment.js +36 -12
  72. package/build/executor/process.js +15 -7
  73. package/build/executor/prompt-spec.js +33 -1
  74. package/build/executor/recently-failed-tests-file.js +71 -0
  75. package/build/executor/reconcile-overlap-job.js +41 -23
  76. package/build/executor/required-verification.js +1 -1
  77. package/build/executor/required-work-ledger.js +111 -18
  78. package/build/executor/resume-pre-spawn.js +2 -0
  79. package/build/executor/retirement.js +69 -0
  80. package/build/executor/runner.js +122 -13
  81. package/build/executor/service-unit.js +7 -1
  82. package/build/executor/test-clock.js +15 -0
  83. package/build/executor/types.js +32 -0
  84. package/build/executor/viewer-tabs.js +58 -8
  85. package/build/executor/worker-command.js +23 -7
  86. package/build/executor/worker-diagnostics.js +37 -0
  87. package/build/executor/worker-finalization.js +113 -34
  88. package/build/executor/worker-guard-hook.js +316 -58
  89. package/build/executor/worker-log.js +4 -3
  90. package/build/executor/worker-verification-guidance.js +37 -0
  91. package/build/executor/worktree.js +166 -8
  92. package/build/first-build-advisory.js +97 -0
  93. package/build/generated-assets-advisory.js +14 -0
  94. package/build/generated-assets-catalog.js +66 -0
  95. package/build/generated-assets-context.js +46 -0
  96. package/build/generated-assets-dependencies.js +26 -0
  97. package/build/generated-assets-doctor.js +50 -0
  98. package/build/generated-assets-health.js +65 -0
  99. package/build/generated-assets-host.js +17 -0
  100. package/build/generated-assets-inventory.js +17 -0
  101. package/build/generated-assets-paths.js +60 -0
  102. package/build/generated-assets-publisher.js +133 -0
  103. package/build/generated-assets-remedy.js +25 -0
  104. package/build/generated-assets-repair.js +72 -0
  105. package/build/generated-assets-session.js +71 -0
  106. package/build/generated-assets-test-support.js +35 -0
  107. package/build/index.js +1224 -1054
  108. package/build/init.js +54 -177
  109. package/build/install-bridge-conductor-gate.js +1372 -0
  110. package/build/install-bridge-conductor.js +296 -41
  111. package/build/install-bridge.js +547 -40
  112. package/build/mcp-install-state.js +50 -4
  113. package/build/merge-workflow-install.js +3 -4
  114. package/build/phase-context-git-probe.js +68 -0
  115. package/build/phase-result-artifacts.js +173 -5
  116. package/build/pipeline-utils.js +6 -2
  117. package/build/pipelines.generated.js +34 -160
  118. package/build/plan-execution-ledger.js +2 -32
  119. package/build/plane/alembic-head.js +12 -3
  120. package/build/plane/base-worktree-guard.js +147 -0
  121. package/build/plane/cli.js +217 -17
  122. package/build/plane/code-snapshot.js +468 -0
  123. package/build/plane/defaults.js +48 -3
  124. package/build/plane/endpoint.js +41 -0
  125. package/build/plane/manifest.js +136 -2
  126. package/build/plane/member-roster.js +94 -19
  127. package/build/plane/preflight.js +83 -2
  128. package/build/plane/process-cwd.js +67 -0
  129. package/build/plane/restart.js +542 -0
  130. package/build/plane/shutdown.js +31 -0
  131. package/build/plane/status.js +143 -8
  132. package/build/plane/supervisor.js +586 -179
  133. package/build/plane/types.js +54 -2
  134. package/build/printed-remedy-commands.js +52 -0
  135. package/build/readiness-check.js +1 -1
  136. package/build/readme.generated.js +1 -1
  137. package/build/repair-assets.js +93 -0
  138. package/build/review-generation.js +22 -0
  139. package/build/run-unit-tests-launcher.js +130 -49
  140. package/build/secret-redaction.js +33 -0
  141. package/build/setup-epic.js +152 -22
  142. package/build/sfcc/config.js +9 -0
  143. package/build/sfcc/credentials.js +100 -38
  144. package/build/sfcc/hostname.js +67 -0
  145. package/build/sfcc/permissions.js +17 -13
  146. package/build/sfcc/register.js +1 -1
  147. package/build/sfcc/tool-wrapper.js +39 -43
  148. package/build/sfcc/write-grants.js +17 -11
  149. package/build/sfcc/write-result.js +4 -3
  150. package/build/sfcc/writes-site-preference.js +20 -8
  151. package/build/start-tickets-prereqs.js +70 -16
  152. package/build/start-tickets.js +208 -36
  153. package/build/tool-error-envelope.js +61 -0
  154. package/build/tool-surface-gating.js +36 -0
  155. package/build/upgrade-cli.js +55 -1
  156. package/build/version.generated.js +3 -3
  157. package/build/visual-diff.js +22 -1
  158. package/build/worker-guard-hook-bin.js +4 -6
  159. package/build/worker-guard-hook-main.js +47 -0
  160. package/build/worktree-core.js +145 -6
  161. package/docs/EPIC-IMPLEMENTER-INSTALL.md +867 -0
  162. package/docs/EPIC-IMPLEMENTER.md +728 -0
  163. package/docs/install/mcp-tool-integrations.md +24 -15
  164. package/docs/install/sfcc-integration.md +12 -4
  165. package/package.json +3 -3
  166. package/pipelines/greenfield-setup.json +4 -128
  167. package/pipelines/implement-ticket.json +3 -2
  168. package/pipelines/plan-epic.json +0 -5
  169. package/pipelines/review-ticket.json +1 -1
  170. package/docs/CONDUCTOR.md +0 -605
  171. package/pipelines/idea-to-pr.json +0 -49
@@ -14,7 +14,12 @@
14
14
  * epic branch through the provider's merge API. No checkout, no force.
15
15
  * * `mark_ready` — finds the ONE open pull request from the epic branch to the
16
16
  * base (creating it only after conclusive absence), confirms its head is the
17
- * expected epic head, and takes it out of draft.
17
+ * expected epic head, and takes it out of draft. BAPI-1399: first it lists the
18
+ * workaround folder `.bridge/epic-workarounds/` (the canonical path, imported
19
+ * from `../epic-workarounds-path.ts`) at the expected epic head. While the folder is
20
+ * present it only finds or creates the draft and reports `already_satisfied`
21
+ * with `detail_code: "workarounds_present"`, so a stale coordinator
22
+ * observation can never take the pull request out of draft.
18
23
  * * `correct` — runs ONE worker through the executor's existing locked spawn
19
24
  * path under a driver that prepares the epic branch, verifies the worker's
20
25
  * edits, makes the one commit, and performs the one push. The worker has no
@@ -46,7 +51,8 @@
46
51
  * and this module chooses no next ticket and no gate.
47
52
  */
48
53
  import { buildLocalMergeChildEnv, resolveLocalMergeCredential, sanitizeLocalMergeOutput, } from "../conductor/local-merge.js";
49
- import { createProductionEpicIntegrationGhRunner, ensureEpicIntegrationPullRequest, } from "../epic-integration-pr.js";
54
+ import { EPIC_INTEGRATION_PR_READ_TIMEOUT_MS, createProductionEpicIntegrationGhRunner, ensureEpicIntegrationPullRequest, } from "../epic-integration-pr.js";
55
+ import { EPIC_WORKAROUNDS_DIR_PATH } from "../epic-workarounds-path.js";
50
56
  import { INTEGRATION_ACTION_OPERATIONS, INTEGRATION_ACTION_OUTCOMES, INTEGRATION_ACTION_PROTOCOL_VERSION, } from "./types.js";
51
57
  /** The route prefix, mirrored from `api/routes/__init__.py`. */
52
58
  export const INTEGRATION_ACTION_ROUTE_PREFIX = "/epic-integration-actions";
@@ -386,20 +392,128 @@ function mapPullRequestOutcome(outcome) {
386
392
  return { outcome: "indeterminate", detail_code: safeDetail(outcome.reason) };
387
393
  }
388
394
  }
389
- async function performMarkReady(action, deps, env, seams) {
395
+ // ---------------------------------------------------------------------------
396
+ // BAPI-1399: the workaround folder re-check
397
+ // ---------------------------------------------------------------------------
398
+ /** The `detail_code` a held `mark_ready` reports on its `already_satisfied` outcome. */
399
+ export const WORKAROUNDS_PRESENT_DETAIL_CODE = "workarounds_present";
400
+ /**
401
+ * Classify one contents-API answer for `.bridge/epic-workarounds/`. Pure, and
402
+ * the twin of `classify_workaround_listing` in
403
+ * `api/library/github/github_webhooks_lib.py`; both suites read the shared
404
+ * parity vectors. `absent` needs a 404 AND proof that the repository and the
405
+ * epic head were readable with the same credential; anything the reader cannot
406
+ * establish — an unproven 404, any other status, no status, an empty array, an
407
+ * object, or entries that are not directory records — is `failed`.
408
+ */
409
+ export function classifyWorkaroundListing(status, body, accessProven) {
410
+ if (status === 404)
411
+ return accessProven === true ? "absent" : "failed";
412
+ if (status !== 200)
413
+ return "failed";
414
+ if (!Array.isArray(body) || body.length === 0)
415
+ return "failed";
416
+ for (const entry of body) {
417
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry))
418
+ return "failed";
419
+ const name = entry.name;
420
+ if (typeof name !== "string" || name.length === 0)
421
+ return "failed";
422
+ }
423
+ return "present";
424
+ }
425
+ /**
426
+ * List the workaround folder at the expected epic head through the restricted
427
+ * credentialed `gh` environment, with a bounded timeout. `accessProven` is true
428
+ * only when the caller read the epic head with this same credential in this
429
+ * attempt. Never throws; a failure is `failed`, never absence.
430
+ */
431
+ async function listEpicWorkarounds(deps, credential, env, repository, expectedEpicHeadSha, accessProven) {
432
+ if (!PROVIDER_REPOSITORY_RE.test(repository) || !SHA_RE.test(expectedEpicHeadSha))
433
+ return "failed";
434
+ const r = await runCredentialed(deps, credential, env, "gh", [
435
+ "api", "--include",
436
+ `repos/${repository}/contents/${EPIC_WORKAROUNDS_DIR_PATH}?ref=${expectedEpicHeadSha}`,
437
+ ], { timeoutMs: READ_TIMEOUT_MS });
438
+ const status = parseGhHttpStatus(r.stdout, r.stderr);
439
+ if (status === 200 && r.exitCode !== 0)
440
+ return "failed";
441
+ return classifyWorkaroundListing(status, status === 200 ? parseIncludedBody(r.stdout) : null, accessProven);
442
+ }
443
+ /**
444
+ * Read one pull request's draft flag, branches, and head, bounded. The draft-only
445
+ * path of {@link ensureEpicIntegrationPullRequest} does not bind the head, so the
446
+ * held path proves the binding itself before it reports a hold. `null` when the
447
+ * read fails or the answer is not well formed.
448
+ */
449
+ async function readPullRequestBinding(gh, prNumber, repository, cwd) {
450
+ try {
451
+ const r = await gh([
452
+ "pr", "view", String(prNumber), "--repo", repository,
453
+ "--json", "isDraft,headRefName,baseRefName,headRefOid",
454
+ ], { cwd, timeoutMs: EPIC_INTEGRATION_PR_READ_TIMEOUT_MS });
455
+ if (r.exitCode !== 0)
456
+ return null;
457
+ const parsed = JSON.parse(r.stdout);
458
+ if (typeof parsed !== "object" || parsed === null)
459
+ return null;
460
+ const { isDraft, headRefName, baseRefName, headRefOid } = parsed;
461
+ if (typeof isDraft !== "boolean" || typeof headRefName !== "string" || typeof baseRefName !== "string") {
462
+ return null;
463
+ }
464
+ const sha = typeof headRefOid === "string" ? headRefOid.toLowerCase() : "";
465
+ return { isDraft, headRefName, baseRefName, headSha: SHA_RE.test(sha) ? sha : null };
466
+ }
467
+ catch {
468
+ return null;
469
+ }
470
+ }
471
+ async function performMarkReady(action, deps, credential, env, seams) {
390
472
  const createGh = seams.createGhRunner ?? ((e) => createProductionEpicIntegrationGhRunner(undefined, e));
391
- const outcome = await ensureEpicIntegrationPullRequest({
473
+ const gh = createGh(env);
474
+ const ensure = (requestReady) => ensureEpicIntegrationPullRequest({
392
475
  epicKey: action.epic_key,
393
476
  epicBranch: action.epic_branch,
394
477
  baseBranch: action.base_branch,
395
478
  command: "executor integration",
396
- gh: createGh(env),
479
+ gh,
397
480
  cwd: deps.cwd,
398
- requestReady: true,
481
+ requestReady,
399
482
  expectedHeadSha: action.expected_epic_head_sha,
400
483
  repo: action.provider_repository,
401
484
  });
402
- return mapPullRequestOutcome(outcome);
485
+ // The caller read the live epic head with this same credential immediately
486
+ // before this call, so a 404 here can only mean the folder is absent.
487
+ const listing = await listEpicWorkarounds(deps, credential, env, action.provider_repository, action.expected_epic_head_sha, true);
488
+ if (listing === "failed") {
489
+ // Unreadable is never absence: report indeterminate, which spends one
490
+ // reconciliation probe exactly as any other unreadable observation does.
491
+ return { outcome: "indeterminate", detail_code: "probe_inconclusive" };
492
+ }
493
+ if (listing === "absent")
494
+ return mapPullRequestOutcome(await ensure(true));
495
+ // Present: find or create the draft and leave it a draft. `not_requested` is
496
+ // never passed through `mapPullRequestOutcome`, which would read it as failed.
497
+ const outcome = await ensure(false);
498
+ if (outcome.kind !== "already_open" && outcome.kind !== "created") {
499
+ return mapPullRequestOutcome(outcome);
500
+ }
501
+ if (outcome.prNumber === null)
502
+ return { outcome: "indeterminate", detail_code: "probe_inconclusive" };
503
+ const pr = outcome.prNumber;
504
+ const binding = await readPullRequestBinding(gh, pr, action.provider_repository, deps.cwd);
505
+ if (binding === null)
506
+ return { outcome: "indeterminate", pr_number: pr, detail_code: "probe_inconclusive" };
507
+ if (binding.headRefName !== action.epic_branch || binding.baseRefName !== action.base_branch) {
508
+ return { outcome: "pr_ambiguous", pr_number: pr, detail_code: "probe_ambiguous" };
509
+ }
510
+ if (binding.headSha !== action.expected_epic_head_sha) {
511
+ return { outcome: "head_drift", pr_number: pr, detail_code: "pr_head_moved" };
512
+ }
513
+ // A non-draft PR is never claimed as held: it is already ready, as today.
514
+ if (!binding.isDraft)
515
+ return { outcome: "already_satisfied", pr_number: pr };
516
+ return { outcome: "already_satisfied", pr_number: pr, detail_code: WORKAROUNDS_PRESENT_DETAIL_CODE };
403
517
  }
404
518
  /**
405
519
  * Perform one claimed integration action and report its facts.
@@ -469,7 +583,7 @@ export async function runIntegrationAction(action, client, deps, seams = {}) {
469
583
  report = await performSyncBase(action, deps, credential, env, reads);
470
584
  }
471
585
  else if (action.operation === "mark_ready") {
472
- report = await performMarkReady(action, deps, env, seams);
586
+ report = await performMarkReady(action, deps, credential, env, seams);
473
587
  }
474
588
  else if (seams.runCorrection === undefined) {
475
589
  report = { outcome: "failed", detail_code: "correction_unsupported" };
@@ -39,8 +39,13 @@
39
39
  * origin, but not this worker's latest commit. Distinct from
40
40
  * `WorkerFinalizationMissingRemoteBranchAndPr` (which covers "no evidence any
41
41
  * work reached origin") because this case has positive proof of recoverable
42
- * state: an operator can resume/finalize from the existing branch rather than
42
+ * state: an operator can preserve the newer local worktree commit rather than
43
43
  * re-running from scratch; see `worker-finalization.ts`.
44
+ * - `WorkerFinalizationOriginUnverifiable` — an implementation-style job
45
+ * (BAPI-1357) exited cleanly, but the origin branch lookup could not be
46
+ * trusted (a throw, an expired bound, an unexpected exit, or unusable output).
47
+ * The branch was NOT observed absent, so this is distinct from
48
+ * `WorkerFinalizationMissingRemoteBranchAndPr`; see `worker-finalization.ts`.
44
49
  * - `ContractError.WorkerConfigIsolation` — a per-job isolated Claude config
45
50
  * directory could not be established (unsupported platform, unsupported auth
46
51
  * layout, unseedable directory, or a missing required MCP registration), so
@@ -141,6 +146,31 @@ export const WorkerFinalizationSavedButUnfinalized = "WorkerFinalizationSavedBut
141
146
  * verdict is `unknown`, never `unmet` and never `ok`.
142
147
  */
143
148
  export const WorkerFinalizationPublicationUnverified = "WorkerFinalizationPublicationUnverified";
149
+ /**
150
+ * BAPI-1357: the origin branch lookup could not be TRUSTED — the command threw,
151
+ * its call bound expired, it exited with anything other than "found" (0) or "no
152
+ * matching ref" (2), or it exited 0 without a usable SHA for the exact ref. The
153
+ * branch was not observed absent, so this is distinct from
154
+ * `WorkerFinalizationMissingRemoteBranchAndPr`, which is reserved for an
155
+ * observed absence. The process itself exited clean. Nothing command-derived
156
+ * (stderr, error text, host, credentials) is carried by this kind.
157
+ */
158
+ export const WorkerFinalizationOriginUnverifiable = "WorkerFinalizationOriginUnverifiable";
159
+ /**
160
+ * BAPI-1364: a LEGACY (non-covered) worker exited cleanly while the structured
161
+ * stream still showed a required background command with no terminal
162
+ * notification. The headless session had no later turn, so the command's result
163
+ * could never reach the worker. Carries only {@link WORKER_ENDED_WITH_PENDING_BACKGROUND_WORK_MESSAGE};
164
+ * no event text, command, path, or output.
165
+ */
166
+ export const WorkerEndedWithPendingBackgroundWork = "WorkerEndedWithPendingBackgroundWork";
167
+ /**
168
+ * BAPI-1392: a recognized Bridge command's packaged recipe could not be delivered
169
+ * to the worker. Refused before spawn rather than silently running the committed
170
+ * copy, which may be stale. The message carries a fixed `reason=<code>` token and
171
+ * a command name only — never prompt text, arguments, or recipe bytes.
172
+ */
173
+ export const PackagedRecipeUndeliverable = "ContractError.PackagedRecipeUndeliverable";
144
174
  export const WorkerConfigIsolation = "ContractError.WorkerConfigIsolation";
145
175
  export const PreSpawnVerification = "ContractError.PreSpawnVerification";
146
176
  export const BridgeCredentialUnavailable = "ContractError.BridgeCredentialUnavailable";
@@ -282,6 +312,8 @@ export function formatMcpSurfaceMismatch(expected, observed) {
282
312
  "Check that the installed Claude CLI supports --strict-mcp-config and that nothing adds MCP " +
283
313
  "servers outside the worktree registration.");
284
314
  }
315
+ /** The fixed message posted with {@link WorkerEndedWithPendingBackgroundWork}. */
316
+ export const WORKER_ENDED_WITH_PENDING_BACKGROUND_WORK_MESSAGE = "the worker ended its session while a background command was still running";
285
317
  /**
286
318
  * The fixed message posted with {@link WorkerStartupFatal}.
287
319
  *