sortie-dogs 0.13.0 → 0.13.1
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 +18 -6
- package/dist/asset-version.d.ts +1 -1
- package/dist/asset-version.js +1 -1
- package/dist/core/initialize.d.ts +1 -1
- package/dist/core/initialize.js +1 -1
- package/dist/core/operator-mission.d.ts +5 -9
- package/dist/core/operator-mission.js +23 -51
- package/dist/core/operator-runtime.d.ts +19 -0
- package/dist/core/operator-runtime.js +29 -11
- package/dist/plugin/adaptive-remediation-host.d.ts +1 -1
- package/dist/plugin/adaptive-remediation-host.js +1 -1
- package/dist/plugin/mission-review.js +36 -9
- package/dist/plugin/model-cost.d.ts +3 -3
- package/dist/plugin/model-cost.js +10 -6
- package/dist/plugin/model-routing.d.ts +7 -7
- package/dist/plugin/model-routing.js +7 -12
- package/dist/plugin/profiled.js +67 -28
- package/dist/plugin/run-metrics.d.ts +1 -0
- package/dist/plugin/run-metrics.js +5 -27
- package/dist/plugin/v2.js +4 -4
- package/dist/runtime-assets-v010.js +6 -30
- package/dist/runtime-assets.d.ts +2 -2
- package/dist/runtime-assets.js +2 -2
- package/dist/runtime-mission-assets.d.ts +4 -1
- package/dist/runtime-mission-assets.js +108 -36
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Sortie-dogs
|
|
2
2
|
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="docs/assets/sortie-dogs-logo.png" alt="Sortie-dogs logo" width="640">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
3
7
|
**A goal-preserving, adaptive execution harness for OpenCode that optimizes cost,
|
|
4
8
|
time, and proof without taking your setup over.**
|
|
5
9
|
|
|
@@ -28,6 +32,14 @@ implementation, validation, review, and model routing.
|
|
|
28
32
|
Guides: [日本語](docs/guide-ja.md) · [简体中文](docs/guide-zh-CN.md) ·
|
|
29
33
|
[Testing](docs/testing.md) · [CLI testing](docs/cli-testing.md)
|
|
30
34
|
|
|
35
|
+
## SWE-bench Lite: 170/300 (56.67%)
|
|
36
|
+
|
|
37
|
+
The fixed **Sortie-dogs v0.12.24** harness resolved **170 of 300 SWE-bench Lite test issues** in one pass@1 campaign, with 9 empty patches and no official evaluation errors. Every instance has a frozen prediction and an inference-time trajectory. The task Workers ran `openai/gpt-6-luna-fast#max`; operator, coordinator and review roles ran `openai/gpt-6-sol#xhigh`. This is a system result, **not** a Luna-only model comparison or a Verified/full SWE-bench score.
|
|
38
|
+
|
|
39
|
+
[Technical report and per-repository results](docs/benchmarks/swebench-lite-v01224-test300-2026-09-29.md) · [Public predictions, logs and trajectories](https://github.com/zufall-upon/sortie-dogs-swebench-lite-20260929)
|
|
40
|
+
|
|
41
|
+
The single official 300-instance report and frozen predictions are hash-bound in the report. Confirmed inference expense was **$162.99**; a separate **$34.60** of usage has unknown pricing and is held against the campaign cap, **not** counted as known expense. Leaderboard registration and maintainer acceptance are separate from this official local evaluation.
|
|
42
|
+
|
|
31
43
|
> **Beta:** v0.12.2 builds on the v0.10.23 execution engine. Runtime behavior,
|
|
32
44
|
> configuration, and generated assets may still change before 1.0.
|
|
33
45
|
|
|
@@ -202,7 +214,7 @@ not invent, probe, or translate variant names.
|
|
|
202
214
|
- `freeTierFallbackModels`: ordered global last-resort model IDs. Default:
|
|
203
215
|
`opencode/deepseek-v4-flash-free`; `[]` disables this fallback.
|
|
204
216
|
- `dedicatedWorkerModel`: canonical stable serial target, default
|
|
205
|
-
`openai/gpt-6-sol` / `medium`. The v0.10 profile also supplies its explicit
|
|
217
|
+
`openai/gpt-6.1-sol` / `medium`. The v0.10 profile also supplies its explicit
|
|
206
218
|
role routes below; do not infer the v0.10 worker route from this stable setting.
|
|
207
219
|
- `consultation.strategy`: fixed advisor identity, optional `required`, and
|
|
208
220
|
positive `maxCallsPerCandidate`; default one call and not required.
|
|
@@ -239,14 +251,14 @@ or explicit risk. Workers own static, targeted, and related checks; the root own
|
|
|
239
251
|
canonical and full-suite checks. An unchanged candidate, command, and environment
|
|
240
252
|
reuse the same evidence instead of spending the validation budget again.
|
|
241
253
|
|
|
242
|
-
### Default
|
|
254
|
+
### Default routes
|
|
243
255
|
|
|
244
|
-
- `dog-operator`: `openai/gpt-6-sol` / `xhigh`
|
|
245
|
-
- `dogs-coordinator`: `openai/gpt-6-sol` / `xhigh`
|
|
256
|
+
- `dog-operator`: `openai/gpt-6.1-sol` / `xhigh`
|
|
257
|
+
- `dogs-coordinator`: `openai/gpt-6.1-sol` / `xhigh`
|
|
246
258
|
- `dog-worker-v010`: `openai/gpt-6-luna-fast` / `max`
|
|
247
259
|
- `dog-scout-v010`: `openai/gpt-6-luna-fast` / `max`
|
|
248
|
-
- `dog-reviewer-v010`: `openai/gpt-6-sol` / `xhigh`
|
|
249
|
-
- `dog-advisor-v010`: `openai/gpt-6-sol` / `xhigh`
|
|
260
|
+
- `dog-reviewer-v010`: `openai/gpt-6.1-sol` / `xhigh`
|
|
261
|
+
- `dog-advisor-v010`: `openai/gpt-6.1-sol` / `xhigh`
|
|
250
262
|
|
|
251
263
|
An explicit model and variant selected in OpenCode remains authoritative for that
|
|
252
264
|
session. Child role defaults fill absent native settings and may be overridden by
|
package/dist/asset-version.d.ts
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* installed project marker without importing every asset body.
|
|
4
4
|
*/
|
|
5
5
|
export declare const RUNTIME_ASSET_VERSION = "0.3.89-completion-proof-v1";
|
|
6
|
-
export declare const V010_RUNTIME_ASSET_VERSION = "0.13.
|
|
6
|
+
export declare const V010_RUNTIME_ASSET_VERSION = "0.13.1-quality-first-review-v1";
|
|
7
7
|
export type RuntimeAssetVersion = typeof RUNTIME_ASSET_VERSION | typeof V010_RUNTIME_ASSET_VERSION;
|
package/dist/asset-version.js
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* installed project marker without importing every asset body.
|
|
4
4
|
*/
|
|
5
5
|
export const RUNTIME_ASSET_VERSION = "0.3.89-completion-proof-v1";
|
|
6
|
-
export const V010_RUNTIME_ASSET_VERSION = "0.13.
|
|
6
|
+
export const V010_RUNTIME_ASSET_VERSION = "0.13.1-quality-first-review-v1";
|
|
@@ -11,7 +11,7 @@ export declare class ProjectInitializationError extends Error {
|
|
|
11
11
|
readonly code: ProjectInitializationErrorCode;
|
|
12
12
|
constructor(code: ProjectInitializationErrorCode, message: string, options?: ErrorOptions);
|
|
13
13
|
}
|
|
14
|
-
export declare const V010_COORDINATOR_MODEL = "openai/gpt-6-sol#xhigh";
|
|
14
|
+
export declare const V010_COORDINATOR_MODEL = "openai/gpt-6.1-sol#xhigh";
|
|
15
15
|
/**
|
|
16
16
|
* Report a user config that routes the v0.10 Coordinator away from its packaged model. Measured Luna
|
|
17
17
|
* Coordinators repeated plans and review dispatches until timeout, so init surfaces it without editing it.
|
package/dist/core/initialize.js
CHANGED
|
@@ -542,7 +542,7 @@ async function initializeRoot(requestedRoot, layout, installAssets = runtimeAsse
|
|
|
542
542
|
preservedLegacyPaths,
|
|
543
543
|
};
|
|
544
544
|
}
|
|
545
|
-
export const V010_COORDINATOR_MODEL = "openai/gpt-6-sol#xhigh";
|
|
545
|
+
export const V010_COORDINATOR_MODEL = "openai/gpt-6.1-sol#xhigh";
|
|
546
546
|
/**
|
|
547
547
|
* Report a user config that routes the v0.10 Coordinator away from its packaged model. Measured Luna
|
|
548
548
|
* Coordinators repeated plans and review dispatches until timeout, so init surfaces it without editing it.
|
|
@@ -80,7 +80,8 @@ export interface MissionExecution {
|
|
|
80
80
|
startedAt: string;
|
|
81
81
|
completedAt?: string;
|
|
82
82
|
exit?: number;
|
|
83
|
-
status?: "completed" | "error";
|
|
83
|
+
status?: "running" | "completed" | "error";
|
|
84
|
+
shellID?: string;
|
|
84
85
|
outcome?: "not-started" | "execution-failed" | "executed";
|
|
85
86
|
result?: Record<string, unknown>;
|
|
86
87
|
}[];
|
|
@@ -141,15 +142,10 @@ export interface OperatorMission {
|
|
|
141
142
|
child?: string;
|
|
142
143
|
/** Completed, independent initial review for this mission, not merely an inherited child ID. */
|
|
143
144
|
initialPrompt?: string;
|
|
144
|
-
/**
|
|
145
|
+
/** Observed evidence-only reviews; reporting only, never an acceptance threshold. */
|
|
145
146
|
evidenceGapReviews?: number;
|
|
146
147
|
};
|
|
147
148
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Evidence-only findings do not establish a defect. Each extra round costs a full Reviewer pass and often a
|
|
150
|
-
* Worker unit, so after this many evidence-only reviews the candidate may be submitted with the gaps listed.
|
|
151
|
-
*/
|
|
152
|
-
export declare const MISSION_EVIDENCE_GAP_REVIEW_LIMIT = 2;
|
|
153
149
|
export declare const MISSION_CONSULTATION_LIMIT = 32;
|
|
154
150
|
/** Review coverage survives a narrower replan; it is not a Worker write grant. */
|
|
155
151
|
export declare function missionReviewScope(previous: MissionReviewScope | undefined, ...runs: OperatorState[]): MissionReviewScope;
|
|
@@ -217,5 +213,5 @@ export declare function missionPlan(mission: OperatorMission, raw: unknown): Ope
|
|
|
217
213
|
export declare function missionPacket(mission: OperatorMission, run?: OperatorState): Record<string, unknown>;
|
|
218
214
|
/** Models forward a short capability, never recopy the host's evidence hashes and source packet. */
|
|
219
215
|
export declare function missionReviewTask(mission: OperatorMission): OperatorTask;
|
|
220
|
-
/**
|
|
221
|
-
export declare function missionReviewTraces(
|
|
216
|
+
/** Optional implementation notes supplement host-observed source/checks; prose is not a coverage gate. */
|
|
217
|
+
export declare function missionReviewTraces(_mission: OperatorMission, raw: unknown): string[];
|
|
@@ -18,11 +18,6 @@ export function missionValidationCommand(command) {
|
|
|
18
18
|
const expression = `exec(${JSON.stringify(heredoc[4])})`;
|
|
19
19
|
return `${heredoc[1]} -c '${expression.replaceAll("'", "'\\''")}'`;
|
|
20
20
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Evidence-only findings do not establish a defect. Each extra round costs a full Reviewer pass and often a
|
|
23
|
-
* Worker unit, so after this many evidence-only reviews the candidate may be submitted with the gaps listed.
|
|
24
|
-
*/
|
|
25
|
-
export const MISSION_EVIDENCE_GAP_REVIEW_LIMIT = 2;
|
|
26
21
|
export const MISSION_CONSULTATION_LIMIT = 32;
|
|
27
22
|
/** Review coverage survives a narrower replan; it is not a Worker write grant. */
|
|
28
23
|
export function missionReviewScope(previous, ...runs) {
|
|
@@ -38,7 +33,7 @@ export function missionReviewVerdict(text) {
|
|
|
38
33
|
/** Whether the recorded review permits submission and acceptance of the current candidate. */
|
|
39
34
|
export function missionReviewAccepted(review) {
|
|
40
35
|
return review.verdict === "PASS" || review.verdict === "skipped-low-risk" ||
|
|
41
|
-
|
|
36
|
+
review.verdict === "evidence-gaps";
|
|
42
37
|
}
|
|
43
38
|
export function missionExecutionStatus(mission) {
|
|
44
39
|
if (mission.kind !== "operation")
|
|
@@ -469,7 +464,7 @@ export function missionPacket(mission, run) {
|
|
|
469
464
|
run_id: mission.review.runID, current_run: currentReview,
|
|
470
465
|
source_fingerprint: mission.review.source, reviewer_session_id: mission.review.child ?? null,
|
|
471
466
|
result: mission.review.result ?? null, evidence_gap_reviews: mission.review.evidenceGapReviews ?? 0,
|
|
472
|
-
|
|
467
|
+
evidence_gaps_advisory: true, accepted: reviewAccepted,
|
|
473
468
|
passed: currentReview && mission.review.verdict === "PASS", permits_submission: reviewAccepted && operationComplete } : null,
|
|
474
469
|
...(run ? { run_id: run.runID, status: run.phase, decision: run.decision,
|
|
475
470
|
units: run.units.map(unit => ({ id: unit.unit.id, title: unit.unit.title, status: unit.status,
|
|
@@ -482,21 +477,21 @@ export function missionPacket(mission, run) {
|
|
|
482
477
|
next_action: mission.phase === "completed" ? "Mission completed. Report the accepted result and retained review gaps; no further dispatch or completion call is needed."
|
|
483
478
|
: mission.phase === "submitted" && mission.submission?.status === "ready"
|
|
484
479
|
? "Operator: compare the submitted candidate with the original requirements and actual evidence, then complete_mission if satisfied. Report remaining evidence gaps; they are not a review PASS."
|
|
485
|
-
:
|
|
486
|
-
? "
|
|
487
|
-
: run
|
|
488
|
-
? "Coordinator:
|
|
489
|
-
: run.units.some(unit => unit.status === "failed" && unit.resultClass === "acceptance" && unit.failure?.outcome === "fail" && unit.normalRemediationUsed
|
|
490
|
-
? "Coordinator:
|
|
491
|
-
:
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
: run?.phase === "awaiting-acceptance"
|
|
495
|
-
?
|
|
496
|
-
: reviewAccepted
|
|
497
|
-
? "Coordinator: review permits submission.
|
|
480
|
+
: mission.kind === "operation" && operationStatus === "running"
|
|
481
|
+
? "The declared operation is already running. Inspect its native shell/progress; do not start another Worker or run. Wait for a terminal result, or report the existing run as blocked if its completion cannot be observed."
|
|
482
|
+
: run?.phase === "awaiting-decision" ? (run.units.some(unit => unit.dispatchDenial)
|
|
483
|
+
? "Coordinator: inspect units[].dispatch_denial before changing the plan. Correct only its diagnosed cause; do not repeat an unchanged refused Task or replan for a host-state mismatch. Report an unresolved runtime mismatch with the loaded runtime identity; preserve requirements and cumulative spend."
|
|
484
|
+
: run.units.some(unit => unit.status === "failed" && unit.resultClass === "acceptance" && unit.failure?.outcome === "fail" && !unit.normalRemediationUsed)
|
|
485
|
+
? "Coordinator: one exact declared validation failed. Reconcile the returned Worker and cumulative budget, then call retry_mission_unit once for that unit before replanning. This preserves the same scope and acceptance."
|
|
486
|
+
: run.units.some(unit => unit.status === "failed" && unit.resultClass === "acceptance" && unit.failure?.outcome === "fail" && unit.normalRemediationUsed && !unit.terminalRescue)
|
|
487
|
+
? "Coordinator: the one ordinary remediation failed the declared validation again. If its native terminal, writer release, exact candidate and cumulative budget permit, call rescue_mission_unit once; inspect and report a non_rescue reason, then continue ordinary correction within budget. Rescue does not bypass validation, review or root acceptance."
|
|
488
|
+
: "Coordinator: correct the cause and call plan_units with the remaining work and all requirements; budget is cumulative.")
|
|
489
|
+
: run?.phase === "awaiting-acceptance" && !operationComplete
|
|
490
|
+
? `Requested operation is ${operationStatus}. Continue the actual operation or report its blocker; auxiliary checks and review disposition cannot complete it.`
|
|
491
|
+
: run?.phase === "awaiting-acceptance" ? (reviewAccepted
|
|
492
|
+
? "Coordinator: review permits submission. Retain advisory review notes; do not repeat passed validation or review for evidence formatting. Operator performs final acceptance against the original requirements."
|
|
498
493
|
: "Coordinator: address recorded findings or obtain the required independent review, then submit_mission. Operator compares all requirements with source/evidence before complete_mission.")
|
|
499
|
-
|
|
494
|
+
: "Coordinator: continue the next useful unit within original requirements. Return only a completion candidate, user-only decision, or scope/budget extension." };
|
|
500
495
|
}
|
|
501
496
|
/** Models forward a short capability, never recopy the host's evidence hashes and source packet. */
|
|
502
497
|
export function missionReviewTask(mission) {
|
|
@@ -506,35 +501,12 @@ export function missionReviewTask(mission) {
|
|
|
506
501
|
return { ...review.task, prompt: `${MISSION_REVIEW_REFERENCE}${JSON.stringify({ r: mission.root,
|
|
507
502
|
m: mission.id, n: review.runID, h: digest(review.task.prompt) })}` };
|
|
508
503
|
}
|
|
509
|
-
/**
|
|
510
|
-
export function missionReviewTraces(
|
|
511
|
-
if (
|
|
512
|
-
|
|
504
|
+
/** Optional implementation notes supplement host-observed source/checks; prose is not a coverage gate. */
|
|
505
|
+
export function missionReviewTraces(_mission, raw) {
|
|
506
|
+
if (raw === undefined)
|
|
507
|
+
return [];
|
|
508
|
+
if (!Array.isArray(raw) || !raw.every(item => typeof item === "string")) {
|
|
509
|
+
throw new Error("mission-review-traces: optional notes must be strings");
|
|
513
510
|
}
|
|
514
|
-
|
|
515
|
-
ids: [...text.matchAll(/(?:^|[.;]\s+|[\r\n])\s*((?:R\d+\s*[-/,]?\s*)+):/gu)]
|
|
516
|
-
.flatMap(match => [...match[1].matchAll(/R(\d+)(?:\s*-\s*R(\d+))?/gu)]
|
|
517
|
-
.flatMap(([, first, last]) => {
|
|
518
|
-
const firstID = `R${first}`;
|
|
519
|
-
if (last === undefined)
|
|
520
|
-
return [firstID];
|
|
521
|
-
const lastID = `R${last}`;
|
|
522
|
-
const start = mission.requirements.findIndex(item => item.id === firstID);
|
|
523
|
-
const end = mission.requirements.findIndex(item => item.id === lastID);
|
|
524
|
-
if (start < 0 || end < 0)
|
|
525
|
-
return [firstID, lastID];
|
|
526
|
-
if (start > end)
|
|
527
|
-
throw new Error(`mission-review-traces: descending range ${firstID}-${lastID}`);
|
|
528
|
-
return mission.requirements.slice(start, end + 1).map(item => item.id);
|
|
529
|
-
})) }));
|
|
530
|
-
if (grouped.every(item => item.ids.length === 0) && raw.length === mission.requirements.length)
|
|
531
|
-
return raw;
|
|
532
|
-
const unknown = grouped.flatMap(item => item.ids).filter(id => !mission.requirements.some(requirement => requirement.id === id));
|
|
533
|
-
const missing = mission.requirements.filter(requirement => !grouped.some(item => item.ids.includes(requirement.id)));
|
|
534
|
-
if (unknown.length || missing.length)
|
|
535
|
-
throw new Error(`mission-review-traces: name the existing R IDs; ${[
|
|
536
|
-
...(missing.length ? [`missing ${missing.map(item => item.id).join(", ")}`] : []),
|
|
537
|
-
...(unknown.length ? [`unknown ${unknown.join(", ")}`] : []),
|
|
538
|
-
].join("; ")}`);
|
|
539
|
-
return mission.requirements.map(requirement => grouped.filter(item => item.ids.includes(requirement.id)).map(item => item.text).join("\n"));
|
|
511
|
+
return raw.map(text => text.trim()).filter(Boolean);
|
|
540
512
|
}
|
|
@@ -227,6 +227,22 @@ export interface OperatorState {
|
|
|
227
227
|
decision: string | null;
|
|
228
228
|
receipt: GoalTerminalReceipt | null;
|
|
229
229
|
}
|
|
230
|
+
export interface OperatorProgress {
|
|
231
|
+
readonly profile: string;
|
|
232
|
+
readonly view: "progress";
|
|
233
|
+
readonly run_id: string;
|
|
234
|
+
readonly stage: OperatorPhase;
|
|
235
|
+
readonly decision: string | null;
|
|
236
|
+
readonly current_unit: {
|
|
237
|
+
readonly id: string;
|
|
238
|
+
readonly title: string;
|
|
239
|
+
readonly status: UnitState["status"];
|
|
240
|
+
} | null;
|
|
241
|
+
readonly completed_units: number;
|
|
242
|
+
readonly total_units: number;
|
|
243
|
+
readonly budget_remaining_units: number | null;
|
|
244
|
+
readonly next_action: string | null;
|
|
245
|
+
}
|
|
230
246
|
/** A later mission may replace an unexecuted cancellation, but must retain settled work's acceptance. */
|
|
231
247
|
export declare function cancelledMissionRetainsAcceptance(state: OperatorState): boolean;
|
|
232
248
|
export declare function operatorGitPathAuthorized(path: string, scopes: readonly string[], platform?: NodeJS.Platform): boolean;
|
|
@@ -371,10 +387,13 @@ export declare class OperatorRuntime {
|
|
|
371
387
|
draftStatus(root: string): Promise<unknown | undefined>;
|
|
372
388
|
completionGoalFingerprint(state: OperatorState): Promise<string>;
|
|
373
389
|
verifyContinuityControls(state: OperatorState): Promise<void>;
|
|
390
|
+
/** Compact, read-only projection of the same durable run and decision as the complete packet. */
|
|
391
|
+
progress(state: OperatorState, budgetRemainingUnits: number | null, nextAction?: string | null): OperatorProgress;
|
|
374
392
|
packet(state: OperatorState): unknown;
|
|
375
393
|
/** Reconstruct the admitted child's instructions without trusting a lossy conversation summary. */
|
|
376
394
|
workerContext(root: string, child: string): Promise<string | undefined>;
|
|
377
395
|
continuationCheckpoint(root: string): Promise<string | undefined>;
|
|
396
|
+
private continuationNextAction;
|
|
378
397
|
private controlReference;
|
|
379
398
|
private verifyControls;
|
|
380
399
|
/** Follow only the host's authorized parent-link repair; keep the durable control pin in sync. */
|
|
@@ -1904,6 +1904,16 @@ export class OperatorRuntime {
|
|
|
1904
1904
|
for (const unit of current.units)
|
|
1905
1905
|
await this.verifyControls(unit);
|
|
1906
1906
|
}
|
|
1907
|
+
/** Compact, read-only projection of the same durable run and decision as the complete packet. */
|
|
1908
|
+
progress(state, budgetRemainingUnits, nextAction) {
|
|
1909
|
+
const current = state.units.find(unit => unit.status !== "succeeded");
|
|
1910
|
+
const authoritativeAction = nextAction !== undefined ? nextAction
|
|
1911
|
+
: this.continuationNextAction(state);
|
|
1912
|
+
return { profile: state.profile, view: "progress", run_id: state.runID, stage: state.phase, decision: state.decision,
|
|
1913
|
+
current_unit: current === undefined ? null : { id: current.unit.id, title: current.unit.title, status: current.status },
|
|
1914
|
+
completed_units: state.units.filter(unit => unit.status === "succeeded").length, total_units: state.units.length,
|
|
1915
|
+
budget_remaining_units: budgetRemainingUnits, next_action: typeof authoritativeAction === "string" ? authoritativeAction : null };
|
|
1916
|
+
}
|
|
1907
1917
|
packet(state) {
|
|
1908
1918
|
const proved = new Set(state.units.flatMap(unit => unit.evidence.flatMap(item => item.measurement.criterion_ids)));
|
|
1909
1919
|
const current = state.units.find(unit => unit.status !== "succeeded");
|
|
@@ -2035,9 +2045,10 @@ export class OperatorRuntime {
|
|
|
2035
2045
|
}
|
|
2036
2046
|
async continuationCheckpoint(root) {
|
|
2037
2047
|
const state = await this.read(root);
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2048
|
+
if (!state)
|
|
2049
|
+
return undefined;
|
|
2050
|
+
const nextAction = this.continuationNextAction(state);
|
|
2051
|
+
if (nextAction === null)
|
|
2041
2052
|
return undefined;
|
|
2042
2053
|
const current = state.units.find(unit => unit.status !== "succeeded");
|
|
2043
2054
|
return JSON.stringify({ authority: "durable-operator-state", root_session_id: state.rootSessionID,
|
|
@@ -2046,14 +2057,21 @@ export class OperatorRuntime {
|
|
|
2046
2057
|
next_task_ref: current?.status === "pending" ? (state.units.length > 1
|
|
2047
2058
|
? state.operatorSessionID === null ? this.dispatchTask(state).prompt : null
|
|
2048
2059
|
: current.repairValidation === null ? this.workerTask(state, current).prompt : this.repairWorkerTask(state, current).prompt) : null,
|
|
2049
|
-
next_action:
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2060
|
+
next_action: nextAction });
|
|
2061
|
+
}
|
|
2062
|
+
continuationNextAction(state) {
|
|
2063
|
+
const cancelledRemediation = state.phase === "cancelled" &&
|
|
2064
|
+
[ACCEPTANCE_REMEDIATION_DECISION, REVIEW_REMEDIATION_DECISION].includes(state.decision ?? "");
|
|
2065
|
+
if (state.phase === "completed" || (state.phase === "cancelled" && !cancelledRemediation))
|
|
2066
|
+
return null;
|
|
2067
|
+
return state.decision === ACCEPTANCE_REMEDIATION_DECISION || state.decision === REVIEW_REMEDIATION_DECISION
|
|
2068
|
+
? `call ${this.profile.toolPrefix}operator_status and execute its cancel-then-replacement next_action in this turn; do not stop after reporting status or call resume_operator`
|
|
2069
|
+
: state.phase === "awaiting-acceptance" ? `call ${this.profile.toolPrefix}operator_status and follow its independent-review next_action; do not complete before review disposition`
|
|
2070
|
+
: state.phase === "prepared" ? "call operator_status, then operator_next; dispatch only the exact returned Task"
|
|
2071
|
+
: state.phase === "running" ? "call operator_status; do not duplicate the running Task"
|
|
2072
|
+
: state.phase === "cancelled"
|
|
2073
|
+
? `call ${this.profile.toolPrefix}operator_status and execute its prepare_operator next_action in this turn; do not stop after reporting status`
|
|
2074
|
+
: `call ${this.profile.toolPrefix}operator_status and execute its exact next_action in this turn; do not stop after reporting status`;
|
|
2057
2075
|
}
|
|
2058
2076
|
controlReference(path) {
|
|
2059
2077
|
const local = relative(this.projectRoot, path);
|
|
@@ -23,7 +23,7 @@ export interface AdaptiveReviewProvider {
|
|
|
23
23
|
readonly fingerprint: string;
|
|
24
24
|
}>;
|
|
25
25
|
}
|
|
26
|
-
export declare const DEFAULT_ADAPTIVE_REMEDIATION_MODEL = "openai/gpt-6-sol";
|
|
26
|
+
export declare const DEFAULT_ADAPTIVE_REMEDIATION_MODEL = "openai/gpt-6.1-sol";
|
|
27
27
|
export interface AdaptiveRemediationSessionClient extends OpenCodeModelAvailabilityClient {
|
|
28
28
|
session: {
|
|
29
29
|
create(input: {
|
|
@@ -10,7 +10,7 @@ import { produceWorktreeCommitArtifact, runContainedValidation } from "../core/w
|
|
|
10
10
|
import { openCodeModel } from "./model-routing-hook.js";
|
|
11
11
|
const SHA = /^[a-f0-9]{40}(?:[a-f0-9]{24})?$/u;
|
|
12
12
|
const HASH = /^[a-f0-9]{64}$/u;
|
|
13
|
-
export const DEFAULT_ADAPTIVE_REMEDIATION_MODEL = "openai/gpt-6-sol";
|
|
13
|
+
export const DEFAULT_ADAPTIVE_REMEDIATION_MODEL = "openai/gpt-6.1-sol";
|
|
14
14
|
const responseData = (value) => {
|
|
15
15
|
if (value === null || typeof value !== "object")
|
|
16
16
|
return {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { execFile } from "node:child_process";
|
|
3
3
|
import { createReadStream } from "node:fs";
|
|
4
|
-
import { lstat, readlink } from "node:fs/promises";
|
|
5
|
-
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { lstat, readlink, readdir } from "node:fs/promises";
|
|
5
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
import { createInterface } from "node:readline";
|
|
8
8
|
import { TOOL_ENVIRONMENT } from "../runtime-mission-assets.js";
|
|
@@ -218,7 +218,7 @@ export async function missionReviewSource(directory, run, evidence = [], baselin
|
|
|
218
218
|
// Keep room for the baseline diff. Reserve notices only after the allocated whole lines show
|
|
219
219
|
// truncation; pre-reserving every possible notice can hide all six otherwise fitting references.
|
|
220
220
|
const heading = (entry) => `\n--- evidence: ${entry.path}:${entry.offset} ---\n`;
|
|
221
|
-
const truncated = (entry) => `[FOCUSED EXCERPT TRUNCATED: ${entry.path}:${entry.offset};
|
|
221
|
+
const truncated = (entry) => `[FOCUSED EXCERPT TRUNCATED: ${entry.path}:${entry.offset}; Reviewer can read the remaining lines directly]\n`;
|
|
222
222
|
// Read-only reviews retain their smaller existing envelope; code reviews may use the space
|
|
223
223
|
// previously reserved for automatic diff prefixes, while leaving room for changed-file context.
|
|
224
224
|
const limit = writes.length ? 18_000 : 11_000;
|
|
@@ -305,13 +305,17 @@ export async function missionReviewSource(directory, run, evidence = [], baselin
|
|
|
305
305
|
const unchanged = diff.length === 0;
|
|
306
306
|
let excerpt = selected + diff;
|
|
307
307
|
const paths = [...new Set([...names.split("\0"), ...ignored.split("\0")].filter(Boolean))].sort();
|
|
308
|
-
|
|
308
|
+
const visited = new Set();
|
|
309
|
+
const visit = async (path, includedByParent = false) => {
|
|
310
|
+
if (visited.has(path))
|
|
311
|
+
return;
|
|
312
|
+
visited.add(path);
|
|
309
313
|
hash.update(JSON.stringify(path));
|
|
310
314
|
try {
|
|
311
315
|
const absolute = resolve(directory, path), stat = await lstat(absolute);
|
|
312
316
|
hash.update(String(stat.mode));
|
|
313
|
-
const include = untracked.has(path) || unchanged;
|
|
314
|
-
const heading = `\n--- ${untracked.has(path) ? "new file" : "current file"}: ${path} ---\n`;
|
|
317
|
+
const include = includedByParent || untracked.has(path) || unchanged;
|
|
318
|
+
const heading = `\n--- ${includedByParent || untracked.has(path) ? "new file" : "current file"}: ${path} ---\n`;
|
|
315
319
|
const room = include ? Math.max(0, 24_000 - Buffer.byteLength(excerpt) - Buffer.byteLength(heading)) : 0;
|
|
316
320
|
let preview = Buffer.alloc(0);
|
|
317
321
|
if (stat.isSymbolicLink()) {
|
|
@@ -319,7 +323,28 @@ export async function missionReviewSource(directory, run, evidence = [], baselin
|
|
|
319
323
|
hash.update(String(content.length)).update(content);
|
|
320
324
|
preview = content.subarray(0, room);
|
|
321
325
|
}
|
|
326
|
+
else if (stat.isDirectory()) {
|
|
327
|
+
hash.update("directory");
|
|
328
|
+
if (include) {
|
|
329
|
+
const marker = "[directory; contained artifacts follow]\n";
|
|
330
|
+
const headingFits = Buffer.byteLength(excerpt) + Buffer.byteLength(heading) + Buffer.byteLength(marker) <= 24_000;
|
|
331
|
+
if (headingFits)
|
|
332
|
+
excerpt += heading + marker;
|
|
333
|
+
else
|
|
334
|
+
omitted.push(path);
|
|
335
|
+
}
|
|
336
|
+
// Nested repository metadata is not candidate output and can crowd out its actual files.
|
|
337
|
+
const children = (await readdir(absolute, { withFileTypes: true }))
|
|
338
|
+
.filter(child => child.name !== ".git")
|
|
339
|
+
.sort((left, right) => Number(left.isDirectory()) - Number(right.isDirectory()) ||
|
|
340
|
+
(left.name < right.name ? -1 : left.name > right.name ? 1 : 0));
|
|
341
|
+
for (const child of children) {
|
|
342
|
+
await visit(join(path, child.name).replaceAll("\\", "/"), include);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
322
345
|
else {
|
|
346
|
+
if (!stat.isFile())
|
|
347
|
+
throw new Error("mission-review-source: unsupported artifact type");
|
|
323
348
|
hash.update(String(stat.size));
|
|
324
349
|
for await (const part of createReadStream(absolute)) {
|
|
325
350
|
const bytes = Buffer.isBuffer(part) ? part : Buffer.from(part);
|
|
@@ -328,7 +353,7 @@ export async function missionReviewSource(directory, run, evidence = [], baselin
|
|
|
328
353
|
preview = Buffer.concat([preview, bytes.subarray(0, room - preview.length)]);
|
|
329
354
|
}
|
|
330
355
|
}
|
|
331
|
-
if (include) {
|
|
356
|
+
if (include && !stat.isDirectory()) {
|
|
332
357
|
const headingFits = Buffer.byteLength(excerpt) + Buffer.byteLength(heading) <= 24_000;
|
|
333
358
|
if (headingFits) {
|
|
334
359
|
const rendered = preview.includes(0) ? "[binary artifact: bytes fingerprinted]" : preview.toString("utf8");
|
|
@@ -358,7 +383,9 @@ export async function missionReviewSource(directory, run, evidence = [], baselin
|
|
|
358
383
|
throw error;
|
|
359
384
|
hash.update("deleted");
|
|
360
385
|
}
|
|
361
|
-
}
|
|
386
|
+
};
|
|
387
|
+
for (const path of paths)
|
|
388
|
+
await visit(path);
|
|
362
389
|
if (external.length) {
|
|
363
390
|
// A declared write scope can also be a host-managed runtime directory (e.g. Docker's data root).
|
|
364
391
|
// Do not make review depend on listing it; record the missing coverage instead. Protected
|
|
@@ -375,7 +402,7 @@ export async function missionReviewSource(directory, run, evidence = [], baselin
|
|
|
375
402
|
if (bytes.length > 24_000 && truncatedSource.length === 0)
|
|
376
403
|
truncatedSource.push("(source diff exceeds excerpt budget)");
|
|
377
404
|
return { fingerprint: `sha256:${hash.digest("hex")}`, excerpt: (bytes.length > 24_000 ? bytes.subarray(0, 24_000).toString("utf8") : excerpt) +
|
|
378
|
-
(truncatedSource.length ? `\n[EXCERPT TRUNCATED: ${truncatedSource.slice(0, 20).join(", ")};
|
|
405
|
+
(truncatedSource.length ? `\n[EXCERPT TRUNCATED: ${truncatedSource.slice(0, 20).join(", ")}; Reviewer can read/search the relevant source directly]` : "") +
|
|
379
406
|
(unreadable.length ? `\n[UNINSPECTED EXTERNAL DIRECTORIES: ${unreadable.slice(0, 20).join(", ")}; select specific result files as review evidence]` : ""),
|
|
380
407
|
truncatedEvidence, truncatedSource };
|
|
381
408
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export declare const MODEL_COST_PRICING_SNAPSHOT: {
|
|
2
|
-
readonly checkedAt: "2026-09-
|
|
2
|
+
readonly checkedAt: "2026-09-30";
|
|
3
3
|
readonly currency: "USD";
|
|
4
4
|
readonly unit: "1M tokens";
|
|
5
|
-
readonly sources: readonly ["https://developers.openai.com/api/docs/pricing", "https://developers.openai.com/api/docs/models/gpt-6-astra", "https://developers.openai.com/api/docs/models/gpt-6-sol", "https://developers.openai.com/api/docs/models/gpt-6-luna", "https://developers.openai.com/api/docs/guides/fast-mode", "https://developers.openai.com/api/docs/models/gpt-5.6-sol", "https://developers.openai.com/api/docs/models/gpt-5.6-terra", "https://developers.openai.com/api/docs/models/gpt-5.6-luna", "https://platform.claude.com/docs/en/about-claude/pricing"];
|
|
6
|
-
readonly assumptions: readonly ["OpenAI Standard pricing; requests above 272,000 total input/cache tokens use 2x input/cache and 1.5x output pricing.", "Anthropic Standard pricing with the 5-minute cache-write rate; Batch, Flex, regional, tool, and subscription charges are excluded.", "variant and serviceTier are separate; model variants do not alter the selected Standard token price.", "GPT-6 Sol and GPT-6 Luna use their official Standard schedules; the OpenCode gpt-6-luna-fast selector sends API model gpt-6-luna with priority service tier.", "GPT-6 Sol
|
|
5
|
+
readonly sources: readonly ["https://developers.openai.com/api/docs/pricing", "https://developers.openai.com/api/docs/models/gpt-6-astra", "https://developers.openai.com/api/docs/models/gpt-6-sol", "https://developers.openai.com/api/docs/models/gpt-6.1-sol", "https://developers.openai.com/api/docs/models/gpt-6-luna", "https://developers.openai.com/api/docs/guides/fast-mode", "https://developers.openai.com/api/docs/models/gpt-5.6-sol", "https://developers.openai.com/api/docs/models/gpt-5.6-terra", "https://developers.openai.com/api/docs/models/gpt-5.6-luna", "https://platform.claude.com/docs/en/about-claude/pricing"];
|
|
6
|
+
readonly assumptions: readonly ["OpenAI Standard pricing; requests above 272,000 total input/cache tokens use 2x input/cache and 1.5x output pricing.", "Anthropic Standard pricing with the 5-minute cache-write rate; Batch, Flex, regional, tool, and subscription charges are excluded.", "variant and serviceTier are separate; model variants do not alter the selected Standard token price.", "GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna use their official Standard schedules; the OpenCode gpt-6-luna-fast selector sends API model gpt-6-luna with priority service tier.", "For GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna, Fast mode (service_tier fast or priority, including the gpt-6.1-sol-fast selector) multiplies applicable Standard rates by 2, including cache and long-context multipliers.", "gpt-5.6-luna-fast is retained only as a compatibility price for historical host catalog entries; it has no published model page and is exactly twice the GPT-5.6 Luna Standard schedule."];
|
|
7
7
|
};
|
|
8
8
|
export interface ModelCostUsage {
|
|
9
9
|
readonly providerID: string | undefined;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export const MODEL_COST_PRICING_SNAPSHOT = {
|
|
2
|
-
checkedAt: "2026-09-
|
|
2
|
+
checkedAt: "2026-09-30",
|
|
3
3
|
currency: "USD",
|
|
4
4
|
unit: "1M tokens",
|
|
5
5
|
sources: [
|
|
6
6
|
"https://developers.openai.com/api/docs/pricing",
|
|
7
7
|
"https://developers.openai.com/api/docs/models/gpt-6-astra",
|
|
8
8
|
"https://developers.openai.com/api/docs/models/gpt-6-sol",
|
|
9
|
+
"https://developers.openai.com/api/docs/models/gpt-6.1-sol",
|
|
9
10
|
"https://developers.openai.com/api/docs/models/gpt-6-luna",
|
|
10
11
|
"https://developers.openai.com/api/docs/guides/fast-mode",
|
|
11
12
|
"https://developers.openai.com/api/docs/models/gpt-5.6-sol",
|
|
@@ -17,14 +18,15 @@ export const MODEL_COST_PRICING_SNAPSHOT = {
|
|
|
17
18
|
"OpenAI Standard pricing; requests above 272,000 total input/cache tokens use 2x input/cache and 1.5x output pricing.",
|
|
18
19
|
"Anthropic Standard pricing with the 5-minute cache-write rate; Batch, Flex, regional, tool, and subscription charges are excluded.",
|
|
19
20
|
"variant and serviceTier are separate; model variants do not alter the selected Standard token price.",
|
|
20
|
-
"GPT-6 Sol and GPT-6 Luna use their official Standard schedules; the OpenCode gpt-6-luna-fast selector sends API model gpt-6-luna with priority service tier.",
|
|
21
|
-
"GPT-6 Sol
|
|
21
|
+
"GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna use their official Standard schedules; the OpenCode gpt-6-luna-fast selector sends API model gpt-6-luna with priority service tier.",
|
|
22
|
+
"For GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna, Fast mode (service_tier fast or priority, including the gpt-6.1-sol-fast selector) multiplies applicable Standard rates by 2, including cache and long-context multipliers.",
|
|
22
23
|
"gpt-5.6-luna-fast is retained only as a compatibility price for historical host catalog entries; it has no published model page and is exactly twice the GPT-5.6 Luna Standard schedule.",
|
|
23
24
|
],
|
|
24
25
|
};
|
|
25
26
|
const OPENAI = {
|
|
26
27
|
"gpt-6-astra": { input: 10, cacheRead: 1, cacheWrite: 12.5, output: 50 },
|
|
27
28
|
"gpt-6-sol": { input: 2, cacheRead: 0.2, cacheWrite: 2.5, output: 10 },
|
|
29
|
+
"gpt-6.1-sol": { input: 2, cacheRead: 0.1, cacheWrite: 2.5, output: 10 },
|
|
28
30
|
"gpt-6-luna": { input: 0.1, cacheRead: 0.01, cacheWrite: 0.125, output: 0.5 },
|
|
29
31
|
"gpt-5.6-sol": { input: 4, cacheRead: 0.4, cacheWrite: 5, output: 20 },
|
|
30
32
|
"gpt-5.6": { input: 4, cacheRead: 0.4, cacheWrite: 5, output: 20 },
|
|
@@ -43,14 +45,16 @@ export function estimateModelUsageCost(usage) {
|
|
|
43
45
|
usage.outputTokens, usage.reasoningTokens];
|
|
44
46
|
if (!counts.every(tokenCount))
|
|
45
47
|
return { status: "unpriced", reason: "missing-usage" };
|
|
46
|
-
const
|
|
48
|
+
const lunaFastAlias = usage.providerID?.toLowerCase() === "openai" && usage.modelID === "gpt-6-luna-fast";
|
|
49
|
+
const sol61FastAlias = usage.providerID?.toLowerCase() === "openai" && usage.modelID === "gpt-6.1-sol-fast";
|
|
50
|
+
const alias = lunaFastAlias || sol61FastAlias;
|
|
47
51
|
const fast = alias || (["fast", "priority"].includes(usage.serviceTier?.toLowerCase() ?? "") &&
|
|
48
|
-
usage.providerID?.toLowerCase() === "openai" && ["gpt-6-sol", "gpt-6-luna"].includes(usage.modelID ?? ""));
|
|
52
|
+
usage.providerID?.toLowerCase() === "openai" && ["gpt-6-sol", "gpt-6.1-sol", "gpt-6-luna"].includes(usage.modelID ?? ""));
|
|
49
53
|
if (usage.serviceTier !== undefined && !(fast ? ["standard", "default", "fast", "priority"] : ["standard", "default"]).includes(usage.serviceTier.toLowerCase())) {
|
|
50
54
|
return { status: "unpriced", reason: "unsupported-service-tier" };
|
|
51
55
|
}
|
|
52
56
|
const provider = usage.providerID?.toLowerCase();
|
|
53
|
-
const model =
|
|
57
|
+
const model = lunaFastAlias ? "gpt-6-luna" : sol61FastAlias ? "gpt-6.1-sol" : usage.modelID;
|
|
54
58
|
const base = provider === "openai" && model !== undefined && Object.hasOwn(OPENAI, model) ? OPENAI[model]
|
|
55
59
|
: provider === "anthropic" && model !== undefined && Object.hasOwn(ANTHROPIC, model) ? ANTHROPIC[model] : undefined;
|
|
56
60
|
if (base === undefined)
|
|
@@ -7,18 +7,18 @@ export interface RoleModelRoute {
|
|
|
7
7
|
readonly fallback?: readonly ModelTarget[];
|
|
8
8
|
}
|
|
9
9
|
export type ModelRoutingConfig = Readonly<Record<string, RoleModelRoute>>;
|
|
10
|
-
/** The stable serial implementation route stays on Sol when Luna fan-out is unsafe or unavailable. */
|
|
11
|
-
export declare const DEDICATED_WORKER_MODEL = "openai/gpt-6-sol";
|
|
10
|
+
/** The stable serial implementation route stays on GPT-6.1 Sol when Luna fan-out is unsafe or unavailable. */
|
|
11
|
+
export declare const DEDICATED_WORKER_MODEL = "openai/gpt-6.1-sol";
|
|
12
12
|
export declare const DEDICATED_WORKER_VARIANT = "medium";
|
|
13
13
|
/** Luna executes only units admitted to the fabric; it is not the serial worker's fallback target. */
|
|
14
14
|
export declare const LUNA_FABRIC_WORKER_MODEL = "openai/gpt-6-luna";
|
|
15
15
|
export declare const LUNA_FABRIC_WORKER_VARIANT = "max";
|
|
16
16
|
export declare const LUNA_FABRIC_WORKER_ROLE = "dog-luna-worker";
|
|
17
|
-
/** The coordinator uses Sol
|
|
18
|
-
export declare const DEFAULT_COORDINATOR_MODEL = "openai/gpt-6-sol";
|
|
17
|
+
/** The coordinator uses GPT-6.1 Sol High so routing and progress decisions do not bottleneck the workflow. */
|
|
18
|
+
export declare const DEFAULT_COORDINATOR_MODEL = "openai/gpt-6.1-sol";
|
|
19
19
|
export declare const DEFAULT_COORDINATOR_VARIANT = "high";
|
|
20
|
-
/** Compatibility names retained for the pre-v0.8 explicit Sol
|
|
21
|
-
export declare const ESCALATION_WORKER_MODEL = "openai/gpt-6-sol";
|
|
20
|
+
/** Compatibility names retained for the pre-v0.8 explicit Sol route. */
|
|
21
|
+
export declare const ESCALATION_WORKER_MODEL = "openai/gpt-6.1-sol";
|
|
22
22
|
export declare const ESCALATION_WORKER_VARIANT = "medium";
|
|
23
23
|
export declare const DEDICATED_WORKER_ROLES: readonly ["implementation", "remediation", "blocker-resolution", "sol-worker-mk2a2", "dog-worker"];
|
|
24
24
|
/** Ordered last-resort targets used only when the host proves a policy target unavailable. */
|
|
@@ -38,7 +38,7 @@ export declare const LUNA_FABRIC_WORKER_ROUTING: ModelRoutingConfig;
|
|
|
38
38
|
export declare function fixedWorkerRouting(dedicatedTarget?: ModelTarget): ModelRoutingConfig;
|
|
39
39
|
export declare const FIXED_MODEL_ROUTING: ModelRoutingConfig;
|
|
40
40
|
export declare const RECOMMENDED_LUNA_MODEL = "openai/gpt-6-luna";
|
|
41
|
-
/** Coordinator state and routing use Sol
|
|
41
|
+
/** Coordinator state and routing use GPT-6.1 Sol High; bounded evidence retrieval uses Luna High. */
|
|
42
42
|
export declare const DEFAULT_COORDINATOR_ROUTING: ModelRoutingConfig;
|
|
43
43
|
/** Evidence gathering is retrieval rather than reasoning, so the scout stays one effort tier lower. */
|
|
44
44
|
export declare const RECOMMENDED_SCOUT_VARIANT = "high";
|