@bridge_gpt/mcp-server 0.2.58 → 0.2.60

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 (127) hide show
  1. package/README.md +231 -113
  2. package/build/agent-guidance.generated.js +1 -1
  3. package/build/agent-notes.js +7 -1
  4. package/build/agent-registry.js +15 -0
  5. package/build/agent-utils.js +16 -8
  6. package/build/claude-user-config-doctor.js +1 -35
  7. package/build/codex-bridge-profile.js +1 -1
  8. package/build/commands.generated.js +7 -8
  9. package/build/conductor/bridge-api-client.js +202 -2
  10. package/build/conductor/bring-up-facts.js +1 -1
  11. package/build/conductor/claude-hook.js +16 -16
  12. package/build/conductor/doctor.js +279 -72
  13. package/build/conductor/epic-implementer-cli.js +38 -5
  14. package/build/conductor/epic-reconcile.js +1 -1
  15. package/build/conductor/epic-runtime.js +21 -12
  16. package/build/conductor/errors.js +3 -3
  17. package/build/conductor/file-scope-guard.js +4 -4
  18. package/build/conductor/git-ci-types.js +1 -1
  19. package/build/conductor/git-inspection.js +2 -2
  20. package/build/conductor/install-doctor.js +28 -6
  21. package/build/conductor/local-merge.js +319 -26
  22. package/build/conductor/merge-execution-contract.js +61 -0
  23. package/build/conductor/merge-execution-eligibility.js +129 -0
  24. package/build/conductor/merge-ledger.js +2 -2
  25. package/build/conductor/pr-ci-producer.js +6 -6
  26. package/build/conductor/pr-review-producer.js +2 -2
  27. package/build/conductor/producer-ledger.js +2 -0
  28. package/build/conductor/readiness-sections.js +166 -9
  29. package/build/conductor/readiness.js +97 -16
  30. package/build/conductor/recovery-cli.js +243 -12
  31. package/build/conductor/recovery-operations.js +64 -6
  32. package/build/conductor/repair-contract.js +38 -4
  33. package/build/conductor/spec-review-producer.js +6 -6
  34. package/build/conductor/store.js +10 -10
  35. package/build/conductor/supervisor-config.js +14 -14
  36. package/build/conductor/supervisor-ledger.js +2 -2
  37. package/build/conductor/supervisor-message-relay.js +2 -2
  38. package/build/conductor/worker-ledger-cli.js +19 -19
  39. package/build/conductor-bundle-artifacts.js +2 -2
  40. package/build/connect-bitbucket-api.js +6 -1
  41. package/build/connect-bitbucket.js +398 -88
  42. package/build/credential-store.js +16 -0
  43. package/build/docs.generated.js +2 -2
  44. package/build/doctor.js +199 -303
  45. package/build/drive-epic.js +88 -71
  46. package/build/epic-implementer-bin.js +22 -17
  47. package/build/epic-implementer-claude-hook-bin.js +4 -2
  48. package/build/epic-implementer-env.js +184 -0
  49. package/build/epic-integration-pr.js +2 -2
  50. package/build/executor/ci-rerun-job.js +269 -0
  51. package/build/executor/cli.js +31 -0
  52. package/build/executor/credentials.js +11 -0
  53. package/build/executor/env.js +79 -8
  54. package/build/executor/heartbeat.js +1 -1
  55. package/build/executor/index.js +21 -4
  56. package/build/executor/job-errors.js +3 -3
  57. package/build/executor/job-runner.js +127 -1
  58. package/build/executor/job-types.js +12 -2
  59. package/build/executor/merge-job.js +46 -5
  60. package/build/executor/observation.js +1 -1
  61. package/build/executor/preflight.js +1 -1
  62. package/build/executor/prompt-spec.js +1 -1
  63. package/build/executor/reconcile-overlap-job.js +10 -130
  64. package/build/executor/reconcile-overlap-types.js +1 -1
  65. package/build/executor/runner.js +1 -1
  66. package/build/executor/service-lifecycle.js +136 -0
  67. package/build/executor/service-unit.js +427 -9
  68. package/build/executor/types.js +5 -0
  69. package/build/index.js +320 -342
  70. package/build/init.js +20 -28
  71. package/build/install-bridge-conductor.js +208 -15
  72. package/build/install-bridge.js +555 -37
  73. package/build/mcp-host-entry-adapter.js +6 -0
  74. package/build/mcp-host-targets.js +2 -0
  75. package/build/mcp-install-state.js +42 -4
  76. package/build/mcp-invoke.js +5 -5
  77. package/build/mcp-profile.js +2 -2
  78. package/build/mcp-provisioning.js +2 -2
  79. package/build/mcp-server-invocation.js +3 -3
  80. package/build/merge-pull-request.js +118 -10
  81. package/build/merge-workflow-codeowners.js +224 -0
  82. package/build/merge-workflow-config.js +133 -0
  83. package/build/merge-workflow-drift.js +66 -0
  84. package/build/merge-workflow-install.js +638 -0
  85. package/build/merge-workflow.js +572 -0
  86. package/build/model-routing-host.js +25 -0
  87. package/build/model-routing-preferences.js +99 -0
  88. package/build/pipelines.generated.js +10 -10
  89. package/build/{plan-epic-conductor-eligibility.js → plan-epic-implementer-eligibility.js} +18 -16
  90. package/build/plan-execution-ledger.js +8 -0
  91. package/build/plane/cli.js +24 -2
  92. package/build/plane/member-roster.js +5 -5
  93. package/build/plane/preflight.js +68 -0
  94. package/build/plane/supervisor.js +1 -1
  95. package/build/plane/types.js +5 -5
  96. package/build/readiness-check.js +1 -1
  97. package/build/readme.generated.js +1 -1
  98. package/build/review-tickets.js +4 -4
  99. package/build/run-unit-tests-launcher.js +5 -0
  100. package/build/setup-epic.js +171 -17
  101. package/build/start-tickets-conductor.js +32 -32
  102. package/build/start-tickets-prereqs.js +4 -9
  103. package/build/start-tickets.js +475 -91
  104. package/build/version.generated.js +3 -3
  105. package/docs/CONDUCTOR.md +69 -18
  106. package/docs/install/mcp-tool-integrations.md +2 -1
  107. package/package.json +4 -4
  108. package/pipelines/implement-ticket.json +1 -1
  109. package/pipelines/plan-epic.json +2 -2
  110. package/build/conduct-epic/bridge-client.js +0 -773
  111. package/build/conduct-epic/checkpoint-store.js +0 -542
  112. package/build/conduct-epic/cli.js +0 -3145
  113. package/build/conduct-epic/cut-protocol.js +0 -392
  114. package/build/conduct-epic/lock.js +0 -302
  115. package/build/conduct-epic/pr-state.js +0 -286
  116. package/build/conduct-epic/spawn.js +0 -113
  117. package/build/conductor/cli.js +0 -1278
  118. package/build/conductor-bundle-cli.js +0 -256
  119. package/build/direct-ticket-tools.js +0 -70
  120. package/build/executor/reconcile-overlap-governance.js +0 -129
  121. package/build/implement-epic/checkpoint-store.js +0 -542
  122. package/build/implement-epic/cli.js +0 -3158
  123. package/build/implement-epic/lock.js +0 -302
  124. package/build/implement-epic/pr-state.js +0 -286
  125. package/build/implement-epic/spawn.js +0 -113
  126. /package/build/{implement-epic → epic-shared}/bridge-client.js +0 -0
  127. /package/build/{implement-epic → epic-shared}/cut-protocol.js +0 -0
