@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
@@ -1,32 +1,29 @@
1
1
  /**
2
2
  * `drive-epic` — the one universal conductor entry point (BAPI-887).
3
3
  *
4
- * Bridge has two conductors and a standing rule that they must never operate on
5
- * the same epic: two transition authorities on one epic wedge it permanently.
6
- *
7
- * - **v2 engine** — bootstrapped by `setup-epic`, which creates a durable
8
- * `epic_run` row, stores a plan DAG, and approves it.
9
- * - **LLM-conductor pilot** — `/loop 5m /conduct-epic <EPIC>`, which creates no
10
- * run row and keeps its whole memory in a local checkpoint plus GitHub.
4
+ * Bridge has one conductor — the **v2 engine**, bootstrapped by `setup-epic`,
5
+ * which creates a durable `epic_run` row, stores a plan DAG, and approves it. The
6
+ * standing rule is that exactly one transition authority ever operates on an
7
+ * epic: two authorities on one epic wedge it permanently.
11
8
  *
12
9
  * Asking a prompt to pick correctly every time is not a control. This subcommand
13
10
  * makes the choice STRUCTURAL: it reads server-side conductor readiness and
14
- * routes to exactly one path, so no prompt names either underlying conductor and
15
- * no prompt can present both. Every ticket-authoring surface hands off to
16
- * `drive-epic` and to nothing else.
11
+ * routes to exactly one path, so no prompt names the underlying conductor. Every
12
+ * ticket-authoring surface hands off to `drive-epic` and to nothing else.
17
13
  *
18
14
  * ## The output invariant
19
15
  *
20
16
  * Every branch — including every error path — emits **at most one** conductor
21
- * invocation. An escalation carries NO alternative conductor command: "v2 failed,
22
- * try the pilot instead" is precisely the dual-authority hazard this subcommand
23
- * exists to remove. {@link assertSingleConductorInvocation} enforces this on the
24
- * way out rather than trusting each branch to have got it right.
17
+ * invocation. A not-ready result or an escalation carries NO alternative
18
+ * conductor command: "v2 failed, try something else instead" is precisely the
19
+ * dual-authority hazard this subcommand exists to remove.
20
+ * {@link assertSingleConductorInvocation} enforces this on the way out rather than
21
+ * trusting each branch to have got it right.
25
22
  *
26
23
  * ## Three-state routing, fail-closed
27
24
  *
28
25
  * - readiness green -> delegate to the `setup-epic` (v2) flow
29
- * - readiness read, not green -> print the pilot instruction
26
+ * - readiness read, not green -> report v2 not-ready, offer no alternative
30
27
  * - readiness UNKNOWN -> escalate to the operator, print no conductor
31
28
  *
32
29
  * Unknown is never treated as not-ready, and selection never happens by
@@ -72,17 +69,16 @@ import { validateBranchName } from "./base-ref.js";
72
69
  // BAPI-806: mcp-identity.ts is the SOLE source of the package-name literal, so
73
70
  // the printed invocation interpolates it rather than repeating it.
74
71
  import { MCP_PACKAGE_NAME } from "./mcp-identity.js";
75
- /** Jira epic key shape. Matches `implement-epic`'s positional rule exactly. */
72
+ /** Jira epic key shape. Matches the epic-key positional rule exactly. */
76
73
  const EPIC_KEY_PATTERN = /^[A-Z]+-[0-9]+$/;
77
- /** The two conductor paths. Derived types below come from this constant. */
78
- export const DRIVE_EPIC_CONDUCTORS = ["v2", "pilot"];
74
+ /** The conductor paths. Derived types below come from this constant. */
75
+ export const DRIVE_EPIC_CONDUCTORS = ["v2"];
79
76
  /**
80
- * THE consolidation-day edit point.
77
+ * The preferred conductor.
81
78
  *
82
- * When readiness is green, v2 is preferred and the pilot is the fallback for
83
- * projects that cannot run it. This is expressed as one named constant rather
84
- * than as branching scattered through the routing logic precisely so that
85
- * eliminating a conductor is a one-line change plus one deleted branch.
79
+ * v2 is the only conductor: when readiness is green it drives the epic, and when
80
+ * it is not the command reports v2 not-ready with no alternative. Expressed as
81
+ * one named constant rather than branching scattered through the routing logic.
86
82
  */
87
83
  export const DRIVE_EPIC_PREFERRED_CONDUCTOR = "v2";
