@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
package/build/worktree-core.js
CHANGED
|
@@ -96,6 +96,8 @@ function pickWorktreePathField(parsed) {
|
|
|
96
96
|
}
|
|
97
97
|
return undefined;
|
|
98
98
|
}
|
|
99
|
+
/** A full 40-character hex object name. */
|
|
100
|
+
const FULL_SHA_PATTERN = /^[0-9a-f]{40}$/i;
|
|
99
101
|
/**
|
|
100
102
|
* The remediation sentence for a branch left over by a prior FAILED run.
|
|
101
103
|
* Unchanged since the guard was introduced.
|
|
@@ -111,18 +113,115 @@ function staleLeftoverRemedy(branch, baseRef) {
|
|
|
111
113
|
*
|
|
112
114
|
* Names the `pr_not_attached` gate observation so the executor refusal and the
|
|
113
115
|
* reconciler's own state are one searchable vocabulary, points at attachment, and
|
|
114
|
-
* states plainly that the two remedies above destroy
|
|
116
|
+
* states plainly that the two remedies above destroy pushed work. It must not
|
|
115
117
|
* contain the words "delete" or "rebase" at all: an operator scanning a wall of
|
|
116
118
|
* job output for the next command is exactly who lost work last time.
|
|
117
119
|
*/
|
|
118
120
|
function unattachedSuccessRemedy(branch) {
|
|
119
|
-
return (`it carries the commits of
|
|
121
|
+
return (`it carries the pushed commits of an implement whose pull request was never attached ` +
|
|
120
122
|
`(implement gate observation: pr_not_attached). Refusing to reuse the worktree — but this ` +
|
|
121
|
-
`branch is
|
|
122
|
-
`
|
|
123
|
-
`
|
|
123
|
+
`branch is pushed work, not a leftover; whether its required work is finished or its checks ` +
|
|
124
|
+
`passed is not established by this observation. Open or attach a pull request from ` +
|
|
125
|
+
`'${branch}' and let the reconciler bind it. Do NOT remove or re-write the branch: either ` +
|
|
126
|
+
`would destroy pushed work.`);
|
|
124
127
|
}
|
|
125
|
-
|
|
128
|
+
/**
|
|
129
|
+
* BAPI-1367: the remedy for a branch that holds pushed work from an EARLIER
|
|
130
|
+
* attempt of this same job. Leads with the work state, uses the short head only
|
|
131
|
+
* as supporting evidence, and points at inspection and recovery. It must not
|
|
132
|
+
* contain the words "delete" or "rebase": an operator scanning job output for the
|
|
133
|
+
* next command is exactly who would lose this work.
|
|
134
|
+
*/
|
|
135
|
+
function priorAttemptRemedy(branch, priorHeadSha) {
|
|
136
|
+
const evidence = priorHeadSha ? ` (recorded head ${priorHeadSha.slice(0, 12)})` : "";
|
|
137
|
+
return (`it holds pushed work from this job's prior attempt${evidence}. ` +
|
|
138
|
+
`Refusing to reuse the worktree automatically because its lineage could not be fully proven; ` +
|
|
139
|
+
`this branch is prior work, not a leftover. Inspect '${branch}' and recover from it; ` +
|
|
140
|
+
`do not discard it.`);
|
|
141
|
+
}
|
|
142
|
+
/** Exit status 1 is Git's definite "not an ancestor"; anything else is not proof. */
|
|
143
|
+
async function isAncestor(deps, ancestor, descendant) {
|
|
144
|
+
const result = await deps.runCommand("git", ["merge-base", "--is-ancestor", ancestor, descendant], { cwd: deps.cwd });
|
|
145
|
+
if (commandSucceeded(result))
|
|
146
|
+
return "yes";
|
|
147
|
+
return result.exitCode === 1 ? "no" : "unknown";
|
|
148
|
+
}
|
|
149
|
+
async function resolveCommit(deps, ref) {
|
|
150
|
+
const result = await deps.runCommand("git", ["rev-parse", "--verify", "--quiet", `${ref}^{commit}`], { cwd: deps.cwd });
|
|
151
|
+
if (!commandSucceeded(result))
|
|
152
|
+
return null;
|
|
153
|
+
const sha = result.stdout.trim();
|
|
154
|
+
return FULL_SHA_PATTERN.test(sha) ? sha : null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* BAPI-1367: prove that `branch` may be resumed from `policy.priorHeadSha`.
|
|
158
|
+
*
|
|
159
|
+
* Selects exactly ONE tip: the local branch when it exists (and only it — a valid
|
|
160
|
+
* `origin/<branch>` never substitutes for a failing local branch), else
|
|
161
|
+
* `origin/<branch>`. That tip must equal or descend from the prior head, and the
|
|
162
|
+
* prior head must NOT already be an ancestor of the resolved base. Every inability
|
|
163
|
+
* to prove any of this refuses. Only read-only Git is run here.
|
|
164
|
+
*/
|
|
165
|
+
export async function provePriorHeadLineage(deps, branch, policy, only) {
|
|
166
|
+
const refuse = (reason, containsPriorHead = false) => ({
|
|
167
|
+
ok: false,
|
|
168
|
+
reason,
|
|
169
|
+
containsPriorHead,
|
|
170
|
+
});
|
|
171
|
+
if (typeof policy.priorHeadSha !== "string" || !FULL_SHA_PATTERN.test(policy.priorHeadSha)) {
|
|
172
|
+
return refuse("no usable prior-attempt head was supplied");
|
|
173
|
+
}
|
|
174
|
+
const prior = await resolveCommit(deps, policy.priorHeadSha);
|
|
175
|
+
if (prior === null) {
|
|
176
|
+
return refuse(`the prior-attempt head ${policy.priorHeadSha.slice(0, 12)} is not present in this checkout`);
|
|
177
|
+
}
|
|
178
|
+
// `only: "origin_branch"` judges the pushed ref alone, for a caller that must
|
|
179
|
+
// recreate a worktree from it even though a local branch also exists.
|
|
180
|
+
const local = only === "origin_branch" ? false : await branchExists(deps, branch);
|
|
181
|
+
const selected = await resolveCommit(deps, local ? `refs/heads/${branch}` : `refs/remotes/origin/${branch}`);
|
|
182
|
+
if (selected === null) {
|
|
183
|
+
return refuse(`${local ? "its local tip" : `origin/${branch}`} could not be resolved`);
|
|
184
|
+
}
|
|
185
|
+
const lineage = await isAncestor(deps, prior, selected);
|
|
186
|
+
if (lineage !== "yes") {
|
|
187
|
+
return refuse(`its tip does not contain the prior-attempt head ${prior.slice(0, 12)}`);
|
|
188
|
+
}
|
|
189
|
+
const inBase = await isAncestor(deps, prior, policy.baseRef);
|
|
190
|
+
if (inBase === "yes") {
|
|
191
|
+
return refuse(`the prior-attempt head ${prior.slice(0, 12)} is already part of the base, so it is not unmerged work from this job`, true);
|
|
192
|
+
}
|
|
193
|
+
if (inBase === "unknown") {
|
|
194
|
+
return refuse(`whether the prior-attempt head ${prior.slice(0, 12)} is part of the base could not be established`, true);
|
|
195
|
+
}
|
|
196
|
+
return { ok: true, source: local ? "local_branch" : "origin_branch" };
|
|
197
|
+
}
|
|
198
|
+
export async function isExistingBranchSafeToReuse(deps, branch, baseStartPoint, classification = "unknown", allowedPriorHead) {
|
|
199
|
+
// BAPI-1367: with a caller-authorized prior head, the ONLY way to reuse a
|
|
200
|
+
// branch that carries commits beyond base is explicit lineage proof. A refusal
|
|
201
|
+
// here is final: the legacy base-ancestry shortcut can never turn it into a
|
|
202
|
+
// base alignment. A refused branch whose history holds the recorded head gets
|
|
203
|
+
// the calm own-prior remedy; one without that history keeps the ordinary
|
|
204
|
+
// stale-branch text when the legacy guard also refuses it.
|
|
205
|
+
if (allowedPriorHead !== undefined) {
|
|
206
|
+
const proof = await provePriorHeadLineage(deps, branch, allowedPriorHead);
|
|
207
|
+
if (proof.ok)
|
|
208
|
+
return { safe: true, resume: proof.source };
|
|
209
|
+
if (proof.containsPriorHead) {
|
|
210
|
+
return {
|
|
211
|
+
safe: false,
|
|
212
|
+
reason: `existing branch '${branch}' ${priorAttemptRemedy(branch, allowedPriorHead.priorHeadSha)} ` +
|
|
213
|
+
`(${proof.reason})`,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
// Only a LOCAL branch has a legacy verdict to keep; an origin-only branch is
|
|
217
|
+
// judged by the proof alone.
|
|
218
|
+
if (await branchExists(deps, branch)) {
|
|
219
|
+
const legacy = await isExistingBranchSafeToReuse(deps, branch, baseStartPoint, classification);
|
|
220
|
+
if (!legacy.safe)
|
|
221
|
+
return legacy;
|
|
222
|
+
}
|
|
223
|
+
return { safe: false, reason: `existing branch '${branch}' cannot be resumed: ${proof.reason}` };
|
|
224
|
+
}
|
|
126
225
|
let baseRef = baseStartPoint;
|
|
127
226
|
const originRef = `origin/${baseStartPoint}`;
|
|
128
227
|
const originExists = await deps.runCommand("git", ["rev-parse", "--verify", "--quiet", originRef], { cwd: deps.cwd });
|
|
@@ -137,7 +236,9 @@ export async function isExistingBranchSafeToReuse(deps, branch, baseStartPoint,
|
|
|
137
236
|
// unchanged). Only the diagnosis and the remedy differ.
|
|
138
237
|
const remedy = classification === "succeeded_pr_not_attached"
|
|
139
238
|
? unattachedSuccessRemedy(branch)
|
|
140
|
-
:
|
|
239
|
+
: classification === "prior_attempt_of_this_job"
|
|
240
|
+
? priorAttemptRemedy(branch)
|
|
241
|
+
: staleLeftoverRemedy(branch, baseRef);
|
|
141
242
|
return {
|
|
142
243
|
safe: false,
|
|
143
244
|
reason: `existing branch '${branch}' is not an ancestor of ${baseRef}; ${remedy}`,
|
|
@@ -272,11 +373,28 @@ export async function createWorktreeForTicket(deps, key, branchOverrides, worktr
|
|
|
272
373
|
const branch = resolveBranchForTicket(key, branchOverrides);
|
|
273
374
|
try {
|
|
274
375
|
const exists = await branchExists(deps, branch);
|
|
376
|
+
// BAPI-1367: a caller-authorized prior head decides reuse by lineage proof
|
|
377
|
+
// alone, before ANY branch mutation (no switch, reset, clean, or alignment).
|
|
378
|
+
// It applies whether or not a local branch exists: with none, the proof reads
|
|
379
|
+
// `origin/<branch>` and the worktree is cut from exactly that ref.
|
|
380
|
+
let priorResume;
|
|
381
|
+
if (behavior.allowedPriorHead !== undefined) {
|
|
382
|
+
const safety = await isExistingBranchSafeToReuse(deps, branch, baseStartPoint, "prior_attempt_of_this_job", behavior.allowedPriorHead);
|
|
383
|
+
if (!safety.safe || safety.resume === undefined) {
|
|
384
|
+
return {
|
|
385
|
+
key,
|
|
386
|
+
branch,
|
|
387
|
+
status: "create-failed",
|
|
388
|
+
error: `stale worktree guard: ${safety.reason ?? "prior-attempt lineage could not be proven"}`,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
priorResume = safety.resume;
|
|
392
|
+
}
|
|
275
393
|
// F7 (conductor dispatch): refuse a stale pre-existing branch rather than
|
|
276
394
|
// silently building the worker on leftover code. BAPI-527: the ancestry
|
|
277
395
|
// check compares against the SAME effective base start point (branch name or
|
|
278
396
|
// fetched SHA) that a NEW branch would be cut from below.
|
|
279
|
-
if (exists && guardStaleWorktree) {
|
|
397
|
+
if (exists && guardStaleWorktree && priorResume === undefined) {
|
|
280
398
|
const safety = await isExistingBranchSafeToReuse(deps, branch, baseStartPoint, behavior.staleBranchClassification ?? "unknown");
|
|
281
399
|
if (!safety.safe) {
|
|
282
400
|
return {
|
|
@@ -287,7 +405,10 @@ export async function createWorktreeForTicket(deps, key, branchOverrides, worktr
|
|
|
287
405
|
};
|
|
288
406
|
}
|
|
289
407
|
}
|
|
290
|
-
|
|
408
|
+
// BAPI-1367: an origin-only resume is cut from exactly the ref whose lineage
|
|
409
|
+
// was just proven, never from whatever start point the caller supplied.
|
|
410
|
+
const startPoint = priorResume === "origin_branch" ? `origin/${branch}` : baseStartPoint;
|
|
411
|
+
const args = buildWtSwitchArgs(branch, exists, startPoint);
|
|
291
412
|
const result = await deps.runCommand(worktrunkBinary, args, { cwd: deps.cwd });
|
|
292
413
|
if (!commandSucceeded(result)) {
|
|
293
414
|
const reason = (result.stderr || result.stdout || "").trim();
|
|
@@ -299,6 +420,12 @@ export async function createWorktreeForTicket(deps, key, branchOverrides, worktr
|
|
|
299
420
|
};
|
|
300
421
|
}
|
|
301
422
|
const worktreePath = extractWorktreePath(result.stdout, deps.cwd, deps.platform);
|
|
423
|
+
// BAPI-1367: a lineage-approved resume stops here. Retained commits and
|
|
424
|
+
// uncommitted files ARE the work, so none of the destructive steps below
|
|
425
|
+
// (reset, clean, base verification) may run.
|
|
426
|
+
if (priorResume !== undefined) {
|
|
427
|
+
return { key, branch, status: "created", path: worktreePath, priorHeadResume: priorResume };
|
|
428
|
+
}
|
|
302
429
|
// BAPI-528: freshen a REUSED existing branch onto the pushed ref. A new
|
|
303
430
|
// branch was already cut from `baseStartPoint` (recovery sets that to
|
|
304
431
|
// `origin/<branch>`), so this only applies when the local branch pre-existed.
|