@@ -23,7 +23,7 @@ import { processGateMetMerge } from "./supervisor-merge.js";
23
23
  import { observePrCiOnce } from "./pr-ci-producer.js";
24
24
  import { runGhCommand } from "./pr-discovery.js";
25
25
  import { isPrMergeConflict, parseGhPrMergeabilityFields, } from "./github-mergeability.js";
26
- import { makeLocalMergeExecutor, resolveLocalMergeMethod } from "./local-merge.js";
26
+ import { makeLocalMergeExecutor, resolveLocalMergeCredential, resolveLocalMergeMethod, } from "./local-merge.js";
27
27
  import { getHeadSha, getPrNumber } from "./event-accessors.js";
28
28
  import { emitConductorEventIfNew } from "./producer-ledger.js";
29
29
  import { rebuildObservedState, extractWorkerLiveness, } from "./epic-state.js";
@@ -54,13 +54,13 @@ const ACTIVE_WORKER_STATUSES = new Set(["dispatched", "running"]);
54
54
  * Source + producer tags for the durable `parse.triggered` marker that the
55
55
  * parse-after-merge wait emits from the epic-tick process.
56
56
  */
57
- const PARSE_WAIT_EVENT_SOURCE = "conductor-supervisor";
57
+ const PARSE_WAIT_EVENT_SOURCE = "epic-implementer-supervisor";
58
58
  const PARSE_WAIT_EVENT_PRODUCER = "epic-parse-wait";