88
84
  /**
@@ -165,6 +161,29 @@ export const V2_READINESS_REQUIREMENTS = [
165
161
  remedy: "Run `install-bridge conductor` to install them, or pass --attended.",
166
162
  satisfied: (r) => r.unattended?.repository_readiness_confirmed === true,
167
163
  },
164
+ // BAPI-1135 — merge-execution eligibility is deliberately NOT a requirement here.
165
+ //
166
+ // It was one, and it made `drive-epic` refuse EVERY repository the moment it
167
+ // shipped. The requirement could only be keyed on repository facts, because
168
+ // this layer keeps the composed run policy opaque to itself — and no
169
+ // repository carries the merge workflow until epic child 4 lands it. So both
170
+ // states resolved the same way: an upgraded server reported
171
+ // `merge_workflow_present: false` (`not_eligible`), an older one reported no
172
+ // block at all (`could_not_verify`), and either made `selectConductor` return
173
+ // `not_ready` and `classifyV2Readiness` return `operator_blocked` — for
174
+ // `--attended`, `--into-base` and `local`-mode runs alike, with a remedy
175
+ // naming a flag that does not exist yet.
176
+ //
177
+ // That is exactly the failure `selectConductor`'s own docstring warns about,
178
+ // and it contradicts the compatibility guarantee the rest of this slice keeps:
179
+ // nothing changes for a run that does not declare `github_actions`.
180
+ //
181
+ // Eligibility is still enforced, at the three layers that can actually see the
182
+ // declared mode: `setup-epic`'s pre-create refusal (which reads the composed
183
+ // policy), the approval route's server-side gate, and — authoritatively — the
184
+ // before-merge preflight. Readiness still REPORTS the facts as diagnostic
185
+ // rows, which inform without blocking. Reinstating a requirement here belongs
186
+ // with child 4, once a repository can actually satisfy it.
168
187
  ];
169
188
  /**
170
189
  * The readiness facts a `plane up` can actually repair (BAPI-1054).
@@ -482,10 +501,10 @@ export function parseDriveEpicArgs(argv) {
482
501
  * v2 engine drive an epic at all?", and the answer does not depend on whether
483
502
  * the repository has consented to UNATTENDED operation: an attended v2 run on a
484
503
  * non-consenting repository is a perfectly ordinary, fully supported run.
485
- * Including them would route every such repository to the pilot conductor the
486
- * moment this ticket deployed — a silent, repository-wide change of conductor for
487
- * a reason that has nothing to do with the choice, and the exact opposite of
488
- * AC-3's "nothing changes for an existing run".
504
+ * Including them would report v2 not-ready for every such repository the moment
505
+ * this ticket deployed — a silent, repository-wide refusal for a reason that has
506
+ * nothing to do with readiness, and the exact opposite of AC-3's "nothing
507
+ * changes for an existing run".
489
508
  *
490
509
  * They still gate the COMPOSED bring-up, through
491
510
  * {@link classifyV2Readiness}, which is where an unattended run is actually
@@ -501,8 +520,7 @@ export function selectConductor(readiness) {
501
520
  };
502
521
  }
503
522
  return {
504
- kind: "selected",
505
- conductor: "pilot",
523
+ kind: "not_ready",
506
524
  reason: `the engine path still needs ${missing.map((m) => m.describe).join("; ")}`,
507
525
  };
508
526
  }
@@ -536,51 +554,35 @@ export function buildSetupEpicArgv(options) {
536
554
  ];
537
555
  }
538
556
  /**
539
- * Render the selected path and only the selected path.
540
- *
541
- * Precondition: the caller has already ruled out delegation. The `v2` branch
542
- * reads as "green, but no plan file was supplied", which is only true once
543
- * {@link runDriveEpicCli} has declined to delegate — so route first, render
544
- * second.
557
+ * Render the selected v2 path and only that path.
545
558
  *
546
- * CONSOLIDATION DAY: delete the branch of the conductor being eliminated and
547
- * point {@link DRIVE_EPIC_PREFERRED_CONDUCTOR} at the survivor. Nothing outside
548
- * this file moves.
559
+ * Precondition: the caller has already ruled out delegation and a not-ready
560
+ * result. The `v2` branch reads as "green, but no plan file was supplied", which
561
+ * is only true once {@link runDriveEpicCli} has declined to delegate — so route
562
+ * first, render second.
549
563
  */
