@bridge_gpt/mcp-server 0.2.16 → 0.2.18

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.
Files changed (45) hide show
  1. package/build/agents.generated.js +2 -2
  2. package/build/commands.generated.js +6 -6
  3. package/build/conductor/bridge-api-client.js +191 -11
  4. package/build/conductor/claude-hook.js +22 -4
  5. package/build/conductor/cli.js +11 -13
  6. package/build/conductor/done-gate.js +5 -0
  7. package/build/conductor/epic-reconcile.js +62 -13
  8. package/build/conductor/epic-runtime.js +447 -35
  9. package/build/conductor/epic-state.js +517 -63
  10. package/build/conductor/errors.js +41 -0
  11. package/build/conductor/event-accessors.js +234 -0
  12. package/build/conductor/file-scope-guard.js +201 -0
  13. package/build/conductor/github-mergeability.js +85 -0
  14. package/build/conductor/local-merge.js +47 -1
  15. package/build/conductor/merge-identity.js +41 -0
  16. package/build/conductor/merge-ledger.js +13 -68
  17. package/build/conductor/plan.js +12 -2
  18. package/build/conductor/pr-discovery.js +11 -1
  19. package/build/conductor/supervisor-config.js +4 -39
  20. package/build/conductor/supervisor-escalation.js +10 -26
  21. package/build/conductor/supervisor-ledger.js +5 -12
  22. package/build/conductor/supervisor-message-relay.js +2 -5
  23. package/build/conductor/supervisor-notification.js +1 -1
  24. package/build/conductor/supervisor-runtime.js +12 -54
  25. package/build/conductor/supervisor-state.js +4 -18
  26. package/build/conductor/supervisor-types.js +2 -2
  27. package/build/conductor/taxonomy.js +4 -0
  28. package/build/conductor-bin.js +2333 -666
  29. package/build/conductor-claude-hook-bin.js +4 -2
  30. package/build/doctor.js +32 -0
  31. package/build/index.js +10125 -8522
  32. package/build/install-bridge.js +25 -8
  33. package/build/install-doctor.js +387 -0
  34. package/build/pipelines.generated.js +30 -5
  35. package/build/regression-check.js +53 -1
  36. package/build/review-tickets.js +175 -21
  37. package/build/start-tickets-conductor.js +22 -6
  38. package/build/start-tickets-prereqs.js +33 -3
  39. package/build/start-tickets.js +122 -22
  40. package/build/version.generated.js +1 -1
  41. package/package.json +5 -5
  42. package/pipelines/review-ticket.json +24 -2
  43. package/public/css/main.min.css +3272 -1
  44. package/public/css/main.min.css.map +1 -1
  45. package/smoke-test/SMOKE-TEST.md +4 -2
@@ -405,7 +405,10 @@ export function getDefaultSpawnTerminalTabForPlatform(platform) {
405
405
  * are always honored). Returns a structured error for unsupported platforms;
406
406
  * never throws.
407
407
  */