59
59
  /**
60
60
  * BAPI-494: source + producer tags for the durable `merge.conflict` marker the
61
61
  * done-gate pass emits when a `ready_for_review` ticket's PR is un-mergeable.
62
62
  */
63
- const MERGE_CONFLICT_EVENT_SOURCE = "conductor-supervisor";
63
+ const MERGE_CONFLICT_EVENT_SOURCE = "epic-implementer-supervisor";
64
64
  const MERGE_CONFLICT_EVENT_PRODUCER = "epic-mergeability";
65
65
  function defaultLeaseOwner() {
66
66
  return `epic-tick-${process.pid}`;
@@ -403,7 +403,7 @@ export async function runConductorDoneGatePass(ticketStatuses, deps) {
403
403
  }
404
404
  // Stamp the ticket's run_id and (when available) worker_id onto the emitted
405
405
  // gate.met via a per-ticket env override (observePrCiOnce reads
406
- // BAPI_CONDUCTOR_RUN_ID/_WORKER_ID from env, env taking precedence). run_id
406
+ // BAPI_EPIC_IMPLEMENTER_RUN_ID/_WORKER_ID from env, env taking precedence). run_id
407
407
  // correlates the fold to the ticket. worker_id is attribution ONLY: BAPI-525
408
408
  // Change A removed the worker_id requirement from merge-identity extraction, so
409
409
  // a missing worker_id no longer blocks the merge — the backstop stamps real
@@ -456,8 +456,8 @@ export async function runConductorDoneGatePass(ticketStatuses, deps) {
456
456
  }
457
457
  const perTicketEnv = {
458
458
  ...deps.env,
459
- ...(runId ? { BAPI_CONDUCTOR_RUN_ID: runId } : {}),
460
- ...(workerId ? { BAPI_CONDUCTOR_WORKER_ID: workerId } : {}),
459
+ ...(runId ? { BAPI_EPIC_IMPLEMENTER_RUN_ID: runId } : {}),
460
+ ...(workerId ? { BAPI_EPIC_IMPLEMENTER_WORKER_ID: workerId } : {}),
461
461
  };
462
462
  try {
463
463
  const observeResult = await deps.observePrCi({
@@ -550,7 +550,7 @@ export async function runEpicTick(options, deps = {}) {
550
550
  // dispatch state. Without this guard, `correlateRunId` writes a `run_spawned` row
551
551
  // under the REAL dispatch_key, and the next real tick's `claimDispatchKey` returns
552
552
  // `already-spawned`, silently skipping the real worker spawn.
553
- const isDryRun = env.BAPI_CONDUCTOR_DISPATCH_DRY_RUN === "1";
553
+ const isDryRun = env.BAPI_EPIC_IMPLEMENTER_DISPATCH_DRY_RUN === "1";
554
554
  const startMs = nowFn();
555
555
  // ---------------------------------------------------------------------------
556
556
  // Step 0: Resolve Bridge API access (offline / fail-closed guard)
@@ -1320,7 +1320,16 @@ export async function runEpicTick(options, deps = {}) {
1320
1320
  merge: makeLocalMergeExecutor({
1321
1321
  method: resolveLocalMergeMethod(localCfg.method),
1322
1322
  approvalRequired: localCfg.approval_required === true,
1323
- }, { env: process.env }),
1323
+ },
1324
+ // BAPI-1136: `env` now supplies only the allowlisted
1325
+ // operational base; the identity is the explicitly configured
1326
+ // local credential, and an unconfigured one fails closed with
1327
+ // `local_merge_credential_missing` rather than borrowing the
1328
+ // ambient `gh` login this path used to rely on.
1329
+ {
1330
+ env: process.env,
1331
+ credential: resolveLocalMergeCredential(process.env, "local"),
1332
+ }),
1324
1333
  // BAPI-525 Change A: durable attribution for a worker_id-less gate.met.
1325
1334
  resolveWorkerIdForGateEvent,
1326
1335
  });
@@ -1736,12 +1745,12 @@ export async function buildProductionEpicRuntimeDeps(epicKey) {
1736
1745
  // The dispatch kind comes from the plan node's automation (start-tickets or
1737
1746
  // review-tickets); default to start-tickets when unspecified.
1738
1747
  const kind = automationMap.get(tk) ?? "start-tickets";
1739
- // Operator dry-run: when BAPI_CONDUCTOR_DISPATCH_DRY_RUN=1, dispatch resolves
1748
+ // Operator dry-run: when BAPI_EPIC_IMPLEMENTER_DISPATCH_DRY_RUN=1, dispatch resolves
1740
1749
  // the spawn command + model routing but opens NO terminal, creates NO worktree,
1741
1750
  // and opens NO PR (start-tickets/review-tickets dryRun). The full loop dispatch
1742
1751
  // path (ready-set → claim key → dispatch → correlate run_id) still exercises;
1743
1752
  // dry-run rows carry no runId, so a synthetic one is substituted for correlation.
1744
- const dispatchDryRun = process.env.BAPI_CONDUCTOR_DISPATCH_DRY_RUN === "1";
1753
+ const dispatchDryRun = process.env.BAPI_EPIC_IMPLEMENTER_DISPATCH_DRY_RUN === "1";
1745
1754
  // BAPI-507 (N-2): thread the ticket's declared file scope into the
1746
1755
  // IMPLEMENTATION dispatch identity only. A `review-tickets` node does not open
1747
1756
  // an implementation PR, so it gets no file-scope env (Step 8.5).
@@ -1850,11 +1859,11 @@ export async function buildProductionEpicRuntimeDeps(epicKey) {
1850
1859
  if (cachedPlanVersion === 0) {
1851
1860
  throw new Error(`dispatchReviewSeam called before fetchPlan for epic ${ek} ticket ${tk}; cachedPlanVersion is 0`);
1852
1861
  }
1853
- const dispatchDryRun = process.env.BAPI_CONDUCTOR_DISPATCH_DRY_RUN === "1";
1862
+ const dispatchDryRun = process.env.BAPI_EPIC_IMPLEMENTER_DISPATCH_DRY_RUN === "1";
1854
1863
  // Deliberately omit `dispatch_key` from the identity: the reconcile pass owns
1855
1864
  // the idempotent :review key claim (recordEpicDispatch with reviewRole) and the
1856
1865
  // run_spawned correlation. orchestrateReviewTickets still mints the run_id and
1857
- // injects BAPI_CONDUCTOR_RUN_ID into the review agent's environment, which is
1866
+ // injects BAPI_EPIC_IMPLEMENTER_RUN_ID into the review agent's environment, which is
1858
1867
  // exactly the correlation channel the Python review orchestrator reads to stamp
1859
1868
  // the spec_review.* verdict event with this review run's id (Phase 2).
1860
1869
  const identity = {
@@ -81,7 +81,7 @@ export class ConductorEpicTickV1FrozenError extends Error {
81
81
  *
82
82
  * Worker-facing ledger operations (`check_messages`, `wait_for_done_gate` event
83
83
  * emission) MUST execute through `conductor-bin.js` under the captured conductor
84
- * Node (`CONDUCTOR_NODE_PATH`) so the worker Node never loads the `better-sqlite3`
84
+ * Node (`EPIC_IMPLEMENTER_NODE_PATH`) so the worker Node never loads the `better-sqlite3`
85
85
  * native binary. When that runtime is missing or invalid, this error makes the
86
86
  * failure LOUD and structured rather than silently falling back to the worker
87
87
  * Node. The carried `reason`/`envVar` are the ONLY diagnostic surface — both are
@@ -240,8 +240,8 @@ export function toConductorErrorEnvelope(error) {
240
240
  message: "Conductor persistence is unavailable (the optional better-sqlite3 native module is not loaded). Conductor coordination features are disabled; core tools are unaffected.",
241
241
  };
242
242
  }
243
- // Worker-ledger subprocess runtime failure (BAPI-527): CONDUCTOR_NODE_PATH /
244
- // BAPI_CONDUCTOR_CLI_FILE is missing or invalid so the worker cannot reach the
243
+ // Worker-ledger subprocess runtime failure (BAPI-527): EPIC_IMPLEMENTER_NODE_PATH /
244
+ // BAPI_EPIC_IMPLEMENTER_CLI_FILE is missing or invalid so the worker cannot reach the
245
245
  // local ledger through the captured conductor Node. Surfaced as a retryable-
246
246
  // shaped 503 with a fixed, secret-free message plus a small non-secret details
247
247
  // bag (env_var + stable reason). NOTHING path/secret-bearing is echoed. This is
@@ -2,7 +2,7 @@
2
2
  * BAPI-507 (N-2): warn-only worker file-scope guard.
3
3
  *
4
4
  * Compares a branch's changed files against the planner-declared touched-file
5
- * set (delivered to the worker via `BAPI_CONDUCTOR_DECLARED_TOUCHED_FILES_JSON`)
5
+ * set (delivered to the worker via `BAPI_EPIC_IMPLEMENTER_DECLARED_TOUCHED_FILES_JSON`)
6
6
  * and warns when the diff strays outside that set. It is strictly warn-only /
7
7
  * fail-open: it NEVER blocks PR creation, mutates the branch, or exits non-zero.
8
8
  * A worker that implements a sibling's files (the N-2 over-reach observed in the
@@ -21,9 +21,9 @@
21
21
  */
22
22
  import { spawnSync } from "node:child_process";
23
23
  /** Env var carrying the compact JSON array of declared repo-relative paths. */
24
- export const DECLARED_TOUCHED_FILES_ENV = "BAPI_CONDUCTOR_DECLARED_TOUCHED_FILES_JSON";
24
+ export const DECLARED_TOUCHED_FILES_ENV = "BAPI_EPIC_IMPLEMENTER_DECLARED_TOUCHED_FILES_JSON";
25
25
  /** Env var carrying the dispatched ticket key (used only to label warnings). */
26
- export const FILE_SCOPE_GUARD_TICKET_KEY_ENV = "BAPI_CONDUCTOR_TICKET_KEY";
26
+ export const FILE_SCOPE_GUARD_TICKET_KEY_ENV = "BAPI_EPIC_IMPLEMENTER_TICKET_KEY";
27
27
  /** Base ref the branch diff is computed against. */
28
28
  export const FILE_SCOPE_GUARD_BASE_REF = "origin/main";
29
29
  /**
@@ -73,7 +73,7 @@ export function normalizeDeclaredTouchedFiles(list) {
73
73
  return Array.from(out).sort();
74
74
  }
75
75
  /**
76
- * Parse `BAPI_CONDUCTOR_DECLARED_TOUCHED_FILES_JSON` into a normalized
76
+ * Parse `BAPI_EPIC_IMPLEMENTER_DECLARED_TOUCHED_FILES_JSON` into a normalized
77
77
  * declaration. Returns an "unspecified" result on a missing, blank, invalid-JSON,
78
78
  * non-array, or empty (after normalization) value — the guard no-ops in every
79
79
  * such case.
@@ -155,7 +155,7 @@ export function stableJsonHash(value) {
155
155
  * The two literals are exported as named constants so no consumer spells them
156
156
  * inline — a typo in one consumer would otherwise silently disagree with the
157
157
  * parser about which disposition is configured. The Python mirror lives in
158
- * `api/library/epic_conductor/epic_implementer_readiness.py` and must carry the same
158
+ * `api/library/epic_implementer/epic_implementer_readiness.py` and must carry the same
159
159
  * closed set.
160
160
  */
161
161
  export const VERDICTLESS_DISPOSITION_PARK = "park";
@@ -72,7 +72,7 @@ export function sanitizeGitRemoteUrl(url) {
72
72
  /**
73
73
  * Resolve the local worktree context: worktree root, git common dir, current
74
74
  * branch, HEAD SHA, sanitized origin remote, and repo identity. Repo name prefers
75
- * `BAPI_CONDUCTOR_REPO_NAME`, then `BAPI_REPO_NAME`, then the git root basename.
75
+ * `BAPI_EPIC_IMPLEMENTER_REPO_NAME`, then `BAPI_REPO_NAME`, then the git root basename.
76
76
  * Never throws — missing git simply yields a degraded context.
77
77
  */
78
78
  export function getGitWorktreeContext(options = {}) {
@@ -86,7 +86,7 @@ export function getGitWorktreeContext(options = {}) {
86
86
  const branch = branchRaw === null || branchRaw === "HEAD" ? null : branchRaw;
87
87
  const headSha = normalizeSha(firstLine(runGitCommand(["rev-parse", "HEAD"], { cwd })) ?? "");
88
88
  const remoteOrigin = sanitizeGitRemoteUrl(firstLine(runGitCommand(["config", "--get", "remote.origin.url"], { cwd })) ?? "");
89
- const repo = normalizeRepoName(env.BAPI_CONDUCTOR_REPO_NAME) ??
89
+ const repo = normalizeRepoName(env.BAPI_EPIC_IMPLEMENTER_REPO_NAME) ??
90
90
  normalizeRepoName(env.BAPI_REPO_NAME) ??
91
91
  normalizeRepoName(basename(worktreePath)) ??
92
92
  "unknown";
@@ -36,7 +36,7 @@ import { buildConductorDoctorReport, formatConductorDoctorReport, } from "./doct
36
36
  import { inspectBridgeApiProfileToken, } from "../mcp-host-config.js";
37
37
  import { collectExecutorServiceDiagnostics, formatExecutorServiceDiagnosticsReport, } from "../doctor.js";
38
38
  import { collectInstallStatusChecks, formatInstallStatusReport, } from "../install-doctor.js";
39
- import { bringUpSafetySections, conductorHookTargetsSection, conductorLedgerLoadabilitySection, conductorProfileTokenSection, CONDUCTOR_PROFILE_TOKEN, detectConductorContext, executorObservationSection, executorProvisioningSection, executorServiceStateSection, githubActionsSection, githubCredentialsSection, inspectWorkflowPresence, reconcilerSection, supervisorSection, workflowSection, } from "./readiness-sections.js";
39
+ import { bringUpSafetySections, conductorHookTargetsSection, conductorLedgerLoadabilitySection, gitHubActionsMergeObservabilitySections, conductorProfileTokenSection, EPIC_IMPLEMENTER_PROFILE_TOKEN, detectConductorContext, executorObservationSection, executorProvisioningSection, executorServiceStateSection, githubActionsSection, mergeExecutionSections, githubCredentialsSection, inspectWorkflowPresence, reconcilerSection, supervisorSection, workflowSection, } from "./readiness-sections.js";
40
40
  import { ConductorBridgeApiError, fetchConductorReadiness, } from "./bridge-api-client.js";
41
41
  /**
42
42
  * Run one optional collector, containing any throw.
@@ -86,8 +86,8 @@ export async function runConductorInstallDoctor(deps) {
86
86
  const legacyConductor = conductorSettled.value ?? null;
87
87
  if (conductorSettled.failed) {
88
88
  sections.push({
89
- id: "conductor-ledger",
90
- label: "Conductor ledger doctor",
89
+ id: "epic-implementer-ledger",
90
+ label: "Epic Implementer ledger doctor",
91
91
  status: "degraded",
92
92
  detail: "the local epic-implementer doctor could not be built",
93
93
  remediation: "run `epic-implementer doctor` directly to see why the local ledger report failed.",
@@ -157,6 +157,13 @@ export async function runConductorInstallDoctor(deps) {
157
157
  sections.push(...supervisorSection(readiness));
158
158
  sections.push(githubCredentialsSection(readiness));
159
159
  sections.push(githubActionsSection(readiness));
160
+ // BAPI-1135 — the shared "Merge execution eligibility" section, immediately
161
+ // after the App permission row it is most often confused with, so the two
162
+ // write facts are read side by side. Built by `readiness-sections.ts` rather
163
+ // than formatted here, so this installer and the advisory gate render one
164
+ // classification; the installer's `settle`-based degraded isolation is
165
+ // unchanged, and no row here is `fatal`.
166
+ sections.push(...mergeExecutionSections(readiness));
160
167
  }
161
168
  const workflow = await inspectWorkflowPresence(deps.readWorkflowFile, deps.classifyWorkflowDrift);
162
169
  sections.push(workflowSection(workflow.presence, deps.reviewPolicySource, workflow.driftDetail));
@@ -219,7 +226,7 @@ export async function runConductorInstallDoctor(deps) {
219
226
  }));
220
227
  let profileToken = null;
221
228
  try {
222
- profileToken = await inspectProfile(deps.projectRoot ?? process.cwd(), CONDUCTOR_PROFILE_TOKEN);
229
+ profileToken = await inspectProfile(deps.projectRoot ?? process.cwd(), EPIC_IMPLEMENTER_PROFILE_TOKEN);
223
230
  }
224
231
  catch {
225
232
  // The shared inspector never throws for the ordinary absent/malformed
@@ -230,6 +237,13 @@ export async function runConductorInstallDoctor(deps) {
230
237
  sections.push(conductorProfileTokenSection(profileToken, conductorContext));
231
238
  sections.push(conductorHookTargetsSection(legacyConductor, conductorContext));
232
239
  sections.push(conductorLedgerLoadabilitySection(legacyConductor));
240
+ // BAPI-1135 — this HOST's ability to observe the merge capability, beside the
241
+ // other locally-derived doctor rows. Distinct from the server-fact
242
+ // "Merge execution eligibility" section pushed above: that one says whether
243
+ // the repository can merge, these two say whether this machine can look.
244
+ // `settle`-based degraded isolation is unchanged — a doctor that failed to
245
+ // collect yields two explicit unknown rows, never an omitted section.
246
+ sections.push(...gitHubActionsMergeObservabilitySections(legacyConductor));
233
247
  return {
234
248
  legacyConductor,
235
249
  legacyExecutorPreflight,
@@ -285,7 +299,7 @@ export function formatConductorInstallDoctorReport(report) {
285
299
  embed("Bridge install status", () => formatInstallStatusReport(report.legacyInstallChecks));
286
300
  }
287
301
  if (report.legacyConductor) {
288
- embed("Conductor ledger doctor", () => formatConductorDoctorReport(report.legacyConductor));
302
+ embed("Epic Implementer ledger doctor", () => formatConductorDoctorReport(report.legacyConductor));
289
303
  }
290
304
  if (report.legacyExecutorPreflight) {
291
305
  const p = report.legacyExecutorPreflight;
@@ -335,6 +349,14 @@ export function conductorInstallDoctorHasFatal(report) {
335
349
  // remediation constants, or the installer reporting APIs from
336
350
  // `conductor/install-doctor.js` keeps resolving exactly as before.
337
351
  // ---------------------------------------------------------------------------
338
- export { BRING_UP_SECTION_LABELS, bringUpSafetySections, databaseMigrationCurrentSection, singleTransitionAuthoritySection, workerPresentSection, CONDUCTOR_OPERATOR_RUNBOOK_POINTER, EXECUTOR_PROVISIONING_GUIDANCE, CONDUCTOR_PROFILE_TOKEN, CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION, CONDUCTOR_PROFILE_TOKEN_REMEDIATION, CONDUCTOR_HOOK_TARGET_REMEDIATION, CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION, EXECUTOR_INSTALL_SERVICE_REMEDIATION, EXECUTOR_SERVICE_START_REMEDIATION, } from "./readiness-sections.js";
352
+ export { BRING_UP_SECTION_LABELS, bringUpSafetySections,
353
+ // BAPI-1135 — re-exported on the compatibility surface like every other
354
+ // section builder, so an existing importer of this module sees the new
355
+ // section without learning a second import path.
356
+ mergeExecutionSections, databaseMigrationCurrentSection, singleTransitionAuthoritySection, workerPresentSection, CONDUCTOR_OPERATOR_RUNBOOK_POINTER, EXECUTOR_PROVISIONING_GUIDANCE, EPIC_IMPLEMENTER_PROFILE_TOKEN, CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION, CONDUCTOR_PROFILE_TOKEN_REMEDIATION, CONDUCTOR_HOOK_TARGET_REMEDIATION, CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION, EXECUTOR_INSTALL_SERVICE_REMEDIATION, EXECUTOR_SERVICE_START_REMEDIATION,
357
+ // BAPI-1135 — both new section builders join the compatibility surface like
358
+ // every other one, so an existing importer of this module does not learn a
359
+ // second import path for them.
360
+ gitHubActionsMergeObservabilitySections, } from "./readiness-sections.js";
339
361
  // BAPI-1153 — the bring-up remediations the three sections above render.
340
362
  export { BRING_UP_RUNBOOK, BRING_UP_UNREPORTED_REMEDIATION, DATABASE_MIGRATION_BEHIND_REMEDIATION, DATABASE_MIGRATION_UNREADABLE_REMEDIATION, SECOND_RECONCILER_REMEDIATION, WORKER_HEARTBEAT_UNREADABLE_REMEDIATION, WORKER_NOT_PRESENT_REMEDIATION, } from "./bring-up-facts.js";