@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
|
@@ -59,7 +59,7 @@ export const PHASE_RESULT_ARTIFACT_VERSION = 1;
|
|
|
59
59
|
* it reaches the filesystem, rather than being sanitized into something that
|
|
60
60
|
* silently addresses a different ticket's artifact.
|
|
61
61
|
*/
|
|
62
|
-
const TICKET_KEY_PATTERN = /^[A-Za-z][A-Za-z0-
|
|
62
|
+
const TICKET_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_]*-\d+$/;
|
|
63
63
|
/** Terminal dispositions that mean "this step is done; do not redo it". */
|
|
64
64
|
const REENTRY_TERMINAL_DISPOSITIONS = new Set([
|
|
65
65
|
"executed",
|
|
@@ -74,6 +74,24 @@ const REENTRY_TERMINAL_DISPOSITIONS = new Set([
|
|
|
74
74
|
*/
|
|
75
75
|
export const INLINE_ROUTING_SOURCE = "inline:get_plan_metadata+phase_result_artifacts";
|
|
76
76
|
// ---------------------------------------------------------------------------
|
|
77
|
+
// Shapes
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
/**
|
|
80
|
+
* Why a checkpoint is not trusted as commit evidence. Closed vocabulary: these
|
|
81
|
+
* tokens are the only diagnostics a response may carry about a failed probe, so
|
|
82
|
+
* no raw git output, path, or credential can ride along.
|
|
83
|
+
*/
|
|
84
|
+
export const CHECKPOINT_STALE_REASONS = [
|
|
85
|
+
"not_ancestor",
|
|
86
|
+
"git_unavailable",
|
|
87
|
+
"invalid_sha",
|
|
88
|
+
"probe_failed",
|
|
89
|
+
"head_unavailable",
|
|
90
|
+
"checkpoint_changed",
|
|
91
|
+
"coverage_mismatch",
|
|
92
|
+
"not_evaluated",
|
|
93
|
+
];
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
77
95
|
// Path safety
|
|
78
96
|
// ---------------------------------------------------------------------------
|
|
79
97
|
function assertValidTicketKey(ticketKey) {
|
|
@@ -265,6 +283,9 @@ export async function loadInlinePhaseContext(options) {
|
|
|
265
283
|
const fingerprint = planFingerprint(metadata);
|
|
266
284
|
let ledger = [];
|
|
267
285
|
const artifactPaths = [];
|
|
286
|
+
// Latest record index per produce step, within the produce artifact's own list.
|
|
287
|
+
const produceLatestIndex = new Map();
|
|
288
|
+
let produceRecordCount = 0;
|
|
268
289
|
// Canonical phase order, not directory order: the ledger is chronological and
|
|
269
290
|
// production always precedes the phases that verify it.
|
|
270
291
|
for (const priorPhase of PLAN_PHASES) {
|
|
@@ -277,21 +298,72 @@ export async function loadInlinePhaseContext(options) {
|
|
|
277
298
|
// Re-check against the CURRENT metadata: an artifact that was valid when
|
|
278
299
|
// written must still describe steps this phase owns under the plan in play now.
|
|
279
300
|
const routable = assertStoredRecordsRoutable(artifact.records, metadata, priorPhase, relativePath);
|
|
301
|
+
if (priorPhase === "produce") {
|
|
302
|
+
produceRecordCount = routable.length;
|
|
303
|
+
routable.forEach((record, index) => produceLatestIndex.set(record.stepId, index));
|
|
304
|
+
}
|
|
280
305
|
ledger = [...ledger, ...sanitizePlanStepRecords(routable)];
|
|
281
306
|
artifactPaths.push(relativePath);
|
|
282
307
|
}
|
|
283
308
|
const checkpoint = await readInlineCheckpoint(docsDir, ticketKey);
|
|
284
309
|
if (checkpoint)
|
|
285
310
|
artifactPaths.push(checkpointRelativePath(ticketKey));
|
|
311
|
+
// Reachability is decided by the caller's git probe. Anything other than a
|
|
312
|
+
// confirmed `true` fails toward redo, and a checkpoint that changed between the
|
|
313
|
+
// probe and this load is not the one that was probed.
|
|
314
|
+
let reachable = options.checkpointReachable ?? "unknown";
|
|
315
|
+
let staleReason;
|
|
316
|
+
if (reachable === "unknown") {
|
|
317
|
+
staleReason = options.checkpointUnknownReason ?? "not_evaluated";
|
|
318
|
+
}
|
|
319
|
+
else if (reachable === false) {
|
|
320
|
+
staleReason = "not_ancestor";
|
|
321
|
+
}
|
|
322
|
+
if (checkpoint &&
|
|
323
|
+
reachable !== "unknown" &&
|
|
324
|
+
options.probedCheckpoint !== undefined &&
|
|
325
|
+
!sameCheckpoint(options.probedCheckpoint, checkpoint)) {
|
|
326
|
+
reachable = "unknown";
|
|
327
|
+
staleReason = "checkpoint_changed";
|
|
328
|
+
}
|
|
329
|
+
// A checkpoint covers the produce prefix only when its binding is intact.
|
|
330
|
+
const coverageIntact = checkpoint !== undefined &&
|
|
331
|
+
checkpoint.producedRecordCount > 0 &&
|
|
332
|
+
checkpoint.producedRecordCount <= produceRecordCount &&
|
|
333
|
+
checkpoint.producePlanFingerprint === fingerprint;
|
|
334
|
+
const coveredCount = checkpoint && reachable === true && coverageIntact
|
|
335
|
+
? checkpoint.producedRecordCount
|
|
336
|
+
: 0;
|
|
337
|
+
if (checkpoint &&
|
|
338
|
+
reachable === true &&
|
|
339
|
+
checkpoint.producedRecordCount > 0 &&
|
|
340
|
+
!coverageIntact) {
|
|
341
|
+
staleReason = "coverage_mismatch";
|
|
342
|
+
}
|
|
286
343
|
const current = currentLedgerState(ledger);
|
|
287
344
|
const currentRecordsByStep = {};
|
|
288
345
|
const terminalStepIds = [];
|
|
346
|
+
const uncommittedStepIds = [];
|
|
289
347
|
for (const [stepId, record] of current) {
|
|
290
348
|
currentRecordsByStep[stepId] = record;
|
|
291
|
-
if (REENTRY_TERMINAL_DISPOSITIONS.has(record.disposition))
|
|
349
|
+
if (!REENTRY_TERMINAL_DISPOSITIONS.has(record.disposition))
|
|
350
|
+
continue;
|
|
351
|
+
const producedAt = produceLatestIndex.get(stepId);
|
|
352
|
+
if (producedAt !== undefined && producedAt >= coveredCount) {
|
|
353
|
+
// Latest produce record is not inside the committed prefix: the work it
|
|
354
|
+
// describes is not evidenced at the evaluated HEAD.
|
|
355
|
+
uncommittedStepIds.push(stepId);
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
292
358
|
terminalStepIds.push(stepId);
|
|
359
|
+
}
|
|
293
360
|
}
|
|
294
361
|
terminalStepIds.sort((a, b) => a - b);
|
|
362
|
+
uncommittedStepIds.sort((a, b) => a - b);
|
|
363
|
+
const checkpointIsEvidence = checkpoint !== undefined && reachable === true && staleReason === undefined;
|
|
364
|
+
const ledgerNote = uncommittedStepIds.length > 0
|
|
365
|
+
? "Produce steps listed in uncommittedStepIds are recorded as done but no reachable checkpoint covers them, so redo them (checking for equivalent existing work first) and do not report them as already done."
|
|
366
|
+
: "";
|
|
295
367
|
return {
|
|
296
368
|
phase,
|
|
297
369
|
routingSource: INLINE_ROUTING_SOURCE,
|
|
@@ -306,12 +378,40 @@ export async function loadInlinePhaseContext(options) {
|
|
|
306
378
|
ledger,
|
|
307
379
|
currentRecordsByStep,
|
|
308
380
|
terminalStepIds,
|
|
381
|
+
uncommittedStepIds,
|
|
382
|
+
ledgerNote,
|
|
309
383
|
unresolved: unresolvedLedgerRecords(ledger),
|
|
310
|
-
...(
|
|
384
|
+
...(options.evaluatedHead ? { evaluatedHead: options.evaluatedHead } : {}),
|
|
385
|
+
...(checkpoint && checkpointIsEvidence
|
|
386
|
+
? { checkpoint: { branch: checkpoint.branch, sha: checkpoint.sha } }
|
|
387
|
+
: {}),
|
|
388
|
+
...(checkpoint && !checkpointIsEvidence
|
|
389
|
+
? {
|
|
390
|
+
staleCheckpoint: {
|
|
391
|
+
branch: checkpoint.branch,
|
|
392
|
+
sha: checkpoint.sha,
|
|
393
|
+
reason: staleReason ?? "not_evaluated",
|
|
394
|
+
},
|
|
395
|
+
}
|
|
396
|
+
: {}),
|
|
311
397
|
artifactPaths,
|
|
312
398
|
};
|
|
313
399
|
}
|
|
314
|
-
|
|
400
|
+
function sameCheckpoint(a, b) {
|
|
401
|
+
return (a.branch === b.branch &&
|
|
402
|
+
a.sha === b.sha &&
|
|
403
|
+
a.producedRecordCount === b.producedRecordCount &&
|
|
404
|
+
a.producePlanFingerprint === b.producePlanFingerprint);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Read and structurally validate the checkpoint artifact.
|
|
408
|
+
*
|
|
409
|
+
* Filesystem only. A legacy checkpoint with no coverage fields reads as covering
|
|
410
|
+
* zero produce records; it is never upgraded by inferring coverage from the
|
|
411
|
+
* current ledger. Malformed coverage, or a mis-versioned artifact, fails closed.
|
|
412
|
+
*/
|
|
413
|
+
export async function readInlineCheckpoint(docsDir, ticketKey) {
|
|
414
|
+
ticketKey = assertValidTicketKey(ticketKey);
|
|
315
415
|
const relativePath = checkpointRelativePath(ticketKey);
|
|
316
416
|
const absolutePath = resolveWithinRoot(docsDir, relativePath);
|
|
317
417
|
const parsed = await readJsonArtifact(absolutePath, relativePath);
|
|
@@ -333,7 +433,69 @@ async function readInlineCheckpoint(docsDir, ticketKey) {
|
|
|
333
433
|
artifact.sha.trim() === "") {
|
|
334
434
|
throw new PlanLedgerError(`${relativePath} is missing its branch or sha`);
|
|
335
435
|
}
|
|
336
|
-
|
|
436
|
+
const hasCount = artifact.produce_record_count !== undefined;
|
|
437
|
+
const fingerprintValue = artifact.produce_plan_fingerprint;
|
|
438
|
+
if (!hasCount) {
|
|
439
|
+
if (fingerprintValue !== undefined && fingerprintValue !== null) {
|
|
440
|
+
throw new PlanLedgerError(`${relativePath} has a produce fingerprint but no record count`);
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
branch: artifact.branch,
|
|
444
|
+
sha: artifact.sha,
|
|
445
|
+
producedRecordCount: 0,
|
|
446
|
+
producePlanFingerprint: null,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
const count = artifact.produce_record_count;
|
|
450
|
+
if (typeof count !== "number" || !Number.isInteger(count) || count < 0) {
|
|
451
|
+
throw new PlanLedgerError(`${relativePath} has an invalid produce_record_count`);
|
|
452
|
+
}
|
|
453
|
+
if (count > 0 && (typeof fingerprintValue !== "string" || fingerprintValue === "")) {
|
|
454
|
+
throw new PlanLedgerError(`${relativePath} covers produce records but has no valid produce_plan_fingerprint`);
|
|
455
|
+
}
|
|
456
|
+
if (count === 0 &&
|
|
457
|
+
fingerprintValue !== undefined &&
|
|
458
|
+
fingerprintValue !== null &&
|
|
459
|
+
typeof fingerprintValue !== "string") {
|
|
460
|
+
throw new PlanLedgerError(`${relativePath} has an invalid produce_plan_fingerprint`);
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
branch: artifact.branch,
|
|
464
|
+
sha: artifact.sha,
|
|
465
|
+
producedRecordCount: count,
|
|
466
|
+
producePlanFingerprint: typeof fingerprintValue === "string" && fingerprintValue !== "" ? fingerprintValue : null,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* How much of the produce artifact a checkpoint written now would cover.
|
|
471
|
+
*
|
|
472
|
+
* Structural validation only, with no plan metadata fetch: the count and the
|
|
473
|
+
* artifact's stored fingerprint are read as written. An absent artifact covers
|
|
474
|
+
* zero records, and nothing is created to calculate that.
|
|
475
|
+
*/
|
|
476
|
+
async function readProduceCoverage(docsDir, ticketKey) {
|
|
477
|
+
const relativePath = phaseResultRelativePath(ticketKey, "produce");
|
|
478
|
+
const absolutePath = resolveWithinRoot(docsDir, relativePath);
|
|
479
|
+
const parsed = await readJsonArtifact(absolutePath, relativePath);
|
|
480
|
+
if (parsed === undefined)
|
|
481
|
+
return { count: 0, fingerprint: null };
|
|
482
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
483
|
+
throw new PlanLedgerError(`${relativePath} is not a phase-result artifact object`);
|
|
484
|
+
}
|
|
485
|
+
const artifact = parsed;
|
|
486
|
+
if (artifact.artifact_version !== PHASE_RESULT_ARTIFACT_VERSION) {
|
|
487
|
+
throw new PlanLedgerError(`${relativePath} has unsupported artifact_version ${String(artifact.artifact_version)}; expected ${PHASE_RESULT_ARTIFACT_VERSION}`);
|
|
488
|
+
}
|
|
489
|
+
if (artifact.ticket_key !== ticketKey || artifact.phase !== "produce") {
|
|
490
|
+
throw new PlanLedgerError(`${relativePath} does not describe the produce phase of '${ticketKey}'`);
|
|
491
|
+
}
|
|
492
|
+
if (typeof artifact.plan_fingerprint !== "string" || artifact.plan_fingerprint === "") {
|
|
493
|
+
throw new PlanLedgerError(`${relativePath} has no plan_fingerprint`);
|
|
494
|
+
}
|
|
495
|
+
if (!Array.isArray(artifact.records)) {
|
|
496
|
+
throw new PlanLedgerError(`${relativePath} has no records array`);
|
|
497
|
+
}
|
|
498
|
+
return { count: artifact.records.length, fingerprint: artifact.plan_fingerprint };
|
|
337
499
|
}
|
|
338
500
|
// ---------------------------------------------------------------------------
|
|
339
501
|
// Writing
|
|
@@ -435,6 +597,10 @@ export async function writeInlineCheckpoint(options) {
|
|
|
435
597
|
if (checkpoint.pushed !== true || checkpoint.remoteMatchesHead !== true) {
|
|
436
598
|
throw new PlanLedgerError("checkpoint must report pushed and remoteMatchesHead true; a checkpoint that is not on origin is not a checkpoint");
|
|
437
599
|
}
|
|
600
|
+
// Coverage is derived here from the produce artifact as it stands, never taken
|
|
601
|
+
// from the caller: the push facts above are the caller's claim, but what the
|
|
602
|
+
// push covers is a fact about the ledger this module owns.
|
|
603
|
+
const coverage = await readProduceCoverage(docsDir, ticketKey);
|
|
438
604
|
const relativePath = checkpointRelativePath(ticketKey);
|
|
439
605
|
const absolutePath = resolveWithinRoot(docsDir, relativePath);
|
|
440
606
|
const artifact = {
|
|
@@ -444,6 +610,8 @@ export async function writeInlineCheckpoint(options) {
|
|
|
444
610
|
sha,
|
|
445
611
|
pushed: true,
|
|
446
612
|
remote_matches_head: true,
|
|
613
|
+
produce_record_count: coverage.count,
|
|
614
|
+
produce_plan_fingerprint: coverage.fingerprint,
|
|
447
615
|
};
|
|
448
616
|
await writeAtomically(absolutePath, relativePath, artifact);
|
|
449
617
|
return { branch, sha, artifactPath: relativePath };
|