550
564
  export function renderConductorHandoff(selection, epicKey) {
551
- if (selection.conductor === "v2") {
552
- const invocation = `npx -y ${MCP_PACKAGE_NAME} drive-epic ${epicKey} --plan-file <path>`;
553
- return {
554
- conductor: "v2",
555
- invocation,
556
- lines: [
557
- `${epicKey}: ${selection.reason}, but no plan file was supplied.`,
558
- "",
559
- "The engine path needs a plan DAG, and nothing derives one from an epic key:",
560
- "the dependency edges and per-ticket touched_files it carries do not exist",
561
- "anywhere else. Produce one, then re-run this command with it.",
562
- "",
563
- ` 1. Run /plan-epic ${epicKey} in an interactive session. It writes the`,
564
- " sidecar to {docs_dir}/epic-plans/{epic_slug}/epic-plan.dag.json.",
565
- " If the epic's tickets already exist, run emit-epic-implementer-bundle",
566
- " finalize instead — it resolves the placeholder keys in an existing",
567
- " sidecar and attaches touched_files.",
568
- "",
569
- ` 2. ${invocation}`,
570
- "",
571
- `That second command bootstraps the run for you; ${SETUP_EPIC_SUBCOMMAND} is not`,
572
- "something you invoke directly.",
573
- ],
574
- };
575
- }
576
- const invocation = `/loop 5m /conduct-epic ${epicKey}`;
565
+ const invocation = `npx -y ${MCP_PACKAGE_NAME} drive-epic ${epicKey} --plan-file <path>`;
577
566
  return {
578
- conductor: "pilot",
567
+ conductor: "v2",
579
568
  invocation,
580
569
  lines: [
581
- `${epicKey}: ${selection.reason}. Drive it from an interactive session with:`,
570
+ `${epicKey}: ${selection.reason}, but no plan file was supplied.`,
571
+ "",
572
+ "The engine path needs a plan DAG, and nothing derives one from an epic key:",
573
+ "the dependency edges and per-ticket touched_files it carries do not exist",
574
+ "anywhere else. Produce one, then re-run this command with it.",
582
575
  "",
583
- ` ${invocation}`,
576
+ ` 1. Run /plan-epic ${epicKey} in an interactive session. It writes the`,
577
+ " sidecar to {docs_dir}/epic-plans/{epic_slug}/epic-plan.dag.json.",
578
+ " If the epic's tickets already exist, run emit-epic-implementer-bundle",
579
+ " finalize instead — it resolves the placeholder keys in an existing",
580
+ " sidecar and attaches touched_files.",
581
+ "",
582
+ ` 2. ${invocation}`,
583
+ "",
584
+ `That second command bootstraps the run for you; ${SETUP_EPIC_SUBCOMMAND} is not`,
585
+ "something you invoke directly.",
584
586
  ],
585
587
  };
586
588
  }
@@ -589,7 +591,7 @@ export function renderConductorHandoff(selection, epicKey) {
589
591
  * output guard and by its test — one list, so a new spelling cannot be added to
590
592
  * the renderer without the guard seeing it.
591
593
  */
592
- export const CONDUCTOR_INVOCATION_TOKENS = ["setup-epic", "conduct-epic"];
594
+ export const CONDUCTOR_INVOCATION_TOKENS = ["setup-epic"];
593
595
  /** The v2 token, named once so prose and the guard cannot drift apart. */
594
596
  const SETUP_EPIC_SUBCOMMAND = CONDUCTOR_INVOCATION_TOKENS[0];
595
597
  /**
@@ -935,9 +937,9 @@ export async function runDriveEpicCli(argv, overrides = {}) {
935
937
  //
936
938
  // BAPI-1054: a supplied plan file is what makes this a BRING-UP decision
937
939
  // rather than a routing one. Everything below runs before `selectConductor`'s
938
- // pilot fallback can be rendered, because a report that is non-green only on
939
- // the runtime facts is not a "use the other conductor" situation — it is a
940
- // plane that has not been started yet.
940
+ // not-ready result can be rendered, because a report that is non-green only on
941
+ // the runtime facts is not a "v2 cannot run" situation — it is a plane that
942
+ // has not been started yet.
941
943
  if (planFile) {
942
944
  // BAPI-1102 — the explicit `--attended` opt-out makes the unattended
943
945
  // prerequisites inapplicable. Both inputs are FLAG checks, not policy
@@ -1061,6 +1063,21 @@ export async function runDriveEpicCli(argv, overrides = {}) {
1061
1063
  awaitPlaneReady: controlPlane.awaitPlaneReady,
1062
1064
  });
1063
1065
  }
1066
+ // No plan file, and readiness is not green: v2 is not ready and there is no
1067
+ // second conductor to offer. Report it as a not-ready refusal on stderr with
1068
+ // exactly one — actually zero — conductor invocation, and a non-zero exit.
1069
+ if (selection.kind === "not_ready") {
1070
+ const refusal = [
1071
+ `${epicKey}: ${selection.reason}.`,
1072
+ "",
1073
+ "The v2 engine is not ready to drive this epic, and there is no alternative",
1074
+ "conductor to fall back to. Resolve conductor readiness (`install-bridge",
1075
+ "conductor`, then `doctor`) and run drive-epic again.",
1076
+ ].join("\n");
1077
+ assertSingleConductorInvocation(refusal);
1078
+ deps.errorLog(refusal);
1079
+ return 1;
1080
+ }
1064
1081
  const handoff = renderConductorHandoff(selection, epicKey);
1065
1082
  const text = handoff.lines.join("\n");
1066
1083
  assertSingleConductorInvocation(text);