@bridge_gpt/mcp-server 0.2.65 → 0.2.67
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 +269 -82
- package/build/agent-capabilities/probes.js +15 -5
- package/build/agent-launchers/claude-executor-adapter.js +55 -34
- package/build/agent-launchers/executor-adapter.js +34 -4
- package/build/agents.generated.js +1 -1
- package/build/bounded-wait.js +67 -10
- package/build/bridge-config.js +104 -0
- package/build/codex-bridge-profile.js +10 -1
- package/build/commands.generated.js +12 -12
- package/build/conductor/bridge-api-client.js +372 -10
- package/build/conductor/bring-up-facts.js +1 -1
- package/build/conductor/doctor.js +3 -3
- package/build/conductor/epic-child-continuation.js +61 -34
- package/build/conductor/epic-implementer-cli.js +34 -6
- package/build/conductor/errors.js +4 -3
- package/build/conductor/guided-repair.js +327 -0
- package/build/conductor/hook-runtime-qualification.js +1 -1
- package/build/conductor/merge-execution-contract.js +27 -8
- package/build/conductor/merge-execution-eligibility.js +3 -2
- package/build/conductor/pr-ci-producer.js +1 -1
- package/build/conductor/readiness-cli.js +46 -9
- package/build/conductor/readiness-sections.js +41 -6
- package/build/conductor/readiness.js +204 -30
- package/build/conductor/recovery-cli.js +703 -20
- package/build/conductor/recovery-operations.js +392 -3
- package/build/conductor/repair-contract.js +112 -3
- package/build/conductor/repository-workflow-remedy.js +125 -0
- package/build/conductor/tools.js +2 -2
- package/build/conductor-bundle-artifacts.js +8 -0
- package/build/credential-store.js +5 -4
- package/build/diagnostic-text.js +36 -0
- package/build/docs.generated.js +8 -3
- package/build/doctor.js +70 -10
- package/build/drive-epic-key.js +6 -5
- package/build/drive-epic.js +479 -131
- package/build/epic-coherence-input.js +2 -1
- package/build/epic-implementer-bin.js +30 -26
- package/build/epic-implementer-bundle-cli.js +2 -2
- package/build/epic-launch-diagnostic.js +31 -0
- package/build/epic-launch-profile.js +44 -14
- package/build/executor/cli.js +3 -2
- package/build/executor/completion-contract.js +48 -5
- package/build/executor/completion-supervision.js +9 -0
- package/build/executor/correction-dispatch.js +60 -0
- package/build/executor/env.js +25 -0
- package/build/executor/heartbeat.js +1 -1
- package/build/executor/http-client.js +35 -0
- package/build/executor/integration-job.js +6 -1
- package/build/executor/job-errors.js +38 -4
- package/build/executor/job-log-registry.js +340 -73
- package/build/executor/job-runner.js +485 -74
- package/build/executor/job-types.js +8 -13
- package/build/executor/observation.js +6 -1
- package/build/executor/preflight.js +136 -10
- package/build/executor/prompt-spec.js +113 -9
- package/build/executor/required-work-ledger.js +6 -1
- package/build/executor/resume-pre-spawn.js +2 -0
- package/build/executor/runner.js +31 -2
- package/build/executor/service-unit.js +7 -1
- package/build/executor/stale-artifacts.js +5 -4
- package/build/executor/types.js +1 -0
- package/build/executor/watch-cli.js +35 -8
- package/build/executor/worker-command.js +43 -43
- package/build/executor/worker-finalization.js +161 -43
- package/build/executor/worker-guard-hook.js +152 -12
- package/build/executor/worker-log.js +137 -70
- package/build/executor/worktree-gc.js +30 -6
- package/build/executor/worktree.js +82 -1
- package/build/index.js +482 -660
- package/build/init.js +107 -4
- package/build/install-bridge-conductor.js +8 -6
- package/build/install-bridge.js +287 -23
- 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/model-thresholds-tool.js +185 -0
- package/build/phase-context-git-probe.js +68 -0
- package/build/phase-result-artifacts.js +173 -5
- package/build/pipelines.generated.js +19 -25
- package/build/plane/alembic-head.js +12 -3
- package/build/plane/base-worktree-guard.js +147 -0
- package/build/plane/cli.js +217 -17
- package/build/plane/code-snapshot.js +468 -0
- package/build/plane/defaults.js +48 -3
- package/build/plane/endpoint.js +41 -0
- package/build/plane/manifest.js +120 -1
- package/build/plane/member-roster.js +94 -19
- package/build/plane/preflight.js +30 -2
- package/build/plane/process-cwd.js +67 -0
- package/build/plane/restart.js +542 -0
- package/build/plane/shutdown.js +31 -0
- package/build/plane/status.js +145 -6
- package/build/plane/supervisor.js +588 -177
- package/build/plane/types.js +54 -2
- package/build/plane/worker-exit-code.js +2 -0
- package/build/printed-remedy-commands.js +37 -0
- package/build/project-root.js +99 -0
- package/build/readiness-check.js +1 -1
- package/build/readme.generated.js +1 -1
- package/build/review-generation.js +22 -0
- package/build/review-tickets.js +156 -13
- package/build/setup-epic.js +224 -127
- package/build/sfcc/config.js +9 -0
- package/build/sfcc/credentials.js +100 -38
- package/build/sfcc/hostname.js +67 -0
- package/build/sfcc/permissions.js +17 -13
- package/build/sfcc/register.js +1 -1
- package/build/sfcc/setup-status.js +2 -0
- package/build/sfcc/tool-wrapper.js +41 -43
- package/build/sfcc/tools-configured.js +96 -0
- package/build/sfcc/write-grants.js +17 -11
- package/build/sfcc/write-result.js +4 -3
- package/build/sfcc/writes-site-preference.js +20 -8
- package/build/start-tickets.js +332 -79
- package/build/tool-error-envelope.js +61 -0
- package/build/upgrade-cli.js +109 -24
- package/build/version.generated.js +3 -3
- package/build/visual-diff.js +22 -1
- package/build/windows-npm-entry.js +103 -0
- package/build/worker-guard-hook-bin.js +3 -5
- package/build/worker-guard-hook-main.js +47 -0
- package/build/worktree-core.js +136 -9
- package/docs/EPIC-IMPLEMENTER-INSTALL.md +849 -0
- package/docs/EPIC-IMPLEMENTER.md +662 -0
- package/docs/install/mcp-tool-integrations.md +25 -15
- package/docs/install/sfcc-integration.md +21 -8
- package/package.json +1 -1
- package/pipelines/implement-ticket.json +1 -1
- package/pipelines/plan-epic.json +0 -5
- package/pipelines/review-ticket.json +1 -1
- package/docs/CONDUCTOR.md +0 -605
- package/pipelines/idea-to-pr.json +0 -49
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/** The two fixed workflow files unattended auto-merge reads. Named once here. */
|
|
2
|
+
export const REVIEW_WORKFLOW_PATH = ".github/workflows/claude-review.yml";
|
|
3
|
+
export const CI_WORKFLOW_PATH = ".github/workflows/epic-implementer-ci.yml";
|
|
4
|
+
/** The migration guard's stable job id and its exact checker invocation. */
|
|
5
|
+
export const MIGRATION_GUARD_JOB_ID = "migration-guard";
|
|
6
|
+
export const MIGRATION_GUARD_CHECKER_PATH = "scripts/check_alembic_migration_graph.py";
|
|
7
|
+
export const MIGRATION_GUARD_INVOCATION = `python ${MIGRATION_GUARD_CHECKER_PATH}`;
|
|
8
|
+
const RETRY = "Run the readiness check again, or pass --attended. " +
|
|
9
|
+
"If it keeps failing, contact Bridge operations.";
|
|
10
|
+
const TEMPLATES = {
|
|
11
|
+
review_workflow_file: `${REVIEW_WORKFLOW_PATH} is missing from the default branch. Add it, or pass --attended.`,
|
|
12
|
+
review_run_id_marker: `${REVIEW_WORKFLOW_PATH} does not emit the run-id: marker in its verdict comment. ` +
|
|
13
|
+
"Add it, or pass --attended.",
|
|
14
|
+
review_reviewed_sha_marker: `${REVIEW_WORKFLOW_PATH} does not emit the Reviewed-SHA: marker in its verdict comment. ` +
|
|
15
|
+
"Add it, or pass --attended.",
|
|
16
|
+
review_workflow_unverifiable: `Bridge could not read ${REVIEW_WORKFLOW_PATH} on the default branch. ${RETRY}`,
|
|
17
|
+
ci_workflow_file: `${CI_WORKFLOW_PATH} is missing from the default branch. Add it, or pass --attended.`,
|
|
18
|
+
migration_guard_job: `${CI_WORKFLOW_PATH} has no job with id ${MIGRATION_GUARD_JOB_ID} running ${MIGRATION_GUARD_INVOCATION}. ` +
|
|
19
|
+
"It is required because this repository has alembic.ini on its default branch, " +
|
|
20
|
+
`and an equivalent checker at ${MIGRATION_GUARD_CHECKER_PATH} is required too. ` +
|
|
21
|
+
"Add that job, or pass --attended.",
|
|
22
|
+
migration_chain_unverifiable: "Bridge could not confirm whether this repository has alembic.ini on its default branch, " +
|
|
23
|
+
`so it could not decide if the ${MIGRATION_GUARD_JOB_ID} job is required. ${RETRY}`,
|
|
24
|
+
ci_workflow_unverifiable: `Bridge could not read ${CI_WORKFLOW_PATH} on the default branch. ${RETRY}`,
|
|
25
|
+
// An older server never reported whether the guard is conditional, so its
|
|
26
|
+
// guard has always been required. This states that requirement and NOTHING
|
|
27
|
+
// about alembic.ini: an older server observed no such file.
|
|
28
|
+
migration_guard_job_legacy: `${CI_WORKFLOW_PATH} has no job with id ${MIGRATION_GUARD_JOB_ID} running ${MIGRATION_GUARD_INVOCATION}. ` +
|
|
29
|
+
"Add that job, or pass --attended.",
|
|
30
|
+
};
|
|
31
|
+
/** Shown when the report is missing, incomplete, or not in a shape we can name. */
|
|
32
|
+
const UNVERIFIABLE_FALLBACK = "Bridge could not verify the review and CI workflows on the default branch. " + RETRY;
|
|
33
|
+
function classifyReview(w) {
|
|
34
|
+
if (w === null || w === undefined || typeof w !== "object")
|
|
35
|
+
return "malformed";
|
|
36
|
+
if (w.probe_succeeded !== true)
|
|
37
|
+
return ["review_workflow_unverifiable"];
|
|
38
|
+
if (w.workflow_present === false)
|
|
39
|
+
return ["review_workflow_file"];
|
|
40
|
+
if (w.workflow_present !== true ||
|
|
41
|
+
typeof w.emits_run_id !== "boolean" ||
|
|
42
|
+
typeof w.emits_reviewed_sha !== "boolean") {
|
|
43
|
+
return "malformed";
|
|
44
|
+
}
|
|
45
|
+
const missing = [];
|
|
46
|
+
if (!w.emits_run_id)
|
|
47
|
+
missing.push("review_run_id_marker");
|
|
48
|
+
if (!w.emits_reviewed_sha)
|
|
49
|
+
missing.push("review_reviewed_sha_marker");
|
|
50
|
+
return missing;
|
|
51
|
+
}
|
|
52
|
+
function classifyCi(c) {
|
|
53
|
+
if (c === null || c === undefined || typeof c !== "object")
|
|
54
|
+
return "malformed";
|
|
55
|
+
if (c.probe_succeeded !== true)
|
|
56
|
+
return ["ci_workflow_unverifiable"];
|
|
57
|
+
if (c.workflow_present === false)
|
|
58
|
+
return ["ci_workflow_file"];
|
|
59
|
+
if (c.workflow_present !== true || typeof c.migration_guard_present !== "boolean") {
|
|
60
|
+
return "malformed";
|
|
61
|
+
}
|
|
62
|
+
if (c.migration_guard_present)
|
|
63
|
+
return [];
|
|
64
|
+
const required = c.migration_guard_required;
|
|
65
|
+
const chainProbed = c.migration_chain_probe_succeeded;
|
|
66
|
+
// Older server: neither field reported. The guard was always required there,
|
|
67
|
+
// and the absent fields must never read as "not required".
|
|
68
|
+
if (required === undefined && chainProbed === undefined) {
|
|
69
|
+
return ["migration_guard_job_legacy"];
|
|
70
|
+
}
|
|
71
|
+
if (typeof required !== "boolean" || typeof chainProbed !== "boolean")
|
|
72
|
+
return "malformed";
|
|
73
|
+
if (chainProbed && !required)
|
|
74
|
+
return []; // confirmed guard-free
|
|
75
|
+
if (chainProbed && required)
|
|
76
|
+
return ["migration_guard_job"];
|
|
77
|
+
return ["migration_chain_unverifiable"];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Name the first failing workflow section of a parsed readiness report, its
|
|
81
|
+
* missing facts in stable order, and one fixed-template message.
|
|
82
|
+
*
|
|
83
|
+
* `section: null` with the fallback text means the report is missing or malformed
|
|
84
|
+
* — "could not verify", never "fine". An empty `missing` with `section: null`
|
|
85
|
+
* cannot occur: a report with nothing failing yields the fallback only when it is
|
|
86
|
+
* unreadable, and otherwise the empty result below.
|
|
87
|
+
*/
|
|
88
|
+
export function describeRepositoryWorkflowRemedy(readiness) {
|
|
89
|
+
const review = classifyReview(readiness?.review_workflow);
|
|
90
|
+
if (review === "malformed") {
|
|
91
|
+
return { section: null, missing: [], text: UNVERIFIABLE_FALLBACK };
|
|
92
|
+
}
|
|
93
|
+
if (review.length > 0)
|
|
94
|
+
return build("review_workflow", review);
|
|
95
|
+
const ci = classifyCi(readiness?.conductor_ci_workflow);
|
|
96
|
+
if (ci === "malformed") {
|
|
97
|
+
return { section: null, missing: [], text: UNVERIFIABLE_FALLBACK };
|
|
98
|
+
}
|
|
99
|
+
if (ci.length > 0)
|
|
100
|
+
return build("conductor_ci_workflow", ci);
|
|
101
|
+
return { section: null, missing: [], text: "" };
|
|
102
|
+
}
|
|
103
|
+
function build(section, missing) {
|
|
104
|
+
return { section, missing, text: missing.map((token) => TEMPLATES[token]).join(" ") };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The remedy sentence for a repository whose workflows are not confirmed. Never
|
|
108
|
+
* empty: a report with nothing to name (the server said unconfirmed but this
|
|
109
|
+
* client can name no item) gets the unverifiable fallback rather than silence.
|
|
110
|
+
*/
|
|
111
|
+
export function repositoryWorkflowRemedy(readiness) {
|
|
112
|
+
const described = describeRepositoryWorkflowRemedy(readiness);
|
|
113
|
+
return described.text === "" ? UNVERIFIABLE_FALLBACK : described.text;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The remedy for the CI workflow section alone — what the readiness CI row shows
|
|
117
|
+
* when the migration guard is absent. Same templates, same words as
|
|
118
|
+
* {@link repositoryWorkflowRemedy}, so the row and the refusals cannot drift.
|
|
119
|
+
*/
|
|
120
|
+
export function ciWorkflowRemedy(c) {
|
|
121
|
+
const tokens = classifyCi(c);
|
|
122
|
+
if (tokens === "malformed" || tokens.length === 0)
|
|
123
|
+
return UNVERIFIABLE_FALLBACK;
|
|
124
|
+
return tokens.map((token) => TEMPLATES[token]).join(" ");
|
|
125
|
+
}
|
package/build/conductor/tools.js
CHANGED
|
@@ -82,9 +82,9 @@ function registerExplainRunTool(registerTool) {
|
|
|
82
82
|
// is the field list: a caller cannot discover the answer shape from a
|
|
83
83
|
// tool that only says "explain a run", and the whole point of the tool is
|
|
84
84
|
// that the answer is in one place.
|
|
85
|
-
description: "Explain why
|
|
85
|
+
description: "Explain why an Epic Implementer run, or one ticket in it, is stuck. One snapshot: " +
|
|
86
86
|
"current gate, latest observation and age, outstanding jobs with queue position, " +
|
|
87
|
-
"lease owner/expiry, blocker reasons, expected
|
|
87
|
+
"lease owner/expiry, blocker reasons, expected/observed head SHA, committed and " +
|
|
88
88
|
"pending disposition, usage ceiling. Pass ticket_key to narrow. Read-only; 404 " +
|
|
89
89
|
"returns status 'unknown'.",
|
|
90
90
|
inputSchema: {
|
|
@@ -27,6 +27,14 @@ import { validateTicketKey } from "./ticket-key-utils.js";
|
|
|
27
27
|
const EPIC_SLUG_RE = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
28
28
|
/** Placeholder node identity written by `decompose-epic.md` before tickets exist. */
|
|
29
29
|
const PLACEHOLDER_RE = /TBD-\d+/;
|
|
30
|
+
/**
|
|
31
|
+
* A whole plan-node key that is still an authoring placeholder (`TBD-<digits>`),
|
|
32
|
+
* case-insensitive. Anchored on purpose and stateless (no `g` or `y` flag, so
|
|
33
|
+
* `.test()` carries no `lastIndex`). This is NOT {@link PLACEHOLDER_RE}: that one
|
|
34
|
+
* is an unanchored scan of a whole serialized plan, and
|
|
35
|
+
* {@link findResidualPlaceholder} keeps using it unchanged.
|
|
36
|
+
*/
|
|
37
|
+
export const PLACEHOLDER_NODE_KEY_RE = /^TBD-\d+$/i;
|
|
30
38
|
/**
|
|
31
39
|
* The conductor's hard spec bound, mirroring `_SPEC_REVIEW_TICKET_SPEC_MAX_CHARS`
|
|
32
40
|
* (64,000) in `api/library/epic_implementer/reconciler.py`. Since PR #848 the
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
* user-scoped `~/.config/bridge/credentials.json` store written here.
|
|
39
39
|
*/
|
|
40
40
|
import path from "path";
|
|
41
|
+
import { diagnosticComponent } from "./epic-launch-diagnostic.js";
|
|
41
42
|
// ---------------------------------------------------------------------------
|
|
42
43
|
// Path resolution
|
|
43
44
|
// ---------------------------------------------------------------------------
|
|
@@ -1497,9 +1498,9 @@ export async function resolveEpicLaunchCredential(repoName, targetBaseUrl, deps,
|
|
|
1497
1498
|
return {
|
|
1498
1499
|
ok: false,
|
|
1499
1500
|
kind: "binding-unbound",
|
|
1500
|
-
error: `The stored credential "${bundleKey}" has not been approved for this Bridge API endpoint ` +
|
|
1501
|
-
`(${primaryPath}). Production needs no approval; any other endpoint does. Run guided setup ` +
|
|
1502
|
-
`once to bind it: install conductor --launch-profile <name> --base-url ${target}.`,
|
|
1501
|
+
error: `The stored credential "${diagnosticComponent(bundleKey)}" has not been approved for this Bridge API endpoint ` +
|
|
1502
|
+
`(${diagnosticComponent(primaryPath)}). Production needs no approval; any other endpoint does. Run guided setup ` +
|
|
1503
|
+
`once to bind it: install conductor --launch-profile <name> --base-url ${diagnosticComponent(target)}.`,
|
|
1503
1504
|
};
|
|
1504
1505
|
}
|
|
1505
1506
|
// An unreadable read-back is refused like a mismatch: the key was read a
|
|
@@ -1508,7 +1509,7 @@ export async function resolveEpicLaunchCredential(repoName, targetBaseUrl, deps,
|
|
|
1508
1509
|
return {
|
|
1509
1510
|
ok: false,
|
|
1510
1511
|
kind: "binding-mismatch",
|
|
1511
|
-
error: `The stored credential "${bundleKey}" is approved for a different Bridge API endpoint than the ` +
|
|
1512
|
+
error: `The stored credential "${diagnosticComponent(bundleKey)}" is approved for a different Bridge API endpoint than the ` +
|
|
1512
1513
|
"selected target. It was not sent. A key approved for a local server is never sent to " +
|
|
1513
1514
|
"production: pass that server's --launch-profile <name> or --base-url <url>, or bind the key " +
|
|
1514
1515
|
"once with install conductor --launch-profile <name> --base-url <url>.",
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-line rendering for untrusted values in diagnostics (BAPI-1318).
|
|
3
|
+
*
|
|
4
|
+
* Project names read from `.bridge/config` or an MCP config env block, and paths
|
|
5
|
+
* read from `BAPI_PROJECT_ROOT`, are user-controlled. A newline or other control
|
|
6
|
+
* character in one of them could forge an extra line in a stderr diagnostic or a
|
|
7
|
+
* doctor report. This renderer escapes every ASCII control character and bounds
|
|
8
|
+
* the length, so each value always occupies exactly one line of output.
|
|
9
|
+
*/
|
|
10
|
+
/** Longest rendered value; anything longer is cut and marked with an ellipsis. */
|
|
11
|
+
export const DIAGNOSTIC_VALUE_MAX_LENGTH = 200;
|
|
12
|
+
/**
|
|
13
|
+
* Render `value` for a one-line diagnostic: control characters become `\xNN`
|
|
14
|
+
* (with `\n`, `\r`, and `\t` spelled out), and the result is bounded to
|
|
15
|
+
* {@link DIAGNOSTIC_VALUE_MAX_LENGTH} characters.
|
|
16
|
+
*/
|
|
17
|
+
export function renderDiagnosticValue(value) {
|
|
18
|
+
let out = "";
|
|
19
|
+
for (const ch of value) {
|
|
20
|
+
const code = ch.charCodeAt(0);
|
|
21
|
+
if (ch === "\n")
|
|
22
|
+
out += "\\n";
|
|
23
|
+
else if (ch === "\r")
|
|
24
|
+
out += "\\r";
|
|
25
|
+
else if (ch === "\t")
|
|
26
|
+
out += "\\t";
|
|
27
|
+
else if (code <= 0x1f || code === 0x7f)
|
|
28
|
+
out += `\\x${code.toString(16).padStart(2, "0")}`;
|
|
29
|
+
else
|
|
30
|
+
out += ch;
|
|
31
|
+
}
|
|
32
|
+
if (out.length > DIAGNOSTIC_VALUE_MAX_LENGTH) {
|
|
33
|
+
out = `${out.slice(0, DIAGNOSTIC_VALUE_MAX_LENGTH)}…`;
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|