@bridge_gpt/mcp-server 0.2.49 → 0.2.51

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 (62) hide show
  1. package/README.md +25 -8
  2. package/build/base-ref.js +28 -3
  3. package/build/claude-review-workflow-drift-probe.js +130 -0
  4. package/build/claude-review-workflow-drift.js +173 -0
  5. package/build/claude-review-workflow.js +81 -16
  6. package/build/commands.generated.js +5 -5
  7. package/build/conduct-epic/bridge-client.js +115 -1
  8. package/build/conduct-epic/cli.js +351 -33
  9. package/build/conduct-epic/cut-protocol.js +51 -0
  10. package/build/conductor/done-gate.js +25 -3
  11. package/build/conductor/install-doctor.js +65 -5
  12. package/build/conductor/latest-check-selector.js +170 -0
  13. package/build/conductor/local-merge.js +8 -6
  14. package/build/conductor-bin.js +1 -1
  15. package/build/{brainstorm-files.js → council-files.js} +15 -15
  16. package/build/decision-page-schema.js +1 -1
  17. package/build/docs.generated.js +1 -1
  18. package/build/doctor.js +352 -4
  19. package/build/epic-integration-pr.js +280 -0
  20. package/build/executor/job-runner.js +7 -1
  21. package/build/executor/merge-job.js +46 -1
  22. package/build/executor/worktree.js +46 -1
  23. package/build/index.js +153 -65
  24. package/build/init.js +9 -2
  25. package/build/install-bridge.js +60 -2
  26. package/build/install-reexec.js +47 -9
  27. package/build/pipelines.generated.js +8 -2
  28. package/build/plan-epic-conductor-eligibility.js +183 -0
  29. package/build/plane/cli.js +12 -2
  30. package/build/plane/manifest.js +25 -1
  31. package/build/plane/member-roster.js +61 -7
  32. package/build/plane/preflight.js +24 -9
  33. package/build/plane/supervisor.js +77 -5
  34. package/build/plane/types.js +23 -3
  35. package/build/readme.generated.js +1 -1
  36. package/build/run-unit-tests-launcher.js +2 -1
  37. package/build/setup-epic.js +32 -0
  38. package/build/sfcc/reads-custom-object-def.js +10 -13
  39. package/build/sfcc/reads-site-preference.js +5 -5
  40. package/build/sfcc/reads-system-object.js +4 -4
  41. package/build/sfcc/writes-custom-object-def.js +7 -7
  42. package/build/sfcc/writes-site-preference.js +4 -3
  43. package/build/sfcc/writes-system-object.js +7 -6
  44. package/build/stale-worktree-doctor.js +120 -0
  45. package/build/start-tickets-prereqs.js +70 -0
  46. package/build/start-tickets.js +91 -3
  47. package/build/version.generated.js +3 -2
  48. package/package.json +6 -3
  49. package/pipelines/plan-epic.json +5 -0
  50. package/build/chain-orchestrator.js +0 -1457
  51. package/build/chain-utils.js +0 -68
  52. package/build/command-catalog.js +0 -376
  53. package/build/schedule-run.js +0 -1300
  54. package/build/schedule-store.js +0 -172
  55. package/build/scheduled-prompt.js +0 -115
  56. package/build/scheduler-backends/at-fallback.js +0 -139
  57. package/build/scheduler-backends/escaping.js +0 -143
  58. package/build/scheduler-backends/index.js +0 -72
  59. package/build/scheduler-backends/launchd.js +0 -225
  60. package/build/scheduler-backends/systemd-user.js +0 -250
  61. package/build/scheduler-backends/task-scheduler.js +0 -214
  62. package/build/scheduler-backends/types.js +0 -23
@@ -28,7 +28,7 @@
28
28
  * No MCP tool is registered from this module — the `tools/list` token budget is
29
29
  * effectively frozen.
30
30
  */
