@bridge_gpt/mcp-server 0.2.52 → 0.2.53
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 +42 -12
- package/build/commands.generated.js +6 -4
- package/build/conductor/bridge-api-client.js +61 -0
- package/build/conductor/cli.js +23 -0
- package/build/conductor/doctor.js +428 -5
- package/build/conductor/install-doctor.js +65 -656
- package/build/conductor/readiness-cli.js +152 -0
- package/build/conductor/readiness-sections.js +666 -0
- package/build/conductor/readiness.js +710 -0
- package/build/conductor/tools.js +56 -3
- package/build/conductor-bin.js +21 -17
- package/build/index.js +4651 -4580
- package/build/install-doctor.js +154 -2
- package/build/pipelines.generated.js +3 -3
- package/build/plane/alembic-head.js +40 -11
- package/build/plane/build-freshness.js +22 -11
- package/build/plane/preflight.js +363 -48
- package/build/plane/types.js +36 -0
- package/build/readiness-check.js +412 -0
- package/build/readme.generated.js +1 -1
- package/build/version.generated.js +3 -3
- package/package.json +2 -2
- package/pipelines/{full-automation.json → idea-to-pr.json} +1 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `conductor readiness` command surface (BAPI-1055, AC-6).
|
|
3
|
+
*
|
|
4
|
+
* A CLI subcommand, deliberately, and NOT an MCP tool. Every peer diagnostic in
|
|
5
|
+
* this package — `doctor`, `plane`, `drive-epic`, `executor`, `install` — is an
|
|
6
|
+
* `argv[0]` subcommand dispatched before MCP server construction, and this one
|
|
7
|
+
* inherits that standard: stdout carries the report, stderr carries only fixed
|
|
8
|
+
* sanitized notices, and no tool is registered, so the budget-pinned `tools/list`
|
|
9
|
+
* surface is untouched.
|
|
10
|
+
*
|
|
11
|
+
* THIN BY CONSTRUCTION. Argument parsing, dependency construction, and
|
|
12
|
+
* formatting live here; every probe, verdict, and mapping belongs to
|
|
13
|
+
* {@link file:./readiness.ts} and the collectors it composes.
|
|
14
|
+
*
|
|
15
|
+
* ## Advisory exit policy
|
|
16
|
+
*
|
|
17
|
+
* This command returns 0 for every readiness outcome — pass, warn, fail, skip,
|
|
18
|
+
* an unavailable source, and a malformed upstream response alike. It never
|
|
19
|
+
* mutates `process.exitCode`, never brings a plane up, never approves a run, and
|
|
20
|
+
* never executes a remediation. An advisory command that could exit non-zero
|
|
21
|
+
* would be a gate, and the hard gates are `drive-epic`'s
|
|
22
|
+
* `V2_READINESS_REQUIREMENTS` and the server-side admission.
|
|
23
|
+
*
|
|
24
|
+
* The only non-zero path is a usage error (an unknown flag), which is the
|
|
25
|
+
* command failing to run at all rather than a readiness verdict.
|
|
26
|
+
*
|
|
27
|
+
* ## Credentials
|
|
28
|
+
*
|
|
29
|
+
* Resolution goes through `resolveConductorBridgeApiAccess`, which reads
|
|
30
|
+
* `BAPI_API_KEY` from the parent environment and then the user-scoped store at
|
|
31
|
+
* `~/.config/bridge/credentials.json`. That is the shell-spawned credential
|
|
32
|
+
* rule: this command runs in a plain shell, which never sees `.mcp.json` env —
|
|
33
|
+
* that file is visible to the MCP server process only.
|
|
34
|
+
*/
|
|
35
|
+
import os from "node:os";
|
|
36
|
+
import { readFile as fsReadFile, stat as fsStat } from "node:fs/promises";
|
|
37
|
+
import { collectConductorReadinessGate, formatConductorReadinessGateReport, } from "./readiness.js";
|
|
38
|
+
import { resolveConductorBridgeApiAccess } from "./bridge-api-client.js";
|
|
39
|
+
import { claudeReviewWorkflowPath } from "../claude-review-workflow.js";
|
|
40
|
+
import { runDefaultPlanePreflight } from "../plane/cli.js";
|
|
41
|
+
/** Fixed notice emitted to stderr when a source could not be collected. */
|
|
42
|
+
export const READINESS_COLLECTION_NOTICE = "one or more readiness sources could not be collected; the affected prerequisites are reported as failures.";
|
|
43
|
+
/** Usage text for `conductor readiness`. */
|
|
44
|
+
export function getReadinessUsage() {
|
|
45
|
+
return [
|
|
46
|
+
"Usage: conductor readiness [--json] [--no-deny-probe]",
|
|
47
|
+
"",
|
|
48
|
+
"Read-only ADVISORY report of every conductor prerequisite, consolidated from the",
|
|
49
|
+
"Bridge install checklist, the conductor doctor, the plane preflight, and the",
|
|
50
|
+
"server conductor-readiness collector. Each prerequisite reports pass/warn/fail/skip",
|
|
51
|
+
"and, on a failure, exactly ONE named remediation.",
|
|
52
|
+
"",
|
|
53
|
+
"Remediations are NOT run automatically. This command changes nothing: it starts no",
|
|
54
|
+
"plane, approves no run, writes no file, and always exits 0 — `drive-epic` remains",
|
|
55
|
+
"the only route-selection gate and the server-side admission the only hard refusal.",
|
|
56
|
+
"",
|
|
57
|
+
"Options:",
|
|
58
|
+
" --json Print the versioned structured report as JSON",
|
|
59
|
+
" --no-deny-probe Accepted for parity with `conductor doctor`; inert here, because",
|
|
60
|
+
" this command never spawns the deny-enforcement probe",
|
|
61
|
+
" --help Print this usage message",
|
|
62
|
+
].join("\n");
|
|
63
|
+
}
|
|
64
|
+
/** Parse `conductor readiness` argv. Unknown flags and positionals are errors. */
|
|
65
|
+
export function parseReadinessArgs(argv) {
|
|
66
|
+
const parsed = { json: false, help: false, noDenyProbe: false };
|
|
67
|
+
for (const token of argv) {
|
|
68
|
+
if (token === "--json")
|
|
69
|
+
parsed.json = true;
|
|
70
|
+
else if (token === "--no-deny-probe")
|
|
71
|
+
parsed.noDenyProbe = true;
|
|
72
|
+
else if (token === "--help" || token === "-h")
|
|
73
|
+
parsed.help = true;
|
|
74
|
+
else
|
|
75
|
+
return { error: `Unknown argument "${token}". Run "conductor readiness --help" for usage.` };
|
|
76
|
+
}
|
|
77
|
+
return parsed;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Build the production report for `repoRoot`.
|
|
81
|
+
*
|
|
82
|
+
* Every seam is a real, READ-ONLY one: the install doctor's own GET, the
|
|
83
|
+
* conductor doctor's local inspections, and the same plane preflight
|
|
84
|
+
* `plane up` and `drive-epic` run. Nothing is re-implemented here.
|
|
85
|
+
*/
|
|
86
|
+
async function collectProductionReport(repoRoot, env) {
|
|
87
|
+
const accessResult = await resolveConductorBridgeApiAccess({ env, cwd: repoRoot });
|
|
88
|
+
const access = accessResult.ok ? accessResult.access : null;
|
|
89
|
+
return collectConductorReadinessGate({
|
|
90
|
+
// Never guessed: an unresolved identity is reported as such rather than
|
|
91
|
+
// invented, and the repository ROOT is never placed in the report at all.
|
|
92
|
+
repoName: access?.repoName ?? null,
|
|
93
|
+
installDoctor: {
|
|
94
|
+
access,
|
|
95
|
+
accessError: accessResult.ok ? undefined : accessResult.error,
|
|
96
|
+
fetch: (...args) => fetch(...args),
|
|
97
|
+
// The consolidated gate reports workflow presence as a fact; it selects no
|
|
98
|
+
// per-run review policy, so applicability is evaluated under the policy
|
|
99
|
+
// that always consumes the workflow's verdict.
|
|
100
|
+
reviewPolicySource: "verdict_protocol",
|
|
101
|
+
readWorkflowFile: () => fsReadFile(claudeReviewWorkflowPath(repoRoot), "utf-8"),
|
|
102
|
+
projectRoot: repoRoot,
|
|
103
|
+
installDoctorDeps: {
|
|
104
|
+
env,
|
|
105
|
+
cwd: repoRoot,
|
|
106
|
+
platform: process.platform,
|
|
107
|
+
homedir: os.homedir,
|
|
108
|
+
readFile: (filePath) => fsReadFile(filePath, "utf-8"),
|
|
109
|
+
stat: (filePath) => fsStat(filePath),
|
|
110
|
+
fetch: (...args) => fetch(...args),
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
// The deny-enforcement probe is never spawned from this command; the check
|
|
114
|
+
// is reported as an explicit skip naming `conductor doctor` instead.
|
|
115
|
+
conductorDoctorDeps: { env, skipDenyProbe: true },
|
|
116
|
+
runPlanePreflight: () => runDefaultPlanePreflight(repoRoot, env),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Run `conductor readiness`.
|
|
121
|
+
*
|
|
122
|
+
* Returns 0 for every readiness outcome; see the module docstring. The only
|
|
123
|
+
* non-zero return is a usage error.
|
|
124
|
+
*/
|
|
125
|
+
export async function runConductorReadinessCommand(argv, deps = {}) {
|
|
126
|
+
const sinks = deps.sinks ?? {
|
|
127
|
+
stdout: (line) => console.log(line),
|
|
128
|
+
stderr: (line) => console.error(line),
|
|
129
|
+
};
|
|
130
|
+
const parsed = parseReadinessArgs(argv);
|
|
131
|
+
if ("error" in parsed) {
|
|
132
|
+
sinks.stderr(`Error: ${parsed.error}`);
|
|
133
|
+
return 1;
|
|
134
|
+
}
|
|
135
|
+
if (parsed.help) {
|
|
136
|
+
sinks.stdout(getReadinessUsage());
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
140
|
+
const env = deps.env ?? process.env;
|
|
141
|
+
const collect = deps.collect ?? ((repoRoot) => collectProductionReport(repoRoot, env));
|
|
142
|
+
const report = await collect(cwd);
|
|
143
|
+
// Fixed, sanitized, and stderr-only: never a credential, exception, header,
|
|
144
|
+
// body, subprocess output, or absolute path. It fires on a COLLECTION gap,
|
|
145
|
+
// not on a failed prerequisite — a report that says "a source is missing"
|
|
146
|
+
// every time an ordinary check fails teaches operators to ignore it.
|
|
147
|
+
if (report.unavailableSources.length > 0)
|
|
148
|
+
sinks.stderr(READINESS_COLLECTION_NOTICE);
|
|
149
|
+
sinks.stdout(parsed.json ? JSON.stringify(report) : formatConductorReadinessGateReport(report));
|
|
150
|
+
// Advisory: the exit code is a constant, never derived from a check status.
|
|
151
|
+
return 0;
|
|
152
|
+
}
|