@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
|
@@ -193,6 +193,28 @@ export class ReviewGenerationRegistry {
|
|
|
193
193
|
return null;
|
|
194
194
|
return { baseline: entry.baseline, expectedLegCount: entry.expectedLegCount };
|
|
195
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Consecutive all-`404` wait windows recorded for the live submission
|
|
198
|
+
* (BAPI-1382), or `0` when there is none or no live entry.
|
|
199
|
+
*/
|
|
200
|
+
notFoundWindowCount(repoName, ticketNumber) {
|
|
201
|
+
this.evictExpired();
|
|
202
|
+
return this.entries.get(baselineKey(repoName, ticketNumber))?.notFoundWindows ?? 0;
|
|
203
|
+
}
|
|
204
|
+
/** Count one more all-`404` wait window for the live submission. No-op without one. */
|
|
205
|
+
noteNotFoundWindow(repoName, ticketNumber) {
|
|
206
|
+
this.evictExpired();
|
|
207
|
+
const entry = this.entries.get(baselineKey(repoName, ticketNumber));
|
|
208
|
+
if (!entry)
|
|
209
|
+
return;
|
|
210
|
+
entry.notFoundWindows = (entry.notFoundWindows ?? 0) + 1;
|
|
211
|
+
}
|
|
212
|
+
/** A non-`404` observation resets the count. No-op without a live entry. */
|
|
213
|
+
resetNotFoundWindows(repoName, ticketNumber) {
|
|
214
|
+
const entry = this.entries.get(baselineKey(repoName, ticketNumber));
|
|
215
|
+
if (entry)
|
|
216
|
+
entry.notFoundWindows = 0;
|
|
217
|
+
}
|
|
196
218
|
/**
|
|
197
219
|
* Consume a baseline. Clearing means "durable persistence has happened",
|
|
198
220
|
* not "a terminal envelope was received" (BAPI-1129) — the anchor is
|
package/build/review-tickets.js
CHANGED
|
@@ -3,12 +3,22 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Reuses the `start-tickets` terminal spawn layer directly, running reviews in
|
|
5
5
|
* the current `deps.cwd`. Intentionally does NOT create Worktrunk worktrees,
|
|
6
|
-
* provision MCP registrations, run venv hooks
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* provision MCP registrations, or run venv hooks. One terminal tab per ticket
|
|
7
|
+
* is spawned with `/review-ticket <KEY> [--auto] [--rounds=<1|2>]` as the agent
|
|
8
|
+
* prompt. `--rounds` is OMITTED by default so the backend's difficulty-adaptive
|
|
9
|
+
* review policy chooses the shape; it is only forwarded when the caller passes
|
|
10
|
+
* an explicit `--rounds`/`--review` round override.
|
|
11
|
+
*
|
|
12
|
+
* BAPI-1343 — review-threshold model routing for spawned tabs: an explicit
|
|
13
|
+
* `--model` always wins and no tier lookup is made. Otherwise each ticket's
|
|
14
|
+
* `/tickets/{n}/model-tier?consumer=review` is fetched (the shared bounded
|
|
15
|
+
* `start-tickets` fetcher, at most 3 at once), and a tab gets `--model` only
|
|
16
|
+
* when the server echoes `consumer: "review"` and reports a threshold-decided
|
|
17
|
+
* (`configured` or `anomaly`) tier, mapped to an alias exactly as
|
|
18
|
+
* `start-tickets` maps it. Legacy mode, a failed or timed-out lookup, or an
|
|
19
|
+
* older server that does not echo the consumer passes no `--model` (today's
|
|
20
|
+
* behavior); there is no premium fallback. `--dry-run` makes no lookup, and the
|
|
21
|
+
* epic-dispatch path below is not re-routed.
|
|
12
22
|
*
|
|
13
23
|
* Optionally supports a supervisor-driven epic-dispatch path: when an
|
|
14
24
|
* `EpicDispatchIdentity` is threaded through `ReviewTicketsOptions.epic`, each
|
|
@@ -18,7 +28,7 @@
|
|
|
18
28
|
* This path is worktree-free and base-branch-free; the human CLI path leaves
|
|
19
29
|
* `epic` unset and retains byte-for-byte identical behavior.
|
|
20
30
|
*/
|
|
21
|
-
import { createDefaultStartTicketsDeps, detectTerminal, runWithConcurrency, buildAgentInvocation, shSquoteInner, powershellSquote, isCommandOnPath, resolveFirstCommandOnPath, tmuxSessionNameForTicket, TICKET_KEY_PATTERN, DEFAULT_MAX_PARALLEL, validateBranchName, fetchAndResolveBaseSha, fetchStartTicketsConfigField, resolveStartTicketsBridgeApiAccess, buildCommandProvisioningDeps, buildMcpProvisioningDeps, } from "./start-tickets.js";
|
|
31
|
+
import { createDefaultStartTicketsDeps, detectTerminal, runWithConcurrency, buildAgentInvocation, shSquoteInner, powershellSquote, isCommandOnPath, resolveFirstCommandOnPath, tmuxSessionNameForTicket, TICKET_KEY_PATTERN, DEFAULT_MAX_PARALLEL, validateBranchName, fetchAndResolveBaseSha, fetchStartTicketsConfigField, resolveStartTicketsBridgeApiAccess, buildCommandProvisioningDeps, buildMcpProvisioningDeps, fetchTicketModelTiersForKeys, isThresholdDecidedTierResponse, normalizeDifficultyModelTierOverrides, fetchCodexModelCatalog, resolveRoutingAlias, validateResolvedModelAliasForAgent, } from "./start-tickets.js";
|
|
22
32
|
import { provisionCommandsForWorktree } from "./command-provisioning.js";
|
|
23
33
|
import { resolveCodexLaunchScope } from "./codex-launch-scope.js";
|
|
24
34
|
import { WINDOWS_TERMINAL_COMMAND, WINDOWS_POWERSHELL_CANDIDATES, TMUX_COMMAND, isSupportedStartTicketsPlatform, unsupportedPlatformMessage, } from "./start-tickets-prereqs.js";
|
|
@@ -48,7 +58,7 @@ export function getReviewTicketsUsage() {
|
|
|
48
58
|
" --rounds=1|2 Review depth: 1=single-pass, 2=full two-pass (default: adaptive — backend routes by difficulty)",
|
|
49
59
|
" --review KEY=auto,rounds=1 Per-ticket review mode override (repeatable)",
|
|
50
60
|
" --agent claude|cursor-agent|codex Agent command to launch in each tab (default: claude)",
|
|
51
|
-
" --model VALUE Model alias
|
|
61
|
+
" --model VALUE Model alias for every tab (always wins). Unset: each tab is routed by the review threshold; legacy mode or an older server passes no --model",
|
|
52
62
|
" --max-parallel N Max tabs to spawn concurrently (default: 3)",
|
|
53
63
|
" --dry-run Print intended commands; creates no tabs and opens no sessions",
|
|
54
64
|
" --base-branch BRANCH Base branch to fetch+pin for grounding (default: config base_branch, else \"main\")",
|
|
@@ -527,12 +537,125 @@ export function buildReviewPlanRows(deps, options, agent, status, overrides = {}
|
|
|
527
537
|
rounds: mode.rounds,
|
|
528
538
|
agentName: options.agentName,
|
|
529
539
|
modelAlias: options.modelAlias,
|
|
540
|
+
// BAPI-1343: plan rows (the dry-run preview) never perform a tier lookup;
|
|
541
|
+
// they show only an explicit --model, or the agent default.
|
|
542
|
+
...(!options.epic && options.modelAlias ? { modelRoutingReason: "explicit" } : {}),
|
|
530
543
|
status,
|
|
531
544
|
command,
|
|
532
545
|
runId,
|
|
533
546
|
};
|
|
534
547
|
});
|
|
535
548
|
}
|
|
549
|
+
/**
|
|
550
|
+
* BAPI-1343 — resolve each spawned tab's model from the review threshold.
|
|
551
|
+
*
|
|
552
|
+
* One `/model-tier?consumer=review` request per key through the shared
|
|
553
|
+
* `start-tickets` fetcher (bounded at 3, never throws). A tab is routed only
|
|
554
|
+
* when the server echoes `consumer: "review"` AND reports a threshold-decided
|
|
555
|
+
* tier; the tier maps to an alias exactly as `start-tickets` maps it (registry
|
|
556
|
+
* plus `difficulty_model_tier_overrides`, read once per batch; the Codex
|
|
557
|
+
* catalog, fetched once per batch; `validateResolvedModelAliasForAgent`, run
|
|
558
|
+
* at most once per distinct alias per batch). Every other outcome returns
|
|
559
|
+
* `modelAlias: null` (no `--model`, today's behavior) — there is no premium
|
|
560
|
+
* fallback. Callers handle explicit `--model`, `--dry-run`, and epic dispatch
|
|
561
|
+
* before calling this, so it always performs lookups.
|
|
562
|
+
*/
|
|
563
|
+
export async function resolveReviewModelRoutingForKeys(deps, keys, agent, maxParallel) {
|
|
564
|
+
const decisions = new Map();
|
|
565
|
+
const noModel = (reason) => ({ modelAlias: null, reason });
|
|
566
|
+
let accessResult;
|
|
567
|
+
try {
|
|
568
|
+
accessResult = await resolveStartTicketsBridgeApiAccess(deps);
|
|
569
|
+
}
|
|
570
|
+
catch {
|
|
571
|
+
for (const key of keys)
|
|
572
|
+
decisions.set(key, noModel("lookup-failed"));
|
|
573
|
+
return decisions;
|
|
574
|
+
}
|
|
575
|
+
if (!accessResult.ok) {
|
|
576
|
+
for (const key of keys)
|
|
577
|
+
decisions.set(key, noModel("lookup-failed"));
|
|
578
|
+
return decisions;
|
|
579
|
+
}
|
|
580
|
+
const access = accessResult.access;
|
|
581
|
+
const tierMap = await fetchTicketModelTiersForKeys(access, keys, maxParallel, { consumer: "review" });
|
|
582
|
+
// Batch-scoped alias inputs, loaded lazily so a batch with no
|
|
583
|
+
// threshold-decided ticket makes no config/catalog request.
|
|
584
|
+
let aliasInputs = null;
|
|
585
|
+
const loadAliasInputs = () => {
|
|
586
|
+
if (!aliasInputs) {
|
|
587
|
+
aliasInputs = (async () => {
|
|
588
|
+
try {
|
|
589
|
+
if (agent.name === "codex") {
|
|
590
|
+
const catalogResult = await fetchCodexModelCatalog(access);
|
|
591
|
+
return catalogResult.ok ? { overrides: null, catalog: catalogResult.catalog } : null;
|
|
592
|
+
}
|
|
593
|
+
const raw = await fetchStartTicketsConfigField(access, "difficulty_model_tier_overrides");
|
|
594
|
+
return { overrides: normalizeDifficultyModelTierOverrides(raw), catalog: null };
|
|
595
|
+
}
|
|
596
|
+
catch {
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
})();
|
|
600
|
+
}
|
|
601
|
+
return aliasInputs;
|
|
602
|
+
};
|
|
603
|
+
const validations = new Map();
|
|
604
|
+
const validateOnce = (alias) => {
|
|
605
|
+
let pending = validations.get(alias);
|
|
606
|
+
if (!pending) {
|
|
607
|
+
pending = validateResolvedModelAliasForAgent(deps, agent, alias).catch(() => ({ ok: false, warning: "model validation failed" }));
|
|
608
|
+
validations.set(alias, pending);
|
|
609
|
+
}
|
|
610
|
+
return pending;
|
|
611
|
+
};
|
|
612
|
+
for (const key of keys) {
|
|
613
|
+
const result = tierMap.get(key);
|
|
614
|
+
if (!result || !result.ok) {
|
|
615
|
+
decisions.set(key, noModel("lookup-failed"));
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
const value = result.value;
|
|
619
|
+
if (value.consumer !== "review") {
|
|
620
|
+
decisions.set(key, noModel("consumer-unrecognized"));
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
if (value.source === "fallback") {
|
|
624
|
+
// The server could not obtain a difficulty; its premium tier is a guess,
|
|
625
|
+
// and review routing has no premium fallback.
|
|
626
|
+
decisions.set(key, noModel("lookup-failed"));
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
if (!isThresholdDecidedTierResponse(value)) {
|
|
630
|
+
decisions.set(key, noModel("legacy"));
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
if (!value.tier) {
|
|
634
|
+
decisions.set(key, noModel("lookup-failed"));
|
|
635
|
+
continue;
|
|
636
|
+
}
|
|
637
|
+
if (!agent.supportsModelOverride) {
|
|
638
|
+
decisions.set(key, noModel("alias-unresolved"));
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
const inputs = await loadAliasInputs();
|
|
642
|
+
const candidate = inputs ? resolveRoutingAlias(agent, value.tier, inputs.overrides, inputs.catalog) : null;
|
|
643
|
+
if (!candidate) {
|
|
644
|
+
decisions.set(key, noModel("alias-unresolved"));
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
const validation = await validateOnce(candidate);
|
|
648
|
+
if (!validation.ok) {
|
|
649
|
+
decisions.set(key, noModel("alias-unresolved"));
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
decisions.set(key, {
|
|
653
|
+
modelAlias: validation.alias,
|
|
654
|
+
reason: value.thresholdMode === "anomaly" ? "review-threshold:anomaly" : "review-threshold:configured",
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
return decisions;
|
|
658
|
+
}
|
|
536
659
|
/** Build a dry-run preview base context from parsed CLI options only — never fetches. */
|
|
537
660
|
function previewBaseContextFromOptions(options) {
|
|
538
661
|
if (options.noRefreshBase)
|
|
@@ -590,10 +713,25 @@ export async function orchestrateReviewTickets(deps, options, overrides = {}) {
|
|
|
590
713
|
return { ok: false, error: baseContextResult.error };
|
|
591
714
|
}
|
|
592
715
|
const baseContext = baseContextResult.context;
|
|
716
|
+
// BAPI-1343: per-tab review-threshold routing for the human CLI path only.
|
|
717
|
+
// An explicit --model wins with no lookup; the epic-dispatch path keeps its
|
|
718
|
+
// pre-feature shape (Epic workers take their tier from the stamped payload).
|
|
719
|
+
let routing = null;
|
|
720
|
+
if (!options.epic) {
|
|
721
|
+
if (options.modelAlias) {
|
|
722
|
+
routing = new Map(options.keys.map((key) => [key, { modelAlias: options.modelAlias ?? null, reason: "explicit" }]));
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
routing = await resolveReviewModelRoutingForKeys(deps, options.keys, agent, options.maxParallel);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
593
728
|
const terminal = detectTerminal(undefined, deps.env);
|
|
594
729
|
const rows = await runWithConcurrency(options.keys, options.maxParallel, async (key) => {
|
|
595
730
|
const mode = resolveEffectiveReviewMode(key, options);
|
|
596
|
-
const
|
|
731
|
+
const decision = routing?.get(key);
|
|
732
|
+
const modelAlias = decision ? decision.modelAlias : options.modelAlias;
|
|
733
|
+
const reasonField = decision ? { modelRoutingReason: decision.reason } : {};
|
|
734
|
+
const baseShellCommand = buildReviewAgentShellCommand(agent, key, mode, deps.platform, deps.cwd, modelAlias, baseContext, codexLaunchArgs);
|
|
597
735
|
let shellCommand = baseShellCommand;
|
|
598
736
|
let runId;
|
|
599
737
|
if (options.epic) {
|
|
@@ -608,7 +746,8 @@ export async function orchestrateReviewTickets(deps, options, overrides = {}) {
|
|
|
608
746
|
auto: mode.auto,
|
|
609
747
|
rounds: mode.rounds,
|
|
610
748
|
agentName: options.agentName,
|
|
611
|
-
modelAlias
|
|
749
|
+
modelAlias,
|
|
750
|
+
...reasonField,
|
|
612
751
|
status: "spawn-failed",
|
|
613
752
|
command: shellCommand,
|
|
614
753
|
runId,
|
|
@@ -625,7 +764,8 @@ export async function orchestrateReviewTickets(deps, options, overrides = {}) {
|
|
|
625
764
|
auto: mode.auto,
|
|
626
765
|
rounds: mode.rounds,
|
|
627
766
|
agentName: options.agentName,
|
|
628
|
-
modelAlias
|
|
767
|
+
modelAlias,
|
|
768
|
+
...reasonField,
|
|
629
769
|
status: "already-dispatched",
|
|
630
770
|
command: shellCommand,
|
|
631
771
|
runId,
|
|
@@ -645,7 +785,8 @@ export async function orchestrateReviewTickets(deps, options, overrides = {}) {
|
|
|
645
785
|
auto: mode.auto,
|
|
646
786
|
rounds: mode.rounds,
|
|
647
787
|
agentName: options.agentName,
|
|
648
|
-
modelAlias
|
|
788
|
+
modelAlias,
|
|
789
|
+
...reasonField,
|
|
649
790
|
status: "spawned",
|
|
650
791
|
command: shellCommand,
|
|
651
792
|
runId,
|
|
@@ -687,9 +828,11 @@ export function formatReviewTicketsSummaryReport(rows) {
|
|
|
687
828
|
const lines = ["Summary:"];
|
|
688
829
|
for (const row of rows) {
|
|
689
830
|
const modelPart = row.modelAlias ? row.modelAlias : "default";
|
|
831
|
+
// BAPI-1343: the closed, secret-free routing reason, when one was recorded.
|
|
832
|
+
const modelReasonPart = row.modelRoutingReason ? ` model_reason=${row.modelRoutingReason}` : "";
|
|
690
833
|
const roundsPart = row.rounds !== undefined ? String(row.rounds) : "adaptive";
|
|
691
834
|
const runIdPart = row.runId ? ` run_id=${row.runId}` : "";
|
|
692
|
-
lines.push(`${row.key} auto=${row.auto} rounds=${roundsPart} agent=${row.agentName} model=${modelPart} status=${row.status}${runIdPart}`);
|
|
835
|
+
lines.push(`${row.key} auto=${row.auto} rounds=${roundsPart} agent=${row.agentName} model=${modelPart}${modelReasonPart} status=${row.status}${runIdPart}`);
|
|
693
836
|
}
|
|
694
837
|
const failedRows = rows.filter((r) => r.status === "spawn-failed" || r.status === "already-dispatched");
|
|
695
838
|
if (failedRows.length > 0) {
|