@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
@@ -1,5 +1,5 @@
1
1
  /** The pinned operator runbook every remedy below points into. */
2
- export const BRING_UP_RUNBOOK = "docs/claude/epic-implementer-v2-operator-runbook.md";
2
+ export const BRING_UP_RUNBOOK = "docs/epic-implementer/operator-runbook.md";
3
3
  /**
4
4
  * The client-derived refusal vocabulary, IN REFUSAL ORDER.
5
5
  *
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Production boundaries for the pure command-drift probe (BAPI-1392).
3
+ *
4
+ * `command-drift.ts` is dependency-injected and imports no `fs` or
5
+ * `child_process`; this module is where those effects live. Two boundaries:
6
+ *
7
+ * - the Git boundary, a list-argument `git` runner (never a shell) that can pass
8
+ * the packaged UTF-8 bytes on stdin for `git hash-object --stdin`; and
9
+ * - the profile boundary, which resolves repo-scoped Bridge access through the
10
+ * shared credential resolver and reads the confirmed gate profile through the
11
+ * existing `fetchConductorGateProfile` — no second profile reader.
12
+ *
13
+ * Everything here is read-only. Raw Git output, error text and credentials are
14
+ * never surfaced: a failure is a thrown marker the probe maps to a closed reason.
15
+ */
16
+ import { spawnSync } from "node:child_process";
17
+ import { COMMANDS } from "../commands.generated.js";
18
+ import { probeCommandDrift, } from "./command-drift.js";
19
+ /** Bounded timeout for one Git subprocess. */
20
+ const GIT_TIMEOUT_MS = 5_000;
21
+ const BLOB_ID = /^[0-9a-f]{40}([0-9a-f]{24})?$/;
22
+ export function createGitRunner(cwd) {
23
+ return (args, input) => {
24
+ const result = spawnSync("git", args, {
25
+ cwd,
26
+ input,
27
+ encoding: "utf-8",
28
+ timeout: GIT_TIMEOUT_MS,
29
+ stdio: [input === undefined ? "ignore" : "pipe", "pipe", "ignore"],
30
+ });
31
+ if (result.error)
32
+ return { status: null, stdout: "" };
33
+ return { status: result.status, stdout: typeof result.stdout === "string" ? result.stdout : "" };
34
+ };
35
+ }
36
+ /** The Git boundary. Throws when Git is unavailable; "no tracked copy" is a value. */
37
+ export function createCommandDriftGit(run) {
38
+ let headState;
39
+ const ensureRepository = () => {
40
+ if (headState)
41
+ return headState;
42
+ const inside = run(["rev-parse", "--git-dir"]);
43
+ if (inside.status !== 0)
44
+ throw new Error("git-unavailable");
45
+ // A repository with no commit yet has no HEAD, so nothing is tracked at HEAD.
46
+ headState = run(["rev-parse", "--verify", "--quiet", "HEAD"]).status === 0 ? "commit" : "no-commit";
47
+ return headState;
48
+ };
49
+ return {
50
+ async trackedBlob(path) {
51
+ if (ensureRepository() === "no-commit")
52
+ return { tracked: false };
53
+ const result = run(["rev-parse", "--verify", "--quiet", `HEAD:${path}`]);
54
+ if (result.status === null)
55
+ throw new Error("git-unavailable");
56
+ const id = result.stdout.trim();
57
+ return result.status === 0 && BLOB_ID.test(id) ? { tracked: true, blobId: id } : { tracked: false };
58
+ },
59
+ async hashObject(content) {
60
+ ensureRepository();
61
+ const result = run(["hash-object", "--stdin"], content);
62
+ const id = result.stdout.trim();
63
+ if (result.status !== 0 || !BLOB_ID.test(id))
64
+ throw new Error("git-unavailable");
65
+ return id;
66
+ },
67
+ };
68
+ }
69
+ /**
70
+ * Build the production drift inspector: resolve Bridge access, read the confirmed
71
+ * profile's `customized_commands` (an unconfirmed repository has none), and probe
72
+ * Git. Never throws; an unresolved credential or failed read is a `warn`.
73
+ */
74
+ export function createCommandDriftInspector(options) {
75
+ return () => probeCommandDrift({
76
+ catalog: COMMANDS,
77
+ git: createCommandDriftGit(options.runGit ?? createGitRunner(options.cwd)),
78
+ fetchCustomizedCommands: async () => {
79
+ // Lazy: keeps the credential/HTTP graph out of the static imports, as the
80
+ // doctor's other credentialed inspections do.
81
+ const client = await import("./bridge-api-client.js");
82
+ const resolved = await client.resolveConductorBridgeApiAccess({
83
+ env: options.env,
84
+ cwd: options.cwd,
85
+ });
86
+ if (!resolved.ok)
87
+ throw new Error("profile-unavailable");
88
+ const read = await client.fetchConductorGateProfile(resolved.access, ((url, init) => (options.fetch ?? fetch)(url, init)));
89
+ return read.profile?.customized_commands ?? [];
90
+ },
91
+ });
92
+ }
@@ -0,0 +1,89 @@
1
+ /** Stable row id shared by `doctor` and `readiness`. */
2
+ export const COMMAND_DRIFT_ROW_ID = "command-drift";
3
+ export const COMMAND_DRIFT_ROW_LABEL = "Committed command drift";
4
+ /** Group-level remedy for divergent, non-customized commands. */
5
+ export const COMMAND_DRIFT_DIVERGENT_REMEDIATION = "run `/upgrade-bridge` and commit the refreshed commands, or mark the command customized in the gate profile";
6
+ /** Remedy when the check itself could not be completed. */
7
+ export const COMMAND_DRIFT_UNASSESSABLE_REMEDIATION = "restore Bridge profile access and Git access for this repository, then rerun `epic-implementer doctor`";
8
+ const SAFE_COMMAND_FILE = /^([a-z][a-z0-9-]*)\.md$/;
9
+ /** The repository-relative path of a packaged command's tracked copy. */
10
+ export function commandDriftTrackedPath(name) {
11
+ return `.claude/commands/${name}.md`;
12
+ }
13
+ /** Run the probe. Never throws and never returns a `fail`. */
14
+ export async function probeCommandDrift(deps) {
15
+ let customized;
16
+ try {
17
+ customized = new Set(await deps.fetchCustomizedCommands());
18
+ }
19
+ catch {
20
+ return { status: "warn", kind: "unassessable", reason: "profile-unavailable" };
21
+ }
22
+ const names = [];
23
+ for (const key of Object.keys(deps.catalog)) {
24
+ const match = SAFE_COMMAND_FILE.exec(key);
25
+ if (match)
26
+ names.push(match[1]);
27
+ }
28
+ names.sort();
29
+ const divergent = [];
30
+ const customizedDivergent = [];
31
+ try {
32
+ for (const name of names) {
33
+ const tracked = await deps.git.trackedBlob(commandDriftTrackedPath(name));
34
+ if (!tracked.tracked)
35
+ continue;
36
+ const packaged = await deps.git.hashObject(deps.catalog[`${name}.md`]);
37
+ if (packaged === tracked.blobId)
38
+ continue;
39
+ (customized.has(name) ? customizedDivergent : divergent).push(name);
40
+ }
41
+ }
42
+ catch {
43
+ return { status: "warn", kind: "unassessable", reason: "git-unavailable" };
44
+ }
45
+ if (divergent.length === 0)
46
+ return { status: "pass", customizedDivergent };
47
+ return { status: "warn", kind: "divergent", divergent, customizedDivergent };
48
+ }
49
+ function commandList(names) {
50
+ return names.map((n) => `/${n}`).join(", ");
51
+ }
52
+ /**
53
+ * The ONE projection of a probe result into a report row, shared by `doctor` and
54
+ * `readiness` so wording, ordering and remediation are decided once. The status
55
+ * vocabulary is the readiness one, and only `pass` or `warn` is ever produced.
56
+ */
57
+ export function projectCommandDriftRow(result) {
58
+ const base = { id: COMMAND_DRIFT_ROW_ID, label: COMMAND_DRIFT_ROW_LABEL };
59
+ if (result.status === "pass") {
60
+ return {
61
+ ...base,
62
+ status: "pass",
63
+ detail: "committed Bridge commands match the packaged copies" +
64
+ (result.customizedDivergent.length > 0
65
+ ? `; customized, not a warning: ${commandList(result.customizedDivergent)}`
66
+ : ""),
67
+ };
68
+ }
69
+ if (result.kind === "divergent") {
70
+ return {
71
+ ...base,
72
+ status: "warn",
73
+ detail: `divergent / likely stale: ${commandList(result.divergent)}` +
74
+ (result.customizedDivergent.length > 0
75
+ ? `; customized, not a warning: ${commandList(result.customizedDivergent)}`
76
+ : ""),
77
+ remediation: COMMAND_DRIFT_DIVERGENT_REMEDIATION,
78
+ };
79
+ }
80
+ const reason = result.reason === "profile-unavailable"
81
+ ? "the gate profile could not be read"
82
+ : "Git could not be inspected";
83
+ return {
84
+ ...base,
85
+ status: "warn",
86
+ detail: `Could not check command drift: ${reason}`,
87
+ remediation: COMMAND_DRIFT_UNASSESSABLE_REMEDIATION,
88
+ };
89
+ }
@@ -15,6 +15,7 @@ import { detectClaudeLogin, formatClaudeLoginAdvisory } from "../claude-login.js
15
15
  import { inspectConductorGitHooks } from "./git-hooks.js";