31
- import { buildConductorJiraUrl, fetchConductorJsonPostWithTimeout, fetchConductorJsonPutWithTimeout, fetchConductorJsonWithTimeout, fetchConductorReadiness, fetchEffectiveSupervisorConfig, fetchEffectiveSupervisorSetup, fetchEpicRunState, fetchParseStatus, fetchPrReviewStatus, pollCiChecksForCommit, ConductorBridgeApiError, CONDUCTOR_FETCH_TIMEOUT_MS, } from "../conductor/bridge-api-client.js";
31
+ import { buildConductorJiraUrl, buildConductorVcsUrl, fetchConductorJsonPostWithTimeout, fetchConductorJsonPutWithTimeout, fetchConductorJsonWithTimeout, fetchConductorReadiness, fetchEffectiveSupervisorConfig, fetchEffectiveSupervisorSetup, fetchEpicRunState, fetchParseStatus, fetchPrReviewStatus, pollCiChecksForCommit, ConductorBridgeApiError, CONDUCTOR_FETCH_TIMEOUT_MS, } from "../conductor/bridge-api-client.js";
32
32
  /**
33
33
  * The one message returned for any failure whose cause cannot be described
34
34
  * without risking the credential. Stable so callers can match on it.
@@ -657,3 +657,117 @@ export async function reclaimIndexScope(access, request, fetchImpl = globalThis.
657
657
  },
658
658
  };
659
659
  }
660
+ /**
661
+ * Epic-run statuses that mean a v2 conductor may still be driving the run.
662
+ *
663
+ * These are the NON-TERMINAL members of the server's `EpicRunStatus` vocabulary
664
+ * (`api/models/epic_run.py`: `planning | pending_approval | active | blocked |
665
+ * abandoned | done`); only `abandoned` and `done` are terminal. `active` is the
666
+ * state a run spends nearly all of its life in, so omitting it would make this
667
+ * whole advisory silent for exactly the overlap it exists to surface.
668
+ *
669
+ * The vocabulary matters and is easy to get wrong: `running`/`queued` belong to
670
+ * `ExecutorJobStatusValue` and `paused` to `RunControlState`, and none of the
671
+ * three is ever an `epic_runs.status`. Status alone is not liveness either — the
672
+ * caller additionally requires an unexpired lease, so a `blocked` run whose lease
673
+ * has lapsed is correctly read as wreckage rather than as a live conductor.
674
+ */
675
+ const ACTIVE_EPIC_RUN_STATUSES = [
676
+ "planning",
677
+ "pending_approval",
678
+ "active",
679
+ "blocked",
680
+ ];
681
+ /**
682
+ * `GET /automation/health?repo_name=` — read-only parse-dispatcher liveness.
683
+ *
684
+ * Root-mounted, NOT under `/jira`. The response is narrowed to two safe fields;
685
+ * signals, stale-ticket samples, queue contents, and every timestamp are
686
+ * deliberately dropped — an advisory line needs a verdict, not a report.
687
+ *
688
+ * `absent` is claimed ONLY on positive evidence: a `stale` or `never_seen`
689
+ * heartbeat together with a responding process that is not itself sweeping.
690
+ * Every other shape — `unknown`, a missing field, a malformed body, any read
691
+ * failure — is `unavailable`.
692
+ */
693
+ export async function getParseDispatcherHealth(access, fetchImpl = globalThis.fetch) {
694
+ const result = await wrap(access, () => {
695
+ const url = new URL(buildConductorVcsUrl(access.baseUrl, "/automation/health"));
696
+ url.searchParams.set("repo_name", access.repoName);
697
+ return fetchConductorJsonWithTimeout(url.toString(), getHeaders(access), CONDUCTOR_FETCH_TIMEOUT_MS, fetchImpl);
698
+ });
699
+ if (!result.ok)
700
+ return result;
701
+ if (!isRecord(result.value)) {
702
+ return {
703
+ ok: true,
704
+ value: { observation: "unavailable", heartbeatState: null, respondingSchedulerRunning: false },
705
+ };
706
+ }
707
+ const reconciler = isRecord(result.value["reconciler"]) ? result.value["reconciler"] : null;
708
+ const scheduler = isRecord(result.value["scheduler"]) ? result.value["scheduler"] : null;
709
+ const rawState = reconciler === null ? undefined : reconciler["state"];
710
+ const heartbeatState = typeof rawState === "string" ? rawState : null;
711
+ const respondingSchedulerRunning = scheduler !== null &&
712
+ scheduler["running"] === true &&
713
+ typeof scheduler["job_count"] === "number" &&
714
+ scheduler["job_count"] > 0;
715
+ let observation;
716
+ if (heartbeatState === "fresh" || respondingSchedulerRunning) {
717
+ observation = "observed";
718
+ }
719
+ else if (heartbeatState === "stale" || heartbeatState === "never_seen") {
720
+ observation = "absent";
721
+ }
722
+ else {
723
+ observation = "unavailable";
724
+ }
725
+ return { ok: true, value: { observation, heartbeatState, respondingSchedulerRunning } };
726
+ }
727
+ /**
728
+ * `GET /jira/epic-runs/runs?repo_name=` — live v2 conductor runs on THIS repo.
729
+ *
730
+ * Scoped by the authenticated repository identity carried on `access`; no caller
731
+ * ever names a repository here. Liveness is judged on the LEASE, not on the
732
+ * status alone: an `active` row whose lease expired is a crashed run, and calling
733
+ * that a concurrent conductor would make the advisory cry wolf on exactly the
734
+ * wreckage `recover` exists to clean up.
735
+ *
736
+ * Only `epic_key` and a controlled state survive into the result. Lease owners,
737
+ * run ids, policies, and timestamps are dropped.
738
+ */
739
+ export async function getLiveRepositoryConductors(access, now, fetchImpl = globalThis.fetch) {
740
+ const result = await wrap(access, () => {
741
+ const url = buildConductorJiraUrl(access.baseUrl, "/epic-runs/runs", {
742
+ repo_name: access.repoName,
743
+ });
744
+ return fetchConductorJsonWithTimeout(url, getHeaders(access), CONDUCTOR_FETCH_TIMEOUT_MS, fetchImpl);
745
+ });
746
+ if (!result.ok)
747
+ return result;
748
+ if (!isRecord(result.value) || !Array.isArray(result.value["runs"])) {
749
+ return { ok: true, value: { observation: "unavailable", conductors: [] } };
750
+ }
751
+ const nowMs = now.getTime();
752
+ const conductors = [];
753
+ for (const entry of result.value["runs"]) {
754
+ if (!isRecord(entry))
755
+ continue;
756
+ const status = entry["status"];
757
+ if (typeof status !== "string" || !ACTIVE_EPIC_RUN_STATUSES.includes(status))
758
+ continue;
759
+ const leaseRaw = nullableString(entry["lease_expires_at"]);
760
+ if (typeof leaseRaw !== "string")
761
+ continue;
762
+ const leaseMs = Date.parse(leaseRaw);
763
+ if (!Number.isFinite(leaseMs) || leaseMs <= nowMs)
764
+ continue;
765
+ conductors.push({
766
+ kind: "v2",
767
+ epicKey: nullableString(entry["epic_key"]) ?? null,
768
+ state: status,
769
+ livenessSource: "lease",
770
+ });
771
+ }
772
+ return { ok: true, value: { observation: conductors.length > 0 ? "observed" : "absent", conductors } };
773
+ }