sortie-dogs 0.12.25 → 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 +4 -4
- package/dist/core/operator-mission.d.ts +5 -9
- package/dist/core/operator-mission.js +28 -40
- package/dist/core/operator-runtime.d.ts +19 -0
- package/dist/core/operator-runtime.js +36 -13
- package/dist/plugin/adaptive-remediation-host.d.ts +1 -1
- package/dist/plugin/adaptive-remediation-host.js +1 -1
- package/dist/plugin/index.js +8 -4
- package/dist/plugin/mission-review.d.ts +12 -0
- package/dist/plugin/mission-review.js +101 -21
- 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 +222 -45
- package/dist/plugin/protected-snapshot.js +19 -3
- package/dist/plugin/run-metrics.d.ts +4 -1
- package/dist/plugin/run-metrics.js +12 -3
- package/dist/plugin/runtime-bridge.d.ts +6 -1
- 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 +161 -42
- 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.
|
|
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.
|
|
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
|
@@ -133,10 +133,10 @@ function classifyVersionTransition(installedValue, currentValue, v010Restore = f
|
|
|
133
133
|
// cross-minor migration; skipped lines still fail closed instead of bypassing migration steps.
|
|
134
134
|
const adjacentPreOneLine = installed.major === 0 && current.major === 0 &&
|
|
135
135
|
current.minor === installed.minor + 1;
|
|
136
|
-
// v0.11 used a different runtime.
|
|
137
|
-
// the 0.
|
|
136
|
+
// v0.11 used a different runtime. The v010 asset migration restores the 0.10
|
|
137
|
+
// preview into the 0.12/0.13 Mission line without selecting a v0.11 execution path.
|
|
138
138
|
const restoredPreview = v010Restore && installed.major === 0 && installed.minor === 10 &&
|
|
139
|
-
current.major === 0 && current.minor === 12;
|
|
139
|
+
current.major === 0 && (current.minor === 12 || current.minor === 13);
|
|
140
140
|
return sameLine || adjacentPreOneLine || restoredPreview ? "compatible-update" : "incompatible";
|
|
141
141
|
}
|
|
142
142
|
async function metadata(path) {
|
|
@@ -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")
|
|
@@ -241,11 +236,11 @@ export class OperatorMissionRuntime {
|
|
|
241
236
|
}
|
|
242
237
|
if (previous)
|
|
243
238
|
await this.save(this.file(root, `.${previous.id}`), previous);
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
const predecessor =
|
|
248
|
-
|
|
239
|
+
// The Operator runtime's current cancelled run is authoritative for an explicit
|
|
240
|
+
// replacement. A no-run mission can still carry an older ancestor's run ID.
|
|
241
|
+
// Ordinary continuation retains that predecessor when no current run is supplied.
|
|
242
|
+
const predecessor = (replaceRequirements ? options.cancelledRunID : undefined) ??
|
|
243
|
+
previous?.runID ?? previous?.supersededRunID;
|
|
249
244
|
const state = { version: "0.12", id: `mission-${randomUUID()}`, root, requests: [request],
|
|
250
245
|
kind: options.kind ?? "implementation",
|
|
251
246
|
context: (options.context ?? []).filter(item => item.id !== request.id),
|
|
@@ -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,19 +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].match(/R\d+/gu) ?? []) }));
|
|
517
|
-
if (grouped.every(item => item.ids.length === 0) && raw.length === mission.requirements.length)
|
|
518
|
-
return raw;
|
|
519
|
-
const unknown = grouped.flatMap(item => item.ids).filter(id => !mission.requirements.some(requirement => requirement.id === id));
|
|
520
|
-
const missing = mission.requirements.filter(requirement => !grouped.some(item => item.ids.includes(requirement.id)));
|
|
521
|
-
if (unknown.length || missing.length)
|
|
522
|
-
throw new Error(`mission-review-traces: name the existing R IDs; missing ${missing.map(item => item.id).join(", ")}; unknown ${unknown.join(", ")}`);
|
|
523
|
-
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);
|
|
524
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. */
|
|
@@ -920,11 +920,11 @@ export class OperatorRuntime {
|
|
|
920
920
|
`goal_declaration_path: ${declarationPath}`, "acceptance:", ...plan.acceptance.map(value => ` - ${value}`),
|
|
921
921
|
"validation:", ...unit.validation.map(value => ` - ${value}`),
|
|
922
922
|
...(mission ? ["Read handoff_path and other repository files using their project-relative paths as supplied. The native working directory is project_root; do not prepend or reconstruct its absolute path for read/search/shell. Copy project_root only when binding the write gate. Preserve explicitly declared external paths."] : []),
|
|
923
|
-
mission ? "Read-only investigation commands are unrestricted. Use shell to reproduce and diagnose without asking for command registration. Keep all writes, including generated/transient outputs and cleanup, inside unit.write. Run formal validation exactly as listed, in order and in separate calls, so the host records its real result. If a write scope or formal check must change, return the precise change to your Coordinator; it can extend/redeclare immediately within the original requirements. Diagnostic success is not formal acceptance evidence."
|
|
923
|
+
mission ? "Read-only investigation commands are unrestricted. Use shell to reproduce and diagnose without asking for command registration. Keep all writes, including generated/transient outputs and cleanup, inside unit.write. Run formal validation exactly as listed, in order and in separate calls, so the host records its real result. If a write scope or formal check must change, return the precise change to your parent Operator or Coordinator; it can extend/redeclare immediately within the original requirements. Diagnostic success is not formal acceptance evidence."
|
|
924
924
|
: "Execute validation in its declared order. Earlier entries may be approved generator, build, formatter, or exact cleanup commands required before canonical criterion tests. Every persistent or transient generator output must be declared in unit.write. Cleanup may remove only declared unit.write outputs and must be an explicit ordered command after generation and before post-commit or canonical validation; never add an ignore rule or remove an undeclared path. If any necessary command, input, output, or cleanup is missing, do not run an undeclared command or variant and do not use resume evidence tooling to invent permission; return a contract-repair decision.",
|
|
925
925
|
...(mission ? [] : ["Preserve existing public API success and error return semantics unless acceptance explicitly changes them, and cover those compatibility boundaries in the declared validation."]),
|
|
926
926
|
mission
|
|
927
|
-
? "Complete the assigned work and listed validation within this Task. For a known operation, proceed through setup, execution and result collection; preparation alone is not execution. Preserve existing public behavior when changing source. Do not spawn nested subagents. The Coordinator handles any applicable independent review after your return; review is not a prerequisite to execution. Return actual results, including failed or not-started operations, and any exact contract correction needed."
|
|
927
|
+
? "Complete the assigned work and listed validation within this Task. For a known operation, proceed through setup, execution and result collection; preparation alone is not execution. Preserve existing public behavior when changing source. Do not spawn nested subagents. The parent Operator or Coordinator handles any applicable independent review after your return; review is not a prerequisite to execution. Return actual results, including failed or not-started operations, and any exact contract correction needed."
|
|
928
928
|
: "Do not spawn nested subagents for consultation. Required consultations belong to the root before dispatch; use the confirmed decisions and evidence declared in the unit objective and inputs. If required consultation results or user decisions are missing, return the exact contract gap to the parent instead of attempting a deeper Task, inventing consent, or asking the user to repeat an already recorded decision.",
|
|
929
929
|
...(plan.git_lifecycle !== undefined && index === plan.units.length - 1 ? [
|
|
930
930
|
`git_post_commit_validation: ${JSON.stringify(plan.git_lifecycle.post_commit_validation)}`,
|
|
@@ -1564,6 +1564,11 @@ export class OperatorRuntime {
|
|
|
1564
1564
|
state.units.some(candidate => candidate.terminalRescue))
|
|
1565
1565
|
throw new Error("operator-mission-normal-remediation-unavailable");
|
|
1566
1566
|
await this.verifyControls(unit);
|
|
1567
|
+
// The ordinary retry keeps its exact scope and validation, but the next Worker needs the
|
|
1568
|
+
// host-observed failed command/exit rather than reconstructing it from an earlier session.
|
|
1569
|
+
unit.task = { ...unit.task, prompt: `${unit.task.prompt}\nnormal_remediation_prior_validation: ${JSON.stringify({
|
|
1570
|
+
command: unit.failure.command, exit_code: unit.failure.exitCode
|
|
1571
|
+
})}` };
|
|
1567
1572
|
unit.normalRemediationUsed = true;
|
|
1568
1573
|
unit.status = "pending";
|
|
1569
1574
|
unit.callID = null;
|
|
@@ -1899,6 +1904,16 @@ export class OperatorRuntime {
|
|
|
1899
1904
|
for (const unit of current.units)
|
|
1900
1905
|
await this.verifyControls(unit);
|
|
1901
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
|
+
}
|
|
1902
1917
|
packet(state) {
|
|
1903
1918
|
const proved = new Set(state.units.flatMap(unit => unit.evidence.flatMap(item => item.measurement.criterion_ids)));
|
|
1904
1919
|
const current = state.units.find(unit => unit.status !== "succeeded");
|
|
@@ -2030,9 +2045,10 @@ export class OperatorRuntime {
|
|
|
2030
2045
|
}
|
|
2031
2046
|
async continuationCheckpoint(root) {
|
|
2032
2047
|
const state = await this.read(root);
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2048
|
+
if (!state)
|
|
2049
|
+
return undefined;
|
|
2050
|
+
const nextAction = this.continuationNextAction(state);
|
|
2051
|
+
if (nextAction === null)
|
|
2036
2052
|
return undefined;
|
|
2037
2053
|
const current = state.units.find(unit => unit.status !== "succeeded");
|
|
2038
2054
|
return JSON.stringify({ authority: "durable-operator-state", root_session_id: state.rootSessionID,
|
|
@@ -2041,14 +2057,21 @@ export class OperatorRuntime {
|
|
|
2041
2057
|
next_task_ref: current?.status === "pending" ? (state.units.length > 1
|
|
2042
2058
|
? state.operatorSessionID === null ? this.dispatchTask(state).prompt : null
|
|
2043
2059
|
: current.repairValidation === null ? this.workerTask(state, current).prompt : this.repairWorkerTask(state, current).prompt) : null,
|
|
2044
|
-
next_action:
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
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`;
|
|
2052
2075
|
}
|
|
2053
2076
|
controlReference(path) {
|
|
2054
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 {};
|
package/dist/plugin/index.js
CHANGED
|
@@ -6060,8 +6060,12 @@ export const SortieDogsPlugin = async (input, options) => {
|
|
|
6060
6060
|
appLogInfo("run-metrics.career-unavailable", textInput.sessionID, { outcome: runOutcome }, "warn");
|
|
6061
6061
|
}
|
|
6062
6062
|
}
|
|
6063
|
-
if (sortieResult !== undefined)
|
|
6064
|
-
|
|
6063
|
+
if (sortieResult !== undefined) {
|
|
6064
|
+
const review = terminal?.receipt?.status === "succeeded"
|
|
6065
|
+
? await input.runtimeBridge?.missionReviewPresentation?.(textInput.sessionID).catch(() => undefined)
|
|
6066
|
+
: undefined;
|
|
6067
|
+
textOutput.text = insertSortieResult(textOutput.text, sortieResult, review?.verdict, review?.evidenceGaps);
|
|
6068
|
+
}
|
|
6065
6069
|
else if (metrics !== undefined && runOutcome === "DONE")
|
|
6066
6070
|
textOutput.text = insertRunMetrics(textOutput.text, metrics);
|
|
6067
6071
|
const { debrief: _debriefObservation, ...metricSummary } = metrics ?? {};
|
|
@@ -7445,7 +7449,7 @@ export const SortieDogsPlugin = async (input, options) => {
|
|
|
7445
7449
|
},
|
|
7446
7450
|
};
|
|
7447
7451
|
input.runtimeBridge?.connected?.({
|
|
7448
|
-
renderReturnReport: async (root, text, expectedReceipt) => {
|
|
7452
|
+
renderReturnReport: async (root, text, expectedReceipt, missionReview, reviewEvidenceGaps) => {
|
|
7449
7453
|
let rendered;
|
|
7450
7454
|
await serializeChatTransition(root, async () => {
|
|
7451
7455
|
if (!isCoordinatorSession(root) && !await recoverCoordinatorRoot(root))
|
|
@@ -7473,7 +7477,7 @@ export const SortieDogsPlugin = async (input, options) => {
|
|
|
7473
7477
|
catch {
|
|
7474
7478
|
appLogInfo("run-metrics.career-unavailable", root, { profile: runtimeProfile.id }, "warn");
|
|
7475
7479
|
}
|
|
7476
|
-
rendered = insertSortieResult(receiptBoundTerminalText(text, receipt), result);
|
|
7480
|
+
rendered = insertSortieResult(receiptBoundTerminalText(text, receipt), result, missionReview, reviewEvidenceGaps);
|
|
7477
7481
|
});
|
|
7478
7482
|
return rendered;
|
|
7479
7483
|
},
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import type { OperatorState } from "../core/operator-runtime.js";
|
|
2
2
|
import { type MissionEvidenceExcerpt, type MissionReviewScope, type OperatorMission } from "../core/operator-mission.js";
|
|
3
3
|
import { type RuntimeProfile } from "../core/runtime-profile.js";
|
|
4
|
+
/** Show native command outcomes to the Reviewer without turning non-criterion checks into acceptance evidence. */
|
|
5
|
+
export declare function observedMissionValidation(validation: readonly string[], childSessionID: string | null, history: readonly Record<string, unknown>[]): {
|
|
6
|
+
attempts: readonly {
|
|
7
|
+
command: string;
|
|
8
|
+
exit_code: number | null;
|
|
9
|
+
started_ms: number | null;
|
|
10
|
+
completed_ms: number | null;
|
|
11
|
+
}[];
|
|
12
|
+
not_observed: readonly string[];
|
|
13
|
+
omitted_attempts: number;
|
|
14
|
+
};
|
|
4
15
|
export declare function missionReviewBaseline(directory: string): Promise<string | undefined>;
|
|
5
16
|
/** A child ID alone cannot establish the initial phase after a restart or failed dispatch. */
|
|
6
17
|
export declare function initialMissionReviewPrompt(mission: OperatorMission, prompts: readonly string[]): string | undefined;
|
|
@@ -14,4 +25,5 @@ export declare function missionReviewSource(directory: string, run: OperatorStat
|
|
|
14
25
|
fingerprint: string;
|
|
15
26
|
excerpt: string;
|
|
16
27
|
truncatedEvidence: string[];
|
|
28
|
+
truncatedSource: string[];
|
|
17
29
|
}>;
|