16
16
  import { MERGE_WORKFLOW_IDENTIFIER } from "./merge-execution-contract.js";
17
17
  import { resolveMcpShimInvocationForRuntime, resolvePackageRootFromModuleUrl, } from "../mcp-server-invocation.js";
18
+ import { projectCommandDriftRow } from "./command-drift.js";
18
19
  import { MCP_PACKAGE_NAME } from "../mcp-identity.js";
19
20
  import { resolveProfiles } from "../mcp-profile.js";
20
21
  import { createReadinessCheck, createReadinessCheckSafely, } from "../readiness-check.js";
@@ -694,6 +695,9 @@ export async function buildConductorDoctorReport(deps = {}) {
694
695
  homedir: deps.claudeLoginDeps?.homedir ?? os.homedir,
695
696
  readFile: deps.claudeLoginDeps?.readFile ?? ((p) => readFileAsync(p, "utf-8")),
696
697
  });
698
+ const command_drift = deps.inspectCommandDrift
699
+ ? await inspectCommandDriftSafe(deps.inspectCommandDrift)
700
+ : undefined;
697
701
  return {
698
702
  ledger,
699
703
  git_hooks: inspectHooks(deps.hooksDeps),
@@ -704,8 +708,18 @@ export async function buildConductorDoctorReport(deps = {}) {
704
708
  deny_enforcement,
705
709
  claude_login,
706
710
  repair_credentials: await inspectRepairVerbCredentials(deps.env ?? process.env, deps.resolveRepairAccess),
711
+ ...(command_drift ? { command_drift } : {}),
707
712
  };
708
713
  }
