@bridge_gpt/mcp-server 0.2.62 → 0.2.66
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.
- package/README.md +66 -15
- package/build/agent-launchers/claude-executor-adapter.js +145 -20
- package/build/agent-launchers/executor-adapter.js +81 -2
- package/build/agents.generated.js +10 -1
- package/build/bounded-wait.js +32 -1
- package/build/bridge-config.js +104 -0
- package/build/codex-bridge-profile.js +10 -1
- package/build/commands.generated.js +7 -6
- package/build/conductor/bridge-api-client.js +565 -32
- package/build/conductor/bring-up-facts.js +3 -1
- package/build/conductor/doctor.js +23 -14
- package/build/conductor/epic-child-continuation.js +351 -0
- package/build/conductor/epic-implementer-cli.js +154 -17
- package/build/conductor/git-hooks.js +529 -118
- package/build/conductor/guided-repair.js +323 -0
- package/build/conductor/hook-runtime-qualification.js +340 -0
- package/build/conductor/readiness-cli.js +30 -9
- package/build/conductor/readiness-sections.js +5 -4
- package/build/conductor/readiness.js +45 -12
- package/build/conductor/recovery-cli.js +859 -27
- package/build/conductor/recovery-operations.js +574 -5
- package/build/conductor/repair-contract.js +69 -3
- package/build/conductor-bundle-artifacts.js +1 -0
- package/build/credential-store.js +52 -13
- package/build/diagnostic-text.js +36 -0
- package/build/docs.generated.js +3 -2
- package/build/doctor.js +147 -21
- package/build/drive-epic-key.js +12 -0
- package/build/drive-epic.js +1537 -125
- package/build/epic-coherence-input-cli.js +137 -0
- package/build/epic-coherence-input.js +920 -0
- package/build/epic-coherence-input.test-fixtures.js +175 -0
- package/build/epic-implementer-bin.js +41 -33
- package/build/epic-implementer-bundle-cli.js +14 -1
- package/build/epic-launch-diagnostic.js +31 -0
- package/build/epic-launch-profile.js +58 -19
- package/build/epic-run-status.js +5 -0
- package/build/epic-shared/bridge-client.js +46 -4
- package/build/executor/cli.js +39 -0
- package/build/executor/completion-contract.js +423 -0
- package/build/executor/completion-supervision.js +291 -0
- package/build/executor/correction-dispatch.js +60 -0
- package/build/executor/credentials.js +3 -1
- package/build/executor/deps.js +65 -1
- package/build/executor/env.js +12 -0
- package/build/executor/heartbeat.js +13 -3
- package/build/executor/http-client.js +91 -4
- package/build/executor/integration-job.js +6 -1
- package/build/executor/job-errors.js +61 -4
- package/build/executor/job-log-registry.js +340 -73
- package/build/executor/job-runner.js +1550 -55
- package/build/executor/job-types.js +9 -6
- package/build/executor/preflight.js +189 -1
- package/build/executor/process-containment.js +756 -0
- package/build/executor/process.js +235 -5
- package/build/executor/prompt-spec.js +366 -1
- package/build/executor/provider-checks.js +69 -0
- package/build/executor/rebase-finalization.js +351 -0
- package/build/executor/reconcile-overlap-job.js +77 -84
- package/build/executor/required-verification.js +313 -0
- package/build/executor/required-work-ledger.js +1121 -0
- package/build/executor/results.js +142 -0
- package/build/executor/resume-pre-spawn.js +87 -4
- package/build/executor/runner.js +168 -0
- package/build/executor/stale-artifacts.js +5 -4
- package/build/executor/test-declaration.js +20 -0
- package/build/executor/types.js +13 -0
- package/build/executor/watch-cli.js +35 -8
- package/build/executor/worker-command.js +70 -34
- package/build/executor/worker-finalization.js +168 -26
- package/build/executor/worker-guard-hook.js +75 -14
- package/build/executor/worker-log.js +137 -70
- package/build/executor/worktree-gc.js +30 -6
- package/build/executor/worktree.js +13 -0
- package/build/executor-launch.js +658 -0
- package/build/index.js +594 -1152
- package/build/init.js +107 -4
- package/build/install-bridge-conductor.js +231 -41
- package/build/install-bridge.js +284 -20
- package/build/install-doctor.js +172 -30
- package/build/install-reexec.js +69 -7
- package/build/macos-terminal-permission-guidance.js +16 -0
- package/build/merge-pull-request.js +1 -1
- package/build/model-thresholds-tool.js +185 -0
- package/build/pipelines.generated.js +9 -8
- package/build/plan-discovery.js +137 -0
- package/build/plan-epic-implementer-eligibility.js +2 -2
- package/build/plane/cli.js +37 -3
- package/build/plane/member-logs.js +3 -0
- package/build/plane/member-roster.js +7 -1
- package/build/plane/shutdown.js +59 -1
- package/build/plane/status.js +4 -0
- package/build/plane/supervisor.js +146 -0
- package/build/plane/worker-exit-code.js +2 -0
- package/build/project-root.js +99 -0
- package/build/readme.generated.js +1 -1
- package/build/review-tickets.js +156 -13
- package/build/scripts/executor-protocol-contract-driver.js +13 -3
- package/build/setup-epic.js +208 -125
- package/build/sfcc/setup-status.js +2 -0
- package/build/sfcc/tool-wrapper.js +2 -0
- package/build/sfcc/tools-configured.js +96 -0
- package/build/start-tickets.js +163 -58
- package/build/upgrade-cli.js +109 -24
- package/build/version.generated.js +3 -3
- package/build/windows-npm-entry.js +103 -0
- package/build/worker-guard-hook-bin.js +5 -4
- package/build/worktree-core.js +6 -5
- package/docs/CONDUCTOR.md +116 -2
- package/docs/install/mcp-tool-integrations.md +1 -0
- package/docs/install/sfcc-integration.md +12 -7
- package/package.json +2 -1
- package/pipelines/implement-ticket.json +1 -1
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
import os from "node:os";
|
|
36
36
|
import { readFile as fsReadFile, stat as fsStat } from "node:fs/promises";
|
|
37
37
|
import { collectConductorReadinessGate, formatConductorReadinessGateReport, } from "./readiness.js";
|
|
38
|
-
import { resolveConductorBridgeApiAccess } from "./bridge-api-client.js";
|
|
38
|
+
import { readinessEndpointEnvironments, resolveConductorBridgeApiAccess, resolveEpicLaunchBridgeApiAccess } from "./bridge-api-client.js";
|
|
39
|
+
import { validateHttpBaseUrl } from "../base-url.js";
|
|
39
40
|
import { claudeReviewWorkflowPath } from "../claude-review-workflow.js";
|
|
40
41
|
import { runDefaultPlanePreflight } from "../plane/cli.js";
|
|
41
42
|
/** Fixed notice emitted to stderr when a source could not be collected. */
|
|
@@ -43,7 +44,7 @@ export const READINESS_COLLECTION_NOTICE = "one or more readiness sources could
|
|
|
43
44
|
/** Usage text for `epic-implementer readiness`. */
|
|
44
45
|
export function getReadinessUsage() {
|
|
45
46
|
return [
|
|
46
|
-
"Usage: epic-implementer readiness [--json] [--no-deny-probe]",
|
|
47
|
+
"Usage: epic-implementer readiness [--json] [--no-deny-probe] [--base-url <url>]",
|
|
47
48
|
"",
|
|
48
49
|
"Read-only ADVISORY report of every conductor prerequisite, consolidated from the",
|
|
49
50
|
"Bridge install checklist, the epic-implementer doctor, the plane preflight, and the",
|
|
@@ -58,19 +59,31 @@ export function getReadinessUsage() {
|
|
|
58
59
|
" --json Print the versioned structured report as JSON",
|
|
59
60
|
" --no-deny-probe Accepted for parity with `epic-implementer doctor`; inert here, because",
|
|
60
61
|
" this command never spawns the deny-enforcement probe",
|
|
62
|
+
" --base-url <url> Select a read-only Bridge API endpoint for this report;",
|
|
63
|
+
" this does not authorize or supply a credential",
|
|
61
64
|
" --help Print this usage message",
|
|
62
65
|
].join("\n");
|
|
63
66
|
}
|
|
64
67
|
/** Parse `epic-implementer readiness` argv. Unknown flags and positionals are errors. */
|
|
65
68
|
export function parseReadinessArgs(argv) {
|
|
66
69
|
const parsed = { json: false, help: false, noDenyProbe: false };
|
|
67
|
-
for (
|
|
70
|
+
for (let index = 0; index < argv.length; index++) {
|
|
71
|
+
const token = argv[index];
|
|
68
72
|
if (token === "--json")
|
|
69
73
|
parsed.json = true;
|
|
70
74
|
else if (token === "--no-deny-probe")
|
|
71
75
|
parsed.noDenyProbe = true;
|
|
72
76
|
else if (token === "--help" || token === "-h")
|
|
73
77
|
parsed.help = true;
|
|
78
|
+
else if (token === "--base-url") {
|
|
79
|
+
const raw = argv[++index];
|
|
80
|
+
if (!raw || raw.startsWith("--"))
|
|
81
|
+
return { error: "--base-url requires an HTTP(S) URL." };
|
|
82
|
+
const valid = validateHttpBaseUrl(raw);
|
|
83
|
+
if (!valid.ok)
|
|
84
|
+
return { error: "--base-url requires a valid HTTP(S) URL." };
|
|
85
|
+
parsed.baseUrl = valid.baseUrl;
|
|
86
|
+
}
|
|
74
87
|
else
|
|
75
88
|
return { error: `Unknown argument "${token}". Run "epic-implementer readiness --help" for usage.` };
|
|
76
89
|
}
|
|
@@ -83,8 +96,16 @@ export function parseReadinessArgs(argv) {
|
|
|
83
96
|
* epic-implementer doctor's local inspections, and the same plane preflight
|
|
84
97
|
* `plane up` and `drive-epic` run. Nothing is re-implemented here.
|
|
85
98
|
*/
|
|
86
|
-
async function collectProductionReport(repoRoot, env) {
|
|
87
|
-
const
|
|
99
|
+
async function collectProductionReport(repoRoot, env, baseUrl) {
|
|
100
|
+
const { reportEnv, resolverEnv } = readinessEndpointEnvironments(env, baseUrl);
|
|
101
|
+
const accessResult = baseUrl === undefined
|
|
102
|
+
? await resolveConductorBridgeApiAccess({ env: reportEnv, cwd: repoRoot })
|
|
103
|
+
: await resolveEpicLaunchBridgeApiAccess({ baseUrl }, { env: resolverEnv, cwd: repoRoot });
|
|
104
|
+
if (baseUrl !== undefined && !accessResult.ok) {
|
|
105
|
+
// A refused override is never permission for a downstream doctor collector
|
|
106
|
+
// to resolve credentials afresh from the general CLI environment.
|
|
107
|
+
return collectConductorReadinessGate({ repoName: null });
|
|
108
|
+
}
|
|
88
109
|
const access = accessResult.ok ? accessResult.access : null;
|
|
89
110
|
return collectConductorReadinessGate({
|
|
90
111
|
// Never guessed: an unresolved identity is reported as such rather than
|
|
@@ -101,7 +122,7 @@ async function collectProductionReport(repoRoot, env) {
|
|
|
101
122
|
readWorkflowFile: () => fsReadFile(claudeReviewWorkflowPath(repoRoot), "utf-8"),
|
|
102
123
|
projectRoot: repoRoot,
|
|
103
124
|
installDoctorDeps: {
|
|
104
|
-
env,
|
|
125
|
+
env: reportEnv,
|
|
105
126
|
cwd: repoRoot,
|
|
106
127
|
platform: process.platform,
|
|
107
128
|
homedir: os.homedir,
|
|
@@ -112,8 +133,8 @@ async function collectProductionReport(repoRoot, env) {
|
|
|
112
133
|
},
|
|
113
134
|
// The deny-enforcement probe is never spawned from this command; the check
|
|
114
135
|
// is reported as an explicit skip naming `epic-implementer doctor` instead.
|
|
115
|
-
conductorDoctorDeps: { env, skipDenyProbe: true },
|
|
116
|
-
runPlanePreflight: () => runDefaultPlanePreflight(repoRoot,
|
|
136
|
+
conductorDoctorDeps: { env: reportEnv, skipDenyProbe: true },
|
|
137
|
+
runPlanePreflight: () => runDefaultPlanePreflight(repoRoot, reportEnv),
|
|
117
138
|
});
|
|
118
139
|
}
|
|
119
140
|
/**
|
|
@@ -138,7 +159,7 @@ export async function runConductorReadinessCommand(argv, deps = {}) {
|
|
|
138
159
|
}
|
|
139
160
|
const cwd = deps.cwd ?? process.cwd();
|
|
140
161
|
const env = deps.env ?? process.env;
|
|
141
|
-
const collect = deps.collect ?? ((repoRoot) => collectProductionReport(repoRoot, env));
|
|
162
|
+
const collect = deps.collect ?? ((repoRoot) => collectProductionReport(repoRoot, env, parsed.baseUrl));
|
|
142
163
|
const report = await collect(cwd);
|
|
143
164
|
// Fixed, sanitized, and stderr-only: never a credential, exception, header,
|
|
144
165
|
// body, subprocess output, or absolute path. It fires on a COLLECTION gap,
|
|
@@ -771,12 +771,13 @@ export function conductorHookTargetsSection(legacyConductor, conductorContext) {
|
|
|
771
771
|
detail: "advisory — not a git worktree, so no managed conductor hooks apply",
|
|
772
772
|
};
|
|
773
773
|
}
|
|
774
|
+
// BAPI-1290: the shared per-hook `usable` verdict — a recognized command, an
|
|
775
|
+
// executable hook, and a qualified persistent runtime whose Node and native
|
|
776
|
+
// binding load. A file that merely exists is not delivery, and a hook without
|
|
777
|
+
// that verdict (an older or partial report) is unknown, never usable.
|
|
774
778
|
const usable = (name) => {
|
|
775
779
|
const hook = (hooks.hooks ?? []).find((h) => h.name === name);
|
|
776
|
-
return
|
|
777
|
-
hook.exists &&
|
|
778
|
-
hook.managed_block_present &&
|
|
779
|
-
hook.embedded_bin_is_file);
|
|
780
|
+
return hook !== undefined && hook.usable === true;
|
|
780
781
|
};
|
|
781
782
|
const rendered = MANAGED_HOOK_NAMES.map((name) => `${name}=${usable(name)}`).join(", ");
|
|
782
783
|
const allUsable = MANAGED_HOOK_NAMES.every((name) => usable(name));
|
|
@@ -141,7 +141,7 @@ export const SERVER_READINESS_DESCRIPTORS = [
|
|
|
141
141
|
{ id: "executor-readiness", label: "Executor server observation" },
|
|
142
142
|
{ id: "review-workflow", label: "Review workflow protocol" },
|
|
143
143
|
{ id: "conductor-ci-workflow", label: "Conductor CI migration guard" },
|
|
144
|
-
// BAPI-1102 — the two
|
|
144
|
+
// BAPI-1102 — the two unattended repository prerequisites plus the aggregate the
|
|
145
145
|
// third unattended refusal reads. Noun phrases, like every row above: these
|
|
146
146
|
// render as list items under a source heading, not as sentences.
|
|
147
147
|
{ id: "unattended-consent", label: "Repository unattended consent" },
|
|
@@ -189,8 +189,10 @@ const SERVER_REMEDIATIONS = {
|
|
|
189
189
|
olderServer: "upgrade the Bridge API deploy so it reports this fact; its state is unknown here, not healthy.",
|
|
190
190
|
// BAPI-1102. Each names the ONE action that clears it, and none of them
|
|
191
191
|
// mentions a webhook URL, a destination, or any configuration value.
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
// BAPI-1273: consent defaults ON; the repository owner switches it on the
|
|
193
|
+
// admin panel's Setup page. No MCP or CLI surface ever writes it.
|
|
194
|
+
unattendedConsent: "turn on 'Allow unattended Epic Implementer runs' on the repository's Setup page in the Bridge admin panel, or run setup with --attended. If it is already on, contact Bridge support.",
|
|
195
|
+
unattendedNotifyDefault: "supply a --policy-file declaring notify.webhook_url, or add an email address to the account so escalation alerts can be emailed, or run setup with --attended; an unattended run must have a working escalation channel, and notify.local_sink is not one.",
|
|
194
196
|
repositoryWorkflowReadiness: "run `install-bridge conductor` so the review and conductor-CI workflows are confirmed on the default branch, or run setup with --attended.",
|
|
195
197
|
// BAPI-1135. Both are IMPORTED from the shared classifier rather than written
|
|
196
198
|
// out here, so the remedy command has exactly one spelling across the refusal,
|
|
@@ -336,7 +338,28 @@ export function mapServerReadinessToChecks(readiness, failure = "unreachable") {
|
|
|
336
338
|
});
|
|
337
339
|
// BAPI-1260 — appended ONLY when the server reported the block, so every
|
|
338
340
|
// pre-BAPI-1260 report keeps exactly the descriptor set above.
|
|
339
|
-
return [...described, ...admissionEvidenceChecks(readiness)];
|
|
341
|
+
return [...described, ...admissionEvidenceChecks(readiness), ...genericDiagnosticChecks(readiness)];
|
|
342
|
+
}
|
|
343
|
+
function genericDiagnosticChecks(readiness) {
|
|
344
|
+
return (readiness.diagnostics ?? []).map((diagnostic, index) => {
|
|
345
|
+
const inapplicable = diagnostic.applicability === "inapplicable";
|
|
346
|
+
const declared = diagnostic.severity !== null && diagnostic.applicability !== null;
|
|
347
|
+
const satisfied = declared && diagnostic.verdict === "passed" && diagnostic.applicability === "applicable";
|
|
348
|
+
const advisory = diagnostic.severity === "advisory";
|
|
349
|
+
const status = !declared ? "fail" : inapplicable ? "skip" : satisfied ? "pass" : advisory ? "warn" : "fail";
|
|
350
|
+
return createReadinessCheckSafely({
|
|
351
|
+
id: `server.diagnostic-${index + 1}-${diagnostic.id.replace(/[_.]/g, "-")}`,
|
|
352
|
+
source: "server",
|
|
353
|
+
label: `Server diagnostic ${diagnostic.id}`,
|
|
354
|
+
status,
|
|
355
|
+
detail: `severity ${diagnostic.severity ?? "unknown"}; applicability ${diagnostic.applicability ?? "unknown"}; verdict ${diagnostic.verdict}`,
|
|
356
|
+
...(status === "pass" ? {} : {
|
|
357
|
+
remediation: status === "skip"
|
|
358
|
+
? "This diagnostic does not apply to the selected topology."
|
|
359
|
+
: "Restore the diagnostic producer or resolve the reported condition before launch.",
|
|
360
|
+
}),
|
|
361
|
+
});
|
|
362
|
+
});
|
|
340
363
|
}
|
|
341
364
|
/** Human labels for the known BAPI-1260 evidence predicates. */
|
|
342
365
|
const ADMISSION_EVIDENCE_LABELS = {
|
|
@@ -351,7 +374,7 @@ const ADMISSION_EVIDENCE_LABELS = {
|
|
|
351
374
|
/** Who acts, in fixed prose. Never a value from the payload. */
|
|
352
375
|
const ADMISSION_OWNER_REMEDIATION = {
|
|
353
376
|
operator: "the operator re-runs guided setup (`install conductor --launch-profile <name>`) and re-observes.",
|
|
354
|
-
repository_admin: "a repository administrator resolves it
|
|
377
|
+
repository_admin: "a repository administrator resolves it (unattended consent is the 'Allow unattended Epic Implementer runs' toggle on the repository's Setup page in the Bridge admin panel); setup never grants it.",
|
|
355
378
|
bridge_operations: "escalate to Bridge operations; this is not something an operator command can change.",
|
|
356
379
|
};
|
|
357
380
|
/**
|
|
@@ -485,7 +508,7 @@ function unattendedOutcomes(readiness) {
|
|
|
485
508
|
: {
|
|
486
509
|
id: "unattended-consent",
|
|
487
510
|
status: "warn",
|
|
488
|
-
detail: "
|
|
511
|
+
detail: "unattended runs are off for this repository — an unattended run will be refused before it is created",
|
|
489
512
|
remediation: SERVER_REMEDIATIONS.unattendedConsent,
|
|
490
513
|
},
|
|
491
514
|
u.notify_webhook_default_declared
|
|
@@ -498,12 +521,21 @@ function unattendedOutcomes(readiness) {
|
|
|
498
521
|
? "a notify webhook default is declared and verified"
|
|
499
522
|
: "a notify webhook default is declared (verified at approval, not here)",
|
|
500
523
|
}
|
|
501
|
-
:
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
524
|
+
: u.escalation_email_available === true
|
|
525
|
+
? {
|
|
526
|
+
// BAPI-1274 — with no webhook declared, escalation alerts go to the
|
|
527
|
+
// account's email address. Presence only: the address is never
|
|
528
|
+
// reported by the server and is never rendered here.
|
|
529
|
+
id: "unattended-notify-default",
|
|
530
|
+
status: "pass",
|
|
531
|
+
detail: "No webhook declared; escalation alerts will be emailed to the account's email address",
|
|
532
|
+
}
|
|
533
|
+
: {
|
|
534
|
+
id: "unattended-notify-default",
|
|
535
|
+
status: "warn",
|
|
536
|
+
detail: "no repository notify webhook default is declared — an unattended run needs an escalation channel, and no column supplies a repository default today, so the run must declare notify.webhook_url itself or the account needs an email address for escalation alerts",
|
|
537
|
+
remediation: SERVER_REMEDIATIONS.unattendedNotifyDefault,
|
|
538
|
+
},
|
|
507
539
|
u.repository_readiness_confirmed
|
|
508
540
|
? {
|
|
509
541
|
id: "repository-workflow-readiness",
|
|
@@ -891,6 +923,7 @@ export async function collectConductorReadinessGate(deps) {
|
|
|
891
923
|
repoName: deps.repoName ?? null,
|
|
892
924
|
unavailableSources,
|
|
893
925
|
checks: validated,
|
|
926
|
+
...(installReport?.readiness?.diagnostics ? { diagnostics: installReport.readiness.diagnostics } : {}),
|
|
894
927
|
summary: summarizeReadinessChecks(validated),
|
|
895
928
|
};
|
|
896
929
|
}
|