408
- export function resolveStartTicketsPlatformConfig(deps, agent, autoApprove = false, conductorEnabled = false, repoName = null) {
408
+ export function resolveStartTicketsPlatformConfig(deps, agent, autoApprove = false, conductorEnabled = false, repoName = null,
409
+ // BAPI-494: a conductor remediation re-dispatch. Appends the full-suite finalize
410
+ // instruction to the resume-mode worker's prompt.
411
+ resumeMode = false) {
409
412
  if (!isSupportedStartTicketsPlatform(deps.platform)) {
410
413
  return { ok: false, error: unsupportedPlatformMessage(deps.platform) };
411
414
  }
@@ -417,7 +420,7 @@ export function resolveStartTicketsPlatformConfig(deps, agent, autoApprove = fal
417
420
  worktrunkBinary: resolveWorktrunkBinary(platform, deps.env),
418
421
  // Inject the resolved repo identity so the spawned worktree session never
419
422
  // falls back to the basename-derived repo name (the 403 root cause).
420
- buildAgentShellCommand: (key, worktreePath, modelAlias) => prependRepoNameEnvAssignment(buildAgentShellCommand(agent, key, worktreePath, platform, autoApprove, modelAlias, conductorEnabled), repoName, platform),
423
+ buildAgentShellCommand: (key, worktreePath, modelAlias) => prependRepoNameEnvAssignment(buildAgentShellCommand(agent, key, worktreePath, platform, autoApprove, modelAlias, conductorEnabled, resumeMode), repoName, platform),
421
424
  spawnTerminalTab: deps.spawnTerminalTab,
422
425
  },
423
426
  };
@@ -714,6 +717,42 @@ export async function refreshBaseBranch(deps, options) {
714
717
  export async function refreshMainBranch(deps, options) {
715
718
  return refreshBaseBranch(deps, { refreshMain: options.refreshMain, baseBranch: "main" });
716
719
  }
720
+ /**
721
+ * Non-mutating counterpart to {@link refreshBaseBranch}: fetches
722
+ * `origin/<baseBranch>` and resolves the fetched tip to an immutable commit
723
+ * SHA, WITHOUT ever fast-forwarding or force-moving any local branch ref (no
724
+ * `git merge --ff-only`, no `git branch --force`). Used by review-grounding
725
+ * (BAPI-474), which must read a pinned base tree without touching the user's
726
+ * working tree, index, stash, or local branch refs.
727
+ *
728
+ * Validates `baseBranch` with {@link validateBranchName} first so an
729
+ * injection-shaped ref name is rejected before any git invocation. Every git
730
+ * call uses an argv array (never a shell string), consistent with
731
+ * {@link refreshBaseBranch}.
732
+ */
733
+ export async function fetchAndResolveBaseSha(deps, baseBranch) {
734
+ const validationError = validateBranchName(baseBranch);
735
+ if (validationError) {
736
+ return { ok: false, error: `Invalid base branch '${baseBranch}': ${validationError}` };
737
+ }
738
+ const fetch = await deps.runCommand("git", ["fetch", "origin", baseBranch], {
739
+ cwd: deps.cwd,
740
+ });
741
+ if (!commandSucceeded(fetch)) {
742
+ return {
743
+ ok: false,
744
+ error: `git fetch origin ${baseBranch} failed. Check your network and 'git remote get-url origin', or pass --no-refresh-base to skip.`,
745
+ };
746
+ }
747
+ const resolve = await deps.runCommand("git", ["rev-parse", "--verify", `origin/${baseBranch}^{commit}`], { cwd: deps.cwd });
748
+ if (!commandSucceeded(resolve)) {
749
+ return {
750
+ ok: false,
751
+ error: `Failed to resolve origin/${baseBranch} to a commit SHA after fetch (git rev-parse --verify failed).`,
752
+ };
753
+ }
754
+ return { ok: true, base_sha: resolve.stdout.trim() };
755
+ }
717
756
  // ---------------------------------------------------------------------------
718
757
  // Concurrency + worktree creation
719
758
  // ---------------------------------------------------------------------------
@@ -956,6 +995,31 @@ export function buildConductorMessageRelayLaunchInstruction() {
956
995
  "emits the gate event; it does not merge). If a tool or the conductor identity is " +
957
996
  "unavailable, continue your task without derailing.");
958
997
  }
998
+ /**
999
+ * BAPI-494: the resume-mode remediation finalize instruction. A conductor
1000
+ * re-dispatch (start-tickets resume mode) is spawned to fix a `blocked` ticket —
1001
+ * for a `merge.conflict` block the worker rebases + resolves conflicts. Catalog
1002
+ * E1/F3b proved a clean TEXTUAL merge can still hide a SEMANTIC break (branch A
1003
+ * adds a helper; branch B adds a contract test over all helpers), which only the
1004
+ * FULL suite catches — so this instruction requires the worker to run the full
1005
+ * project test suite (the same gate the advisory pre-push hook enforces) and only
1006
+ * push/complete on green, escalating otherwise.
1007
+ *
1008
+ * Single line (no newlines, no `;`, no quotes/apostrophes) so it stays safe when
1009
+ * single-quoted into a shell command and embedded in terminal-launcher args.
1010
+ */
1011
+ export function buildResumeModeRemediationFinalizeInstruction() {
1012
+ return ("Resume-mode remediation finalize: you were re-dispatched to fix a blocked ticket " +
1013
+ "(a merge conflict, a CI failure, or requested review changes). First rebase against " +
1014
+ "the current base branch and resolve the merge conflicts. A clean textual merge can " +
1015
+ "still break behavior, so inspect for semantic conflicts even when there are no textual " +
1016
+ "conflict markers. Before you push or mark the ticket complete, run the full test suite " +
1017
+ "for the project (the full unit suite, the same gate enforced by the advisory pre-push " +
1018
+ "hook described in CLAUDE.md under the CI cost model and advisory pre-push hook section) " +
1019
+ "and do not rely on targeted subsets as your only verification. Push and mark the ticket " +
1020
+ "complete only after the full suite is green. If you cannot make the full suite pass, " +
1021
+ "report the ticket blocked and escalate rather than pushing a green-looking but broken merge.");
1022
+ }
959
1023
  /**
960
1024
  * The starter prompt handed to the selected agent. Identical for every agent.
961
1025
  * When `autoApprove` is set, the implementation agent runs hands-off
@@ -966,15 +1030,23 @@ export function buildConductorMessageRelayLaunchInstruction() {
966
1030
  * flag). A plain run returns the bare `/implement-ticket <KEY> [--auto]` so the
967
1031
  * worker is not told to poll `check_messages` for a conductor that is not
968
1032
  * running.
1033
+ *
1034
+ * BAPI-494: when `resumeMode` is set (a conductor remediation re-dispatch), the
1035
+ * full-suite finalize instruction is appended so the rebase/resolve worker proves
1036
+ * semantic compatibility before pushing. Scoped to resume mode only — a normal
1037
+ * fresh dispatch is unaffected.
969
1038
  */
970
1039
  export function buildAgentPrompt(key, opts = {}) {
971
1040
  // `modelAlias` is accepted for signature consistency only — the model is
972
1041
  // injected as a `--model` flag (see buildAgentInvocationArgv), never embedded
973
1042
  // in the prompt text.
974
1043
  const command = `/implement-ticket ${key}${opts.autoApprove ? " --auto" : ""}`;
975
- return opts.conductorEnabled
976
- ? `${command} ${buildConductorMessageRelayLaunchInstruction()}`
977
- : command;
1044
+ const parts = [command];
1045
+ if (opts.conductorEnabled)
1046
+ parts.push(buildConductorMessageRelayLaunchInstruction());
1047
+ if (opts.resumeMode)
1048
+ parts.push(buildResumeModeRemediationFinalizeInstruction());
1049
+ return parts.join(" ");
978
1050
  }
979
1051
  /**
980
1052
  * Build the ordered argv for an agent invocation:
@@ -1013,13 +1085,13 @@ export function buildAgentInvocation(agent, prompt, quote, modelAlias) {
1013
1085
  }
1014
1086
  }
1015
1087
  /** POSIX agent shell command: `cd '<path>' && <agent> [--model '<alias>'] '<prompt>'`. */
1016
- export function buildPosixAgentShellCommand(agent, key, worktreePath, autoApprove = false, modelAlias, conductorEnabled = false) {
1017
- const invocation = buildAgentInvocation(agent, buildAgentPrompt(key, { autoApprove, conductorEnabled }), (p) => `'${shSquoteInner(p)}'`, modelAlias);
1088
+ export function buildPosixAgentShellCommand(agent, key, worktreePath, autoApprove = false, modelAlias, conductorEnabled = false, resumeMode = false) {
1089
+ const invocation = buildAgentInvocation(agent, buildAgentPrompt(key, { autoApprove, conductorEnabled, resumeMode }), (p) => `'${shSquoteInner(p)}'`, modelAlias);
1018
1090
  return `cd '${shSquoteInner(worktreePath)}' && ${invocation}`;
1019
1091
  }
1020
1092
  /** PowerShell agent shell command: `Set-Location -LiteralPath '<path>'; <agent> [--model '<alias>'] '<prompt>'`. */
1021
- export function buildPowerShellAgentShellCommand(agent, key, worktreePath, autoApprove = false, modelAlias, conductorEnabled = false) {
1022
- const invocation = buildAgentInvocation(agent, buildAgentPrompt(key, { autoApprove, conductorEnabled }), powershellSquote, modelAlias);
1093
+ export function buildPowerShellAgentShellCommand(agent, key, worktreePath, autoApprove = false, modelAlias, conductorEnabled = false, resumeMode = false) {
1094
+ const invocation = buildAgentInvocation(agent, buildAgentPrompt(key, { autoApprove, conductorEnabled, resumeMode }), powershellSquote, modelAlias);
1023
1095
  return `Set-Location -LiteralPath ${powershellSquote(worktreePath)}; ${invocation}`;
1024
1096
  }
1025
1097
  /**
@@ -1030,10 +1102,10 @@ export function buildPowerShellAgentShellCommand(agent, key, worktreePath, autoA
1030
1102
  * injected as `--model` at the spawn boundary. `conductorEnabled` appends the
1031
1103
  * BAPI-397 message-relay instruction to the prompt (opt-in via `--conductor`).
1032
1104
  */
1033
- export function buildAgentShellCommand(agent, key, worktreePath, platform = "darwin", autoApprove = false, modelAlias, conductorEnabled = false) {
1105
+ export function buildAgentShellCommand(agent, key, worktreePath, platform = "darwin", autoApprove = false, modelAlias, conductorEnabled = false, resumeMode = false) {
1034
1106
  if (platform === "win32")
1035
- return buildPowerShellAgentShellCommand(agent, key, worktreePath, autoApprove, modelAlias, conductorEnabled);
1036
- return buildPosixAgentShellCommand(agent, key, worktreePath, autoApprove, modelAlias, conductorEnabled);
1107
+ return buildPowerShellAgentShellCommand(agent, key, worktreePath, autoApprove, modelAlias, conductorEnabled, resumeMode);
1108
+ return buildPosixAgentShellCommand(agent, key, worktreePath, autoApprove, modelAlias, conductorEnabled, resumeMode);
1037
1109
  }
1038
1110
  /**
1039
1111
  * Build the shell command run inside a spawned tab/session for an ARBITRARY
@@ -1090,15 +1162,36 @@ export function buildTerminalAppleScript(shellCommand, title) {
1090
1162
  "end tell",
1091
1163
  ].join("\n");
1092
1164
  }
1165
+ /**
1166
+ * Build the shell command that sets an iTerm2 session **badge** to `badgeText`
1167
+ * via the proprietary `OSC 1337 ; SetBadgeFormat` escape (base64 payload, per
1168
+ * the iTerm2 spec). The badge is a large translucent per-pane label drawn in
1169
+ * the session corner.
1170
+ *
1171
+ * Why a badge and not just the session `name`: iTerm2 lets a running program
1172
+ * overwrite the session name via ordinary title escapes (`OSC 0/1/2`), and
1173
+ * Claude Code re-sets its terminal title continuously while it works — so the
1174
+ * `set name` label is clobbered within a fraction of a second (empirically the
1175
+ * tab ends up reading "claude working", never "<KEY> Implementation"). The
1176
+ * badge lives in a separate namespace those title escapes never touch, so it
1177
+ * sticks for the life of the pane. `printf` emits the escape from inside the
1178
+ * spawned shell, before the agent command runs.
1179
+ */
1180
+ export function itermBadgeShellCommand(badgeText) {
1181
+ const b64 = Buffer.from(badgeText, "utf8").toString("base64");
1182
+ return `printf '\\033]1337;SetBadgeFormat=%s\\007' '${b64}'`;
1183
+ }
1093
1184
  /**
1094
1185
  * Generate AppleScript that runs `shellCommand` in an iTerm2 tab. We set the
1095
- * session `name` (which drives the tab title) so the label sticks rather than
1096
- * being overwritten by the running agent's program title.
1186
+ * session `name` (labels the tab until the agent starts re-titling) and, when a
1187
+ * `badgeText` is supplied, pin an agent-proof iTerm badge so the pane stays
1188
+ * identifiable even after Claude Code overrides the title — see
1189
+ * {@link itermBadgeShellCommand}.
1097
1190
  */
1098
- export function buildITermAppleScript(shellCommand, title) {
1191
+ export function buildITermAppleScript(shellCommand, title, badgeText) {
1099
1192
  const esc = applescriptDquoteInner(shellCommand);
1100
1193
  const titleEsc = applescriptDquoteInner(title);
1101
- return [
1194
+ const lines = [
1102
1195
  'tell application "iTerm"',
1103
1196
  " activate",
1104
1197
  " if (count of windows) = 0 then",
@@ -1108,10 +1201,15 @@ export function buildITermAppleScript(shellCommand, title) {
1108
1201
  " end if",
1109
1202
  " tell spawnedSession",
1110
1203
  ` set name to "${titleEsc}"`,
1111
- ` write text "${esc}"`,
1112
- " end tell",
1113
- "end tell",
1114
- ].join("\n");
1204
+ ];
1205
+ if (badgeText) {
1206
+ const badgeEsc = applescriptDquoteInner(itermBadgeShellCommand(badgeText));
1207
+ lines.push(` write text "${badgeEsc}"`);
1208
+ }
1209
+ lines.push(` write text "${esc}"`);
1210
+ lines.push(" end tell");
1211
+ lines.push("end tell");
1212
+ return lines.join("\n");
1115
1213
  }
1116
1214
  /**
1117
1215
  * Spawn a single macOS terminal tab running `shellCommand`. Selects the
@@ -1123,7 +1221,7 @@ export function buildITermAppleScript(shellCommand, title) {
1123
1221
  export async function spawnMacOSTerminalTab(deps, terminal, shellCommand, context) {
1124
1222
  const title = terminalTitleForTicket(context?.key ?? "");
1125
1223
  const script = terminal === "iterm"
1126
- ? buildITermAppleScript(shellCommand, title)
1224
+ ? buildITermAppleScript(shellCommand, title, context?.key || undefined)
1127
1225
  : buildTerminalAppleScript(shellCommand, title);
1128
1226
  const result = await deps.runCommand("osascript", ["-e", script]);
1129
1227
  if (commandSucceeded(result))
@@ -2490,7 +2588,9 @@ export async function orchestrateStartTickets(deps, options, overrides = {}) {
2490
2588
  ".bridge/config). Spawned worktrees may fall back to the directory name and " +
2491
2589
  "hit 403 'repository not registered' if it differs from the Bridge API project name.");
2492
2590
  }
2493
- const platformConfig = resolveStartTicketsPlatformConfig(deps, agent, options.autoApprove, options.conductorEnabled ?? false, resolvedRepoName);
2591
+ const platformConfig = resolveStartTicketsPlatformConfig(deps, agent, options.autoApprove, options.conductorEnabled ?? false, resolvedRepoName,
2592
+ // BAPI-494: resume-mode dispatches get the full-suite remediation finalize prompt.
2593
+ options.resumeMode ?? false);
2494
2594
  if (!platformConfig.ok)
2495
2595
  return { ok: false, error: platformConfig.error };
2496
2596
  const refresh = await refreshBaseBranch(deps, {
@@ -1,2 +1,2 @@
1
1
  // AUTO-GENERATED — do not edit manually. Regenerate with: npm run build
2
- export const VERSION = "0.2.16";
2
+ export const VERSION = "0.2.18";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bridge_gpt/mcp-server",
3
- "version": "0.2.16",
3
+ "version": "0.2.18",
4
4
  "description": "Bridge API MCP server — exposes Jira endpoints as MCP tools for Claude Code agents",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -27,7 +27,7 @@
27
27
  "check:version-generated": "node scripts/bundle-version.js && node scripts/check-version-generated.js",
28
28
  "postbuild": "node scripts/prepend-shebang.cjs",
29
29
  "start": "node build/index.js",
30
- "test": "node --test build/pipeline-utils.test.js build/update-check.test.js build/cli-upgrade.test.js build/decision-page-schema.test.js build/decision-page-template.test.js build/bundle-pipelines.test.js build/instructions-contract.test.js build/pipeline-orchestrator-persistence.test.js build/pipeline-orchestrator-execution.test.js build/pipeline-orchestrator-integration.test.js build/index-static.test.js build/index-resolvers.test.js build/index-project-root.test.js build/index-pipelines.test.js build/index.test.js build/bridge-config.test.js build/credential-store.test.js build/agent-config-credential-migration.test.js build/mcp-invoke.test.js build/mcp-provisioning.test.js build/third-party-mcp-targets.test.js build/git-ignore-utils.test.js build/credential-materialization.test.js build/mcp-registration-doctor.test.js build/secret-safety.test.js build/start-tickets.test.js build/review-tickets.test.js build/start-tickets-base-branch.test.js build/agent-registry.test.js build/agent-registry.model-routing.test.js build/start-tickets.shell-model-routing.test.js build/start-tickets.bridge-api-model-routing.test.js build/start-tickets.tier-fetch-model-routing.test.js build/start-tickets.resolve-model-routing.test.js build/start-tickets.orchestrate-model-routing.test.js build/start-tickets.routing-diagnostics.test.js build/start-tickets-repo.test.js build/start-tickets-credential-invariants.static.test.js build/credentials-cli.test.js build/start-tickets-prereqs.test.js build/regression-check.test.js build/doctor.test.js build/install-bridge.test.js build/init.test.js build/resolveUploadAttachment.test.js build/package-static.test.js build/chain-utils.test.js build/chain-orchestrator.test.js build/scheduler-backends/types.test.js build/scheduler-backends/escaping.test.js build/scheduler-backends/launchd.test.js build/scheduler-backends/task-scheduler.test.js build/scheduler-backends/systemd-user.test.js build/scheduler-backends/at-fallback.test.js build/scheduler-backends/index.test.js build/command-catalog.test.js build/scheduled-prompt.test.js build/agent-launchers/claude.test.js build/agent-launchers/cursor.test.js build/agent-launchers/index.test.js build/schedule-store.test.js build/schedule-run.test.js build/agent-capabilities/cli.test.js build/agent-capabilities/runner.test.js build/agent-capabilities/probes.test.js build/agent-capabilities/reporter.test.js build/conductor/taxonomy-and-errors.test.js build/conductor/redaction-normalization.test.js build/conductor/claude-hook.test.js build/conductor/git-ci-types.test.js build/conductor/done-gate.test.js build/conductor/git-ci-taxonomy-payload.test.js build/conductor/bridge-api-client.test.js build/conductor/plan.test.js build/conductor/producer-ledger.test.js build/conductor/spec-review-producer.test.js build/conductor/git-producer.test.js build/conductor/git-hooks.test.js build/conductor/store-migration.test.js build/conductor/pr-discovery.test.js build/conductor/pr-ci-producer.test.js build/conductor/pr-review-producer.test.js build/conductor/doctor.test.js build/conductor/index-poll-ci-producer.test.js build/start-tickets-conductor.test.js build/start-tickets-conductor.spawn.test.js build/conductor/supervisor-config.test.js build/conductor/supervisor-ledger.test.js build/conductor/supervisor-state-reducer.test.js build/conductor/supervisor-housekeeping-projection.test.js build/conductor/supervisor-escalation.test.js build/conductor/supervisor-judgment.test.js build/conductor/supervisor-judgment-python-adapter.test.js build/conductor/supervisor-runtime.test.js build/conductor/supervisor-store-projection.test.js build/conductor/supervisor-cli.test.js build/conductor/supervisor-start-tickets.test.js build/conductor/supervisor-message-relay.test.js build/conductor/supervisor-state-message-events.test.js build/conductor/store-message-relay.test.js build/start-tickets-message-relay.test.js build/conductor/merge-ledger.test.js build/conductor/local-merge.test.js build/conductor/supervisor-merge.test.js build/conductor/bridge-api-merge-client.test.js build/conductor/bridge-api-epic-client.test.js build/conductor/supervisor-merge-runtime-state.test.js build/conductor/epic-state.test.js build/conductor/epic-reconcile.test.js build/conductor/epic-runtime.test.js build/conductor/epic-tick-sequence.test.js build/conductor/epic-runtime-post-action.test.js build/mcp-profile.test.js build/mcp-profile-registration.test.js build/tools-budget.test.js build/integration/measure-tools.test.js build/sfcc/config.test.js build/sfcc/ocapi-shape.test.js build/sfcc/output.test.js build/sfcc/credentials.test.js && node --experimental-test-module-mocks --test build/index-heavy-read-truncation.test.js build/index-artifacts.test.js build/index-brainstorm-filenames.test.js build/index-output-path.test.js build/index-generate-decision-page.test.js build/index-generate-decision-page.integration.test.js build/conductor/paths.test.js build/conductor/store-lifecycle.test.js build/conductor/store-queries.test.js build/conductor/tools.test.js build/conductor/cli.test.js build/conductor/security-regressions.test.js build/conductor/git-inspection.test.js build/conductor/tools-done-gate.test.js build/conductor/cli-git-hooks.test.js build/sfcc/client.test.js build/sfcc/tool-wrapper.test.js build/sfcc/setup-status.test.js build/sfcc/permissions.test.js build/sfcc/register.test.js build/sfcc/reads-system-object.test.js build/sfcc/reads-custom-object-def.test.js build/sfcc/reads-site-preference.test.js",
30
+ "test": "node --test --test-force-exit build/pipeline-utils.test.js build/update-check.test.js build/cli-upgrade.test.js build/decision-page-schema.test.js build/decision-page-template.test.js build/bundle-pipelines.test.js build/instructions-contract.test.js build/pipeline-orchestrator-persistence.test.js build/pipeline-orchestrator-execution.test.js build/pipeline-orchestrator-integration.test.js build/index-static.test.js build/config-fields.static.test.js build/index-resolvers.test.js build/index-project-root.test.js build/index-pipelines.test.js build/index.test.js build/bridge-config.test.js build/credential-store.test.js build/agent-config-credential-migration.test.js build/mcp-invoke.test.js build/mcp-provisioning.test.js build/third-party-mcp-targets.test.js build/git-ignore-utils.test.js build/credential-materialization.test.js build/mcp-registration-doctor.test.js build/secret-safety.test.js build/start-tickets.test.js build/review-tickets.test.js build/start-tickets-base-branch.test.js build/agent-registry.test.js build/agent-registry.model-routing.test.js build/start-tickets.shell-model-routing.test.js build/start-tickets.bridge-api-model-routing.test.js build/start-tickets.tier-fetch-model-routing.test.js build/start-tickets.resolve-model-routing.test.js build/start-tickets.orchestrate-model-routing.test.js build/start-tickets.routing-diagnostics.test.js build/start-tickets-repo.test.js build/start-tickets-credential-invariants.static.test.js build/credentials-cli.test.js build/start-tickets-prereqs.test.js build/regression-check.test.js build/doctor.test.js build/install-doctor.test.js build/install-bridge.test.js build/init.test.js build/resolveUploadAttachment.test.js build/package-static.test.js build/chain-utils.test.js build/chain-orchestrator.test.js build/scheduler-backends/types.test.js build/scheduler-backends/escaping.test.js build/scheduler-backends/launchd.test.js build/scheduler-backends/task-scheduler.test.js build/scheduler-backends/systemd-user.test.js build/scheduler-backends/at-fallback.test.js build/scheduler-backends/index.test.js build/command-catalog.test.js build/scheduled-prompt.test.js build/agent-launchers/claude.test.js build/agent-launchers/cursor.test.js build/agent-launchers/index.test.js build/schedule-store.test.js build/schedule-run.test.js build/agent-capabilities/cli.test.js build/agent-capabilities/runner.test.js build/agent-capabilities/probes.test.js build/agent-capabilities/reporter.test.js build/conductor/taxonomy-and-errors.test.js build/conductor/github-mergeability.test.js build/conductor/merge-conflict-routing.test.js build/conductor/redaction-normalization.test.js build/conductor/claude-hook.test.js build/conductor/git-ci-types.test.js build/conductor/done-gate.test.js build/conductor/git-ci-taxonomy-payload.test.js build/conductor/bridge-api-client.test.js build/conductor/plan.test.js build/conductor/producer-ledger.test.js build/conductor/spec-review-producer.test.js build/conductor/git-producer.test.js build/conductor/git-hooks.test.js build/conductor/store-migration.test.js build/conductor/pr-discovery.test.js build/conductor/pr-ci-producer.test.js build/conductor/pr-review-producer.test.js build/conductor/doctor.test.js build/conductor/index-poll-ci-producer.test.js build/start-tickets-conductor.test.js build/start-tickets-conductor.spawn.test.js build/conductor/supervisor-config.test.js build/conductor/supervisor-ledger.test.js build/conductor/supervisor-state-reducer.test.js build/conductor/supervisor-housekeeping-projection.test.js build/conductor/supervisor-escalation.test.js build/conductor/supervisor-retired-judgment.static.test.js build/conductor/supervisor-runtime.test.js build/conductor/supervisor-store-projection.test.js build/conductor/supervisor-cli.test.js build/conductor/supervisor-start-tickets.test.js build/conductor/supervisor-message-relay.test.js build/conductor/supervisor-state-message-events.test.js build/conductor/store-message-relay.test.js build/start-tickets-message-relay.test.js build/conductor/event-accessors.test.js build/conductor/merge-ledger.test.js build/conductor/local-merge.test.js build/conductor/supervisor-merge.test.js build/conductor/bridge-api-merge-client.test.js build/conductor/bridge-api-epic-client.test.js build/conductor/supervisor-merge-runtime-state.test.js build/conductor/epic-state.test.js build/conductor/epic-reconcile.test.js build/conductor/epic-runtime.test.js build/conductor/epic-tick-sequence.test.js build/conductor/epic-runtime-post-action.test.js build/conductor/file-scope-guard.test.js build/conductor/file-scope-guard.integration.test.js build/mcp-profile.test.js build/mcp-profile-registration.test.js build/tools-budget.test.js build/integration/measure-tools.test.js build/sfcc/config.test.js build/sfcc/ocapi-shape.test.js build/sfcc/output.test.js build/sfcc/credentials.test.js && node --experimental-test-module-mocks --test --test-force-exit build/index-heavy-read-truncation.test.js build/index-artifacts.test.js build/index-brainstorm-filenames.test.js build/index-output-path.test.js build/index-generate-decision-page.test.js build/index-generate-decision-page.integration.test.js build/conductor/paths.test.js build/conductor/store-lifecycle.test.js build/conductor/store-queries.test.js build/conductor/tools.test.js build/conductor/cli.test.js build/conductor/security-regressions.test.js build/conductor/git-inspection.test.js build/conductor/tools-done-gate.test.js build/conductor/cli-git-hooks.test.js build/sfcc/client.test.js build/sfcc/tool-wrapper.test.js build/sfcc/setup-status.test.js build/sfcc/permissions.test.js build/sfcc/register.test.js build/sfcc/reads-system-object.test.js build/sfcc/reads-custom-object-def.test.js build/sfcc/reads-site-preference.test.js",
31
31
  "test:integration": "node --test build/integration/refresh-main.integration.test.js build/integration/start-tickets.integration.test.js build/integration/doctor.integration.test.js build/integration/agent-capabilities.integration.test.js build/integration/conductor-producer.integration.test.js build/integration/conductor-message-relay.integration.test.js",
32
32
  "test:smoke": "node --test build/integration/packaged-cli-smoke.test.js",
33
33
  "prepublishOnly": "node scripts/bundle-assets.js && npm run build && node scripts/verify-shebang.cjs"
@@ -37,12 +37,12 @@
37
37
  "zod": "^4.4.3"
38
38
  },
39
39
  "optionalDependencies": {
40
- "better-sqlite3": "^11.8.1"
40
+ "better-sqlite3": "^12.11.1"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/better-sqlite3": "^7.6.12",
44
- "@types/node": "^25.9.1",
45
- "esbuild": "^0.25.0",
44
+ "@types/node": "^26.0.1",
45
+ "esbuild": "^0.28.1",
46
46
  "typescript": "^6.0.3"
47
47
  },
48
48
  "engines": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "review-ticket",
3
3
  "description": "Review a ticket with two rounds of analysis (initial + automatic second opinion by default), evaluate suggestions for accuracy, and produce a combined review-and-resolution document with decision trees. The automatic second-opinion step is skippable via --rounds=1 mode (skip_steps: [\"second-opinion-review\"]).",
4
- "variables": ["ticket_key", "docs_dir"],
4
+ "variables": ["ticket_key", "docs_dir", "base_branch", "base_sha", "no_refresh_base"],
5
5
  "steps": [
6
6
  {
7
7
  "type": "mcp_call",
@@ -35,15 +35,37 @@
35
35
  "description": "Generate combined clarify+critique review (second opinion)",
36
36
  "on_error": "warn_and_continue"
37
37
  },
38
+ {
39
+ "type": "mcp_call",
40
+ "id": "materialize-fresh-base",
41
+ "tool": "materialize_fresh_base",
42
+ "params": {
43
+ "base_branch": "{base_branch}",
44
+ "base_sha": "{base_sha}",
45
+ "no_refresh_base": "{no_refresh_base}"
46
+ },
47
+ "description": "Materialize a freshly-fetched, immutably-pinned origin/<base_branch> tree in an isolated temp dir for grounding",
48
+ "on_error": "halt"
49
+ },
38
50
  {
39
51
  "type": "agent_task",
40
52
  "instruction_file": "evaluate-and-recommend.md",
41
- "description": "Evaluate ticket-review findings against the codebase and produce the combined review-and-resolution document at {docs_dir}/review/{ticket_key}-review-and-resolution.md"
53
+ "description": "Evaluate ticket-review findings against the freshly-materialized codebase and produce the combined review-and-resolution document at {docs_dir}/review/{ticket_key}-review-and-resolution.md"
42
54
  },
43
55
  {
44
56
  "type": "agent_task",
45
57
  "instruction_file": "capture-review-decisions.md",
46
58
  "description": "Generate HTML decision page, capture user decisions, and interpretively rewrite clarifying questions and critique docs"
59
+ },
60
+ {
61
+ "type": "mcp_call",
62
+ "id": "cleanup-fresh-base",
63
+ "tool": "cleanup_fresh_base",
64
+ "params": {
65
+ "fresh_base_root": "<the fresh_base_root path returned by the earlier materialize_fresh_base step's result>"
66
+ },
67
+ "description": "Remove the temp workspace created by materialize_fresh_base. fresh_base_root is a RUNTIME value, not a static recipe variable: call this tool with the actual path string returned by the earlier materialize_fresh_base step's result, not the placeholder text shown in params above.",
68
+ "on_error": "warn_and_continue"
47
69
  }
48
70
  ]
49
71
  }