714
+ /** Run the drift inspector, containing any throw as an unassessable `warn`. */
715
+ async function inspectCommandDriftSafe(inspect) {
716
+ try {
717
+ return await inspect();
718
+ }
719
+ catch {
720
+ return { status: "warn", kind: "unassessable", reason: "git-unavailable" };
721
+ }
722
+ }
709
723
  /**
710
724
  * Run the GitHub Actions merge inspector, containing any throw as degraded data.
711
725
  *
@@ -822,9 +836,9 @@ export function formatConductorDoctorReport(report) {
822
836
  lines.push(` - ${w}`);
823
837
  }
824
838
  lines.push("");
825
- lines.push("Epic Conductor v2 reconciles epics server-side — nothing to schedule");
826
- lines.push("locally. To execute claimed jobs on this machine, run:");
827
- lines.push(` npx -y ${MCP_PACKAGE_NAME} executor --repo <name>`);
839
+ lines.push("The Epic Implementer reconciles epics server-side — nothing to schedule");
840
+ lines.push("locally. To execute a run's claimed jobs on this machine, run:");
841
+ lines.push(` npx -y ${MCP_PACKAGE_NAME} executor --repo <name> --epic-run-id <run-id>`);
828
842
  lines.push("");
829
843
  lines.push("MCP Profile (optional, local)");
830
844
  lines.push("─────────────────────────────");
@@ -940,6 +954,17 @@ export function formatConductorDoctorReport(report) {
940
954
  }
941
955
  lines.push("");
942
956
  lines.push(formatClaudeLoginAdvisory(claude_login));
957
+ // BAPI-1392 — the same projected row `readiness` shows, last in both reports.
958
+ // Warn-only: it never changes this command's exit code.
959
+ if (report.command_drift) {
960
+ const row = projectCommandDriftRow(report.command_drift);
961
+ lines.push("");
962
+ lines.push("Committed command drift (advisory)");
963
+ lines.push("──────────────────────────────────");
964
+ lines.push(`${row.id}: ${row.status === "pass" ? "[OK]" : "[WARNING]"} ${row.detail ?? ""}`);
965
+ if (row.remediation)
966
+ lines.push(` → ${row.remediation}`);
967
+ }
943
968
  return lines.join("\n");
944
969
  }
945
970
  // ---------------------------------------------------------------------------
@@ -1136,33 +1161,51 @@ export function mapConductorDoctorReportToReadinessChecks(report) {
1136
1161
  record(outcome);
1137
1162
  record(denyEnforcementOutcome(report));
1138
1163
  record(claudeLoginOutcome(report));
1139
- return CONDUCTOR_READINESS_DESCRIPTORS.map(({ id, label }) => {
1140
- const outcome = collected.get(id);
1141
- if (!outcome) {
1142
- // Unknown, and unknown is never healthy: a prerequisite whose owning
1143
- // inspection did not report is a failure with a restoring remediation.
1144
- return createReadinessCheck({
1164
+ // BAPI-1392 — appended AFTER the fixed descriptor set and only when the drift
1165
+ // inspection ran. It is deliberately not a descriptor: an uncollected
1166
+ // descriptor reports as a `fail`, and this row is warn-only by contract.
1167
+ const driftChecks = report?.command_drift
1168
+ ? (() => {
1169
+ const row = projectCommandDriftRow(report.command_drift);
1170
+ return [
1171
+ createReadinessCheckSafely({
1172
+ id: `conductor.${row.id}`,
1173
+ source: "conductor",
1174
+ label: row.label,
1175
+ status: row.status,
1176
+ ...(row.detail ? { detail: row.detail } : {}),
1177
+ ...(row.remediation ? { remediation: row.remediation } : {}),
1178
+ }),
1179
+ ];
1180
+ })()
1181
+ : [];
1182
+ return [...CONDUCTOR_READINESS_DESCRIPTORS.map(({ id, label }) => {
1183
+ const outcome = collected.get(id);
1184
+ if (!outcome) {
1185
+ // Unknown, and unknown is never healthy: a prerequisite whose owning
1186
+ // inspection did not report is a failure with a restoring remediation.
1187
+ return createReadinessCheck({
1188
+ id: `conductor.${id}`,
1189
+ source: "conductor",
1190
+ label,
1191
+ status: "fail",
1192
+ detail: CONDUCTOR_UNCOLLECTED_DETAIL,
1193
+ remediation: CONDUCTOR_UNCOLLECTED_REMEDIATION,
1194
+ });
1195
+ }
1196
+ return createReadinessCheckSafely({
1145
1197
  id: `conductor.${id}`,
1146
1198
  source: "conductor",
1147
- label,
1148
- status: "fail",
1149
- detail: CONDUCTOR_UNCOLLECTED_DETAIL,
1150
- remediation: CONDUCTOR_UNCOLLECTED_REMEDIATION,
1199
+ label: outcome.label || label,
1200
+ status: outcome.status,
1201
+ ...(outcome.detail ? { detail: outcome.detail } : {}),
1202
+ // Same fallback as the plane adapter: a real failure must never be
1203
+ // downgraded into a generic "unreadable check" for want of a fix line.
1204
+ ...(outcome.status === "fail"
1205
+ ? { remediation: outcome.remediation ?? CONDUCTOR_UNCOLLECTED_REMEDIATION }
1206
+ : outcome.status !== "pass" && outcome.remediation
1207
+ ? { remediation: outcome.remediation }
1208
+ : {}),
1151
1209
  });
1152
- }
1153
- return createReadinessCheckSafely({
1154
- id: `conductor.${id}`,
1155
- source: "conductor",
1156
- label: outcome.label || label,
1157
- status: outcome.status,
1158
- ...(outcome.detail ? { detail: outcome.detail } : {}),
1159
- // Same fallback as the plane adapter: a real failure must never be
1160
- // downgraded into a generic "unreadable check" for want of a fix line.
1161
- ...(outcome.status === "fail"
1162
- ? { remediation: outcome.remediation ?? CONDUCTOR_UNCOLLECTED_REMEDIATION }
1163
- : outcome.status !== "pass" && outcome.remediation
1164
- ? { remediation: outcome.remediation }
1165
- : {}),
1166
- });
1167
- });
1210
+ }), ...driftChecks];
1168
1211
  }