sortie-dogs 0.10.20 → 0.10.22
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 +7 -7
- package/dist/core/operator-proposal.d.ts +12 -1
- package/dist/core/operator-proposal.js +86 -2
- package/dist/plugin/adaptive-remediation-host.d.ts +1 -1
- package/dist/plugin/adaptive-remediation-host.js +1 -1
- package/dist/plugin/model-cost.d.ts +3 -3
- package/dist/plugin/model-cost.js +7 -2
- package/dist/plugin/model-routing.d.ts +7 -7
- package/dist/plugin/model-routing.js +5 -5
- package/dist/plugin/profiled.js +50 -8
- package/dist/runtime-assets-v010.js +9 -1
- package/dist/runtime-assets.d.ts +2 -2
- package/dist/runtime-assets.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -198,7 +198,7 @@ not invent, probe, or translate variant names.
|
|
|
198
198
|
- `freeTierFallbackModels`: ordered global last-resort model IDs. Default:
|
|
199
199
|
`opencode/deepseek-v4-flash-free`; `[]` disables this fallback.
|
|
200
200
|
- `dedicatedWorkerModel`: canonical stable serial target, default
|
|
201
|
-
`openai/gpt-
|
|
201
|
+
`openai/gpt-6-sol` / `medium`. The v0.10 profile also supplies its explicit
|
|
202
202
|
role routes below; do not infer the v0.10 worker route from this stable setting.
|
|
203
203
|
- `consultation.strategy`: fixed advisor identity, optional `required`, and
|
|
204
204
|
positive `maxCallsPerCandidate`; default one call and not required.
|
|
@@ -237,13 +237,13 @@ reuse the same evidence instead of spending the validation budget again.
|
|
|
237
237
|
|
|
238
238
|
### Default v0.10 routes
|
|
239
239
|
|
|
240
|
-
- `dog-operator`: `openai/gpt-
|
|
241
|
-
- `dogs-coordinator`: `openai/gpt-
|
|
242
|
-
- `dog-worker-v010`: `openai/gpt-
|
|
243
|
-
- `dog-scout-v010`: `openai/gpt-
|
|
244
|
-
- `dog-reviewer-v010`: `openai/gpt-
|
|
240
|
+
- `dog-operator`: `openai/gpt-6-luna` / `max`
|
|
241
|
+
- `dogs-coordinator`: `openai/gpt-6-sol` / `xhigh`
|
|
242
|
+
- `dog-worker-v010`: `openai/gpt-6-luna` / `max`
|
|
243
|
+
- `dog-scout-v010`: `openai/gpt-6-luna` / `xhigh`
|
|
244
|
+
- `dog-reviewer-v010`: `openai/gpt-6-sol` / `xhigh`
|
|
245
245
|
- `dog-advisor-v010`: preferred declared `anthropic/claude-opus-5`, otherwise
|
|
246
|
-
`openai/gpt-
|
|
246
|
+
`openai/gpt-6-sol` / `xhigh`
|
|
247
247
|
|
|
248
248
|
An explicit model and variant selected in OpenCode remains authoritative for that
|
|
249
249
|
session. Child role defaults fill absent native settings and may be overridden by
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RuntimeProfile } from "./runtime-profile.js";
|
|
2
|
-
import { type OperatorPlan, type OperatorTask } from "./operator-runtime.js";
|
|
2
|
+
import { type OperatorPlan, type OperatorState, type OperatorTask } from "./operator-runtime.js";
|
|
3
3
|
export declare const DEFAULT_OPERATOR_PROPOSAL_BUDGET: Readonly<{
|
|
4
4
|
max_reads: 45;
|
|
5
5
|
max_submissions: 9;
|
|
@@ -94,6 +94,14 @@ export interface OperatorProposalState {
|
|
|
94
94
|
/** Preparation may publish execution controls before approval commits; never revise that pinned plan. */
|
|
95
95
|
approval_started?: boolean;
|
|
96
96
|
root_revisions?: OperatorProposalRevision[];
|
|
97
|
+
/** Immutable archive identities of earlier approved contracts on this root. */
|
|
98
|
+
approved_history?: readonly {
|
|
99
|
+
readonly archive_hash: string;
|
|
100
|
+
readonly intent_id: string;
|
|
101
|
+
readonly proposal_id: string;
|
|
102
|
+
readonly run_id: string;
|
|
103
|
+
readonly disposition: "completed" | "incomplete";
|
|
104
|
+
}[];
|
|
97
105
|
}
|
|
98
106
|
interface OperatorProposalIdentity {
|
|
99
107
|
readonly proposal_id: string;
|
|
@@ -136,6 +144,7 @@ export declare class OperatorProposalRuntime {
|
|
|
136
144
|
readonly projectRoot: string;
|
|
137
145
|
constructor(projectRoot: string, profile: RuntimeProfile);
|
|
138
146
|
private file;
|
|
147
|
+
private approvedArchiveFile;
|
|
139
148
|
private spendFile;
|
|
140
149
|
private readSpend;
|
|
141
150
|
private saveSpend;
|
|
@@ -153,6 +162,8 @@ export declare class OperatorProposalRuntime {
|
|
|
153
162
|
private resolveTask;
|
|
154
163
|
begin(root: string, raw: unknown): Promise<OperatorProposalState>;
|
|
155
164
|
private beginUnlocked;
|
|
165
|
+
/** Explicit root-only transition after an approved contract's execution lane has ended. */
|
|
166
|
+
reviseApproved(root: string, actor: string, raw: unknown, readRun: () => Promise<OperatorState | undefined>, currentGoal: OperatorProposalGoalBinding): Promise<OperatorProposalState>;
|
|
156
167
|
bindGoal(root: string, binding: OperatorProposalGoalBinding): Promise<OperatorProposalState>;
|
|
157
168
|
private bindGoalUnlocked;
|
|
158
169
|
admit(root: string, callID: string, args: unknown, reserveBudget?: () => Promise<void>): Promise<OperatorTask>;
|
|
@@ -343,6 +343,9 @@ export class OperatorProposalRuntime {
|
|
|
343
343
|
this.projectRoot = resolve(projectRoot);
|
|
344
344
|
}
|
|
345
345
|
file(root) { return join(this.projectRoot, this.profile.stateDirectory, "operator-proposals", `${hash(root)}.json`); }
|
|
346
|
+
approvedArchiveFile(root, intentID, proposalHash, runID) {
|
|
347
|
+
return join(this.projectRoot, this.profile.stateDirectory, "operator-proposals", `${hash(root)}.${intentID}.${proposalHash}.${hash(runID).slice(0, 16)}.approved.json`);
|
|
348
|
+
}
|
|
346
349
|
spendFile(root) { return join(this.projectRoot, this.profile.stateDirectory, "operator-proposals", `${hash(root)}.spend.json`); }
|
|
347
350
|
async readSpend(root) {
|
|
348
351
|
let source;
|
|
@@ -367,6 +370,12 @@ export class OperatorProposalRuntime {
|
|
|
367
370
|
!/^sha256:[a-f0-9]{64}$/u.test(spend.retry.goal_binding.acceptance_fingerprint))) {
|
|
368
371
|
throw new Error("operator-proposal-spend-invalid");
|
|
369
372
|
}
|
|
373
|
+
if (spend.approved_history !== undefined && (!Array.isArray(spend.approved_history) ||
|
|
374
|
+
spend.approved_history.some(item => !record(item) || !/^[a-f0-9]{64}$/u.test(String(item.archive_hash)) ||
|
|
375
|
+
!identifier(item.intent_id) || !identifier(item.proposal_id) || !text(item.run_id) ||
|
|
376
|
+
!["completed", "incomplete"].includes(String(item.disposition))))) {
|
|
377
|
+
throw new Error("operator-proposal-spend-invalid");
|
|
378
|
+
}
|
|
370
379
|
return spend;
|
|
371
380
|
}
|
|
372
381
|
async saveSpend(spend) {
|
|
@@ -543,11 +552,85 @@ export class OperatorProposalRuntime {
|
|
|
543
552
|
goal_binding: spend.retry?.intent_hash === intentHash ? structuredClone(spend.retry.goal_binding) : null,
|
|
544
553
|
proposal_call_id: null, proposal_session_id: null, read_count: spend.reads, read_paths: [], submission_count: spend.submissions, proposal_id: null,
|
|
545
554
|
...(spend.reads > 0 || spend.submissions > 0 ? { prior_spend: { reads: spend.reads, submissions: spend.submissions } } : {}),
|
|
546
|
-
proposal_revision: null, proposal_hash: null, proposal: null, approval_rationale: null
|
|
555
|
+
proposal_revision: null, proposal_hash: null, proposal: null, approval_rationale: null,
|
|
556
|
+
...(spend.approved_history ? { approved_history: structuredClone(spend.approved_history) } : {}) };
|
|
547
557
|
this.assertBudgetAvailable(state);
|
|
548
558
|
await this.save(state);
|
|
549
559
|
return state;
|
|
550
560
|
}
|
|
561
|
+
/** Explicit root-only transition after an approved contract's execution lane has ended. */
|
|
562
|
+
async reviseApproved(root, actor, raw, readRun, currentGoal) {
|
|
563
|
+
if (actor !== root)
|
|
564
|
+
throw new Error("operator-proposal-approved-revision-root-required");
|
|
565
|
+
return this.serial(root, async () => {
|
|
566
|
+
if (!record(raw) || !exactSet(raw, ["proposal_id", "revision", "content_hash", "operator_run_id", "rationale", "intent"]) ||
|
|
567
|
+
typeof raw.proposal_id !== "string" || !Number.isSafeInteger(raw.revision) || typeof raw.content_hash !== "string" ||
|
|
568
|
+
typeof raw.operator_run_id !== "string" || !text(raw.rationale)) {
|
|
569
|
+
throw new Error("operator-proposal-approved-revision-invalid");
|
|
570
|
+
}
|
|
571
|
+
const previous = await this.requiredUnlocked(root);
|
|
572
|
+
if (previous.phase !== "approved" || !previous.proposal || !previous.goal_binding) {
|
|
573
|
+
throw new Error("operator-proposal-approved-revision-not-approved");
|
|
574
|
+
}
|
|
575
|
+
if (raw.proposal_id !== previous.proposal_id || raw.revision !== previous.proposal_revision ||
|
|
576
|
+
raw.content_hash !== previous.proposal_hash)
|
|
577
|
+
throw new Error("operator-proposal-approved-revision-identity-mismatch");
|
|
578
|
+
const run = await readRun();
|
|
579
|
+
if (!run || !["cancelled", "completed"].includes(run.phase) || run.rootSessionID !== root ||
|
|
580
|
+
run.runID !== raw.operator_run_id || run.planHash !== hash(JSON.stringify(previous.proposal.plan)) ||
|
|
581
|
+
JSON.stringify(run.acceptance) !== JSON.stringify(previous.proposal.plan.acceptance)) {
|
|
582
|
+
throw new Error("operator-proposal-approved-revision-terminal-run-required");
|
|
583
|
+
}
|
|
584
|
+
if (!text(currentGoal.goal_id) || !Number.isSafeInteger(currentGoal.revision) || currentGoal.revision < 1 ||
|
|
585
|
+
!Number.isSafeInteger(currentGoal.scope_epoch) || currentGoal.scope_epoch < 1 ||
|
|
586
|
+
!/^sha256:[a-f0-9]{64}$/u.test(currentGoal.acceptance_fingerprint)) {
|
|
587
|
+
throw new Error("operator-proposal-goal-binding-invalid");
|
|
588
|
+
}
|
|
589
|
+
if (JSON.stringify(currentGoal) === JSON.stringify(previous.goal_binding)) {
|
|
590
|
+
throw new Error("operator-proposal-approved-revision-goal-revision-required");
|
|
591
|
+
}
|
|
592
|
+
const intent = parseIntent(raw.intent), intentHash = hash(JSON.stringify(intent));
|
|
593
|
+
if (intentHash === previous.intent_hash)
|
|
594
|
+
throw new Error("operator-proposal-approved-revision-intent-unchanged");
|
|
595
|
+
if (currentGoal.goal_id === previous.goal_binding.goal_id &&
|
|
596
|
+
JSON.stringify(intent.requirements.slice(0, previous.intent.requirements.length)) !== JSON.stringify(previous.intent.requirements)) {
|
|
597
|
+
throw new Error("operator-proposal-approved-revision-acceptance-continuity-required");
|
|
598
|
+
}
|
|
599
|
+
const remainingReads = intent.proposal_budget.max_reads - previous.read_count;
|
|
600
|
+
const remainingSubmissions = intent.proposal_budget.max_submissions - previous.submission_count;
|
|
601
|
+
if (remainingReads <= 0 || remainingSubmissions <= 0) {
|
|
602
|
+
throw new OperatorProposalBudgetError({ status: "proposal-budget-exhausted",
|
|
603
|
+
code: remainingReads <= 0 ? "operator-proposal-read-budget-exhausted" : "operator-proposal-submission-budget-exhausted",
|
|
604
|
+
reads: previous.read_count, max_reads: intent.proposal_budget.max_reads, remaining_reads: Math.max(0, remainingReads),
|
|
605
|
+
submissions: previous.submission_count, max_submissions: intent.proposal_budget.max_submissions,
|
|
606
|
+
remaining_submissions: Math.max(0, remainingSubmissions),
|
|
607
|
+
required_minimum_budget: { max_reads: previous.read_count + 1, max_submissions: previous.submission_count + 1 } });
|
|
608
|
+
}
|
|
609
|
+
const archive = JSON.stringify({ approved_proposal: previous, terminal_run: {
|
|
610
|
+
run_id: run.runID, plan_hash: run.planHash, acceptance: run.acceptance, acceptance_fingerprint: run.acceptanceFingerprint,
|
|
611
|
+
phase: run.phase, decision: run.decision, receipt: run.receipt, generation: run.generation
|
|
612
|
+
} });
|
|
613
|
+
const archivePath = this.approvedArchiveFile(root, previous.intent_id, previous.proposal_hash, run.runID);
|
|
614
|
+
try {
|
|
615
|
+
await writeFile(archivePath, archive, { flag: "wx", mode: 0o600 });
|
|
616
|
+
}
|
|
617
|
+
catch (error) {
|
|
618
|
+
if (error.code !== "EEXIST" || hash(await readFile(archivePath, "utf8")) !== hash(archive))
|
|
619
|
+
throw error;
|
|
620
|
+
}
|
|
621
|
+
const state = { schema_version: "0.1", profile: this.profile.id, root_session_id: root,
|
|
622
|
+
intent_id: `intent-${intentHash.slice(0, 24)}`, intent_hash: intentHash, intent, created_at: new Date().toISOString(),
|
|
623
|
+
phase: "investigating", goal_binding: structuredClone(currentGoal),
|
|
624
|
+
prior_spend: { reads: previous.read_count, submissions: previous.submission_count },
|
|
625
|
+
proposal_call_id: null, proposal_session_id: null, read_count: previous.read_count, read_paths: [],
|
|
626
|
+
submission_count: previous.submission_count, proposal_id: null, proposal_revision: null, proposal_hash: null,
|
|
627
|
+
proposal: null, approval_rationale: null,
|
|
628
|
+
approved_history: [...(previous.approved_history ?? []), { archive_hash: hash(archive), intent_id: previous.intent_id,
|
|
629
|
+
proposal_id: previous.proposal_id, run_id: run.runID, disposition: run.phase === "completed" ? "completed" : "incomplete" }] };
|
|
630
|
+
await this.save(state);
|
|
631
|
+
return state;
|
|
632
|
+
});
|
|
633
|
+
}
|
|
551
634
|
async bindGoal(root, binding) {
|
|
552
635
|
return this.serial(root, () => this.bindGoalUnlocked(root, binding));
|
|
553
636
|
}
|
|
@@ -826,6 +909,7 @@ export class OperatorProposalRuntime {
|
|
|
826
909
|
return undefined;
|
|
827
910
|
await this.saveSpend({ schema_version: "0.1", profile: this.profile.id, root_session_id: root,
|
|
828
911
|
reads: state.read_count, submissions: state.submission_count,
|
|
912
|
+
...(state.approved_history ? { approved_history: state.approved_history } : {}),
|
|
829
913
|
...(state.goal_binding === null ? {} : { retry: { intent_hash: state.intent_hash, goal_binding: state.goal_binding } }) });
|
|
830
914
|
await rm(this.file(root), { force: true });
|
|
831
915
|
return state;
|
|
@@ -849,7 +933,7 @@ export class OperatorProposalRuntime {
|
|
|
849
933
|
remaining_reads: state.intent.proposal_budget.max_reads - state.read_count, submissions: state.submission_count,
|
|
850
934
|
remaining_submissions: state.intent.proposal_budget.max_submissions - state.submission_count,
|
|
851
935
|
task_admitted: state.proposal_call_id !== null, uncovered: state.proposal?.uncovered ?? [], proposal: state.proposal,
|
|
852
|
-
approval_rationale: state.approval_rationale, root_revisions: state.root_revisions ?? [],
|
|
936
|
+
approval_rationale: state.approval_rationale, root_revisions: state.root_revisions ?? [], approved_history: state.approved_history ?? [],
|
|
853
937
|
revision_available: state.phase === "submitted" && !state.approval_started && state.submission_count < state.intent.proposal_budget.max_submissions };
|
|
854
938
|
}
|
|
855
939
|
}
|
|
@@ -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-
|
|
26
|
+
export declare const DEFAULT_ADAPTIVE_REMEDIATION_MODEL = "openai/gpt-6-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-
|
|
13
|
+
export const DEFAULT_ADAPTIVE_REMEDIATION_MODEL = "openai/gpt-6-sol";
|
|
14
14
|
const responseData = (value) => {
|
|
15
15
|
if (value === null || typeof value !== "object")
|
|
16
16
|
return {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export declare const MODEL_COST_PRICING_SNAPSHOT: {
|
|
2
|
-
readonly checkedAt: "2026-09-
|
|
2
|
+
readonly checkedAt: "2026-09-23";
|
|
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-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; Fast, Batch, Flex, regional, tool, and subscription charges are excluded.", "variant and serviceTier are separate; model variants do not alter the selected Standard token price.", "
|
|
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/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; Fast, 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; Fast mode is a service tier priced separately and does not create a second model ID.", "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,10 +1,12 @@
|
|
|
1
1
|
export const MODEL_COST_PRICING_SNAPSHOT = {
|
|
2
|
-
checkedAt: "2026-09-
|
|
2
|
+
checkedAt: "2026-09-23",
|
|
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
|
+
"https://developers.openai.com/api/docs/models/gpt-6-sol",
|
|
9
|
+
"https://developers.openai.com/api/docs/models/gpt-6-luna",
|
|
8
10
|
"https://developers.openai.com/api/docs/models/gpt-5.6-sol",
|
|
9
11
|
"https://developers.openai.com/api/docs/models/gpt-5.6-terra",
|
|
10
12
|
"https://developers.openai.com/api/docs/models/gpt-5.6-luna",
|
|
@@ -14,11 +16,14 @@ export const MODEL_COST_PRICING_SNAPSHOT = {
|
|
|
14
16
|
"OpenAI Standard pricing; requests above 272,000 total input/cache tokens use 2x input/cache and 1.5x output pricing.",
|
|
15
17
|
"Anthropic Standard pricing with the 5-minute cache-write rate; Fast, Batch, Flex, regional, tool, and subscription charges are excluded.",
|
|
16
18
|
"variant and serviceTier are separate; model variants do not alter the selected Standard token price.",
|
|
17
|
-
"
|
|
19
|
+
"GPT-6 Sol and GPT-6 Luna use their official Standard schedules; Fast mode is a service tier priced separately and does not create a second model ID.",
|
|
20
|
+
"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.",
|
|
18
21
|
],
|
|
19
22
|
};
|
|
20
23
|
const OPENAI = {
|
|
21
24
|
"gpt-6-astra": { input: 10, cacheRead: 1, cacheWrite: 12.5, output: 50 },
|
|
25
|
+
"gpt-6-sol": { input: 2, cacheRead: 0.2, cacheWrite: 2.5, output: 10 },
|
|
26
|
+
"gpt-6-luna": { input: 0.1, cacheRead: 0.01, cacheWrite: 0.125, output: 0.5 },
|
|
22
27
|
"gpt-5.6-sol": { input: 4, cacheRead: 0.4, cacheWrite: 5, output: 20 },
|
|
23
28
|
"gpt-5.6": { input: 4, cacheRead: 0.4, cacheWrite: 5, output: 20 },
|
|
24
29
|
"gpt-5.6-terra": { input: 2, cacheRead: 0.2, cacheWrite: 2.5, output: 12 },
|
|
@@ -8,17 +8,17 @@ export interface RoleModelRoute {
|
|
|
8
8
|
}
|
|
9
9
|
export type ModelRoutingConfig = Readonly<Record<string, RoleModelRoute>>;
|
|
10
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-
|
|
11
|
+
export declare const DEDICATED_WORKER_MODEL = "openai/gpt-6-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
|
-
export declare const LUNA_FABRIC_WORKER_MODEL = "openai/gpt-
|
|
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
|
|
18
|
-
export declare const DEFAULT_COORDINATOR_MODEL = "openai/gpt-
|
|
17
|
+
/** The coordinator uses Sol 6 High so routing and progress decisions do not bottleneck the workflow. */
|
|
18
|
+
export declare const DEFAULT_COORDINATOR_MODEL = "openai/gpt-6-sol";
|
|
19
19
|
export declare const DEFAULT_COORDINATOR_VARIANT = "high";
|
|
20
20
|
/** Compatibility names retained for the pre-v0.8 explicit Sol target. */
|
|
21
|
-
export declare const ESCALATION_WORKER_MODEL = "openai/gpt-
|
|
21
|
+
export declare const ESCALATION_WORKER_MODEL = "openai/gpt-6-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. */
|
|
@@ -37,8 +37,8 @@ export declare const LUNA_FABRIC_WORKER_TARGET: ModelTarget;
|
|
|
37
37
|
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
|
-
export declare const RECOMMENDED_LUNA_MODEL = "openai/gpt-
|
|
41
|
-
/** Coordinator state and routing use
|
|
40
|
+
export declare const RECOMMENDED_LUNA_MODEL = "openai/gpt-6-luna";
|
|
41
|
+
/** Coordinator state and routing use Sol 6 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";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { CONSULTATION_ROLE_POLICY } from "../core/consultation.js";
|
|
2
2
|
/** The stable serial implementation route stays on Sol when Luna fan-out is unsafe or unavailable. */
|
|
3
|
-
export const DEDICATED_WORKER_MODEL = "openai/gpt-
|
|
3
|
+
export const DEDICATED_WORKER_MODEL = "openai/gpt-6-sol";
|
|
4
4
|
export const DEDICATED_WORKER_VARIANT = "medium";
|
|
5
5
|
/** Luna executes only units admitted to the fabric; it is not the serial worker's fallback target. */
|
|
6
|
-
export const LUNA_FABRIC_WORKER_MODEL = "openai/gpt-
|
|
6
|
+
export const LUNA_FABRIC_WORKER_MODEL = "openai/gpt-6-luna";
|
|
7
7
|
export const LUNA_FABRIC_WORKER_VARIANT = "max";
|
|
8
8
|
export const LUNA_FABRIC_WORKER_ROLE = "dog-luna-worker";
|
|
9
|
-
/** The coordinator uses
|
|
10
|
-
export const DEFAULT_COORDINATOR_MODEL = "openai/gpt-
|
|
9
|
+
/** The coordinator uses Sol 6 High so routing and progress decisions do not bottleneck the workflow. */
|
|
10
|
+
export const DEFAULT_COORDINATOR_MODEL = "openai/gpt-6-sol";
|
|
11
11
|
export const DEFAULT_COORDINATOR_VARIANT = "high";
|
|
12
12
|
/** Compatibility names retained for the pre-v0.8 explicit Sol target. */
|
|
13
13
|
export const ESCALATION_WORKER_MODEL = DEDICATED_WORKER_MODEL;
|
|
@@ -64,7 +64,7 @@ export function fixedWorkerRouting(dedicatedTarget = DEFAULT_DEDICATED_WORKER_TA
|
|
|
64
64
|
export const FIXED_MODEL_ROUTING = fixedWorkerRouting();
|
|
65
65
|
const fixedModelRoleSet = new Set(Object.keys(FIXED_MODEL_ROUTING));
|
|
66
66
|
export const RECOMMENDED_LUNA_MODEL = LUNA_FABRIC_WORKER_MODEL;
|
|
67
|
-
/** Coordinator state and routing use
|
|
67
|
+
/** Coordinator state and routing use Sol 6 High; bounded evidence retrieval uses Luna High. */
|
|
68
68
|
export const DEFAULT_COORDINATOR_ROUTING = Object.freeze({
|
|
69
69
|
"dog-coordinator": Object.freeze({
|
|
70
70
|
preferred: Object.freeze({
|
package/dist/plugin/profiled.js
CHANGED
|
@@ -22,17 +22,17 @@ const SERIAL_OPTIONAL_ARGUMENTS = new Map([
|
|
|
22
22
|
"scope", "trigger", "cause", "prevention", "evidence", "evidenceRef", "id", "promotedRef", "confirmation",
|
|
23
23
|
])],
|
|
24
24
|
]);
|
|
25
|
-
const PREVIEW_WORKER_ROUTE = Object.freeze({ model: "openai/gpt-
|
|
26
|
-
const PREVIEW_SCOUT_ROUTE = Object.freeze({ model: "openai/gpt-
|
|
25
|
+
const PREVIEW_WORKER_ROUTE = Object.freeze({ model: "openai/gpt-6-luna", variant: "max" });
|
|
26
|
+
const PREVIEW_SCOUT_ROUTE = Object.freeze({ model: "openai/gpt-6-luna", variant: "xhigh" });
|
|
27
27
|
/**
|
|
28
28
|
* Contract authorship, not throughput. Qualification observed a cheaper operations model emit
|
|
29
29
|
* structurally valid but under-scoped contracts: a write union narrower than the remediation the
|
|
30
30
|
* review it also schedules demands, which strands an otherwise complete run on NEED_DECISION.
|
|
31
31
|
*/
|
|
32
|
-
const PREVIEW_OPERATIONS_ROUTE = Object.freeze({ model: "openai/gpt-
|
|
33
|
-
const PREVIEW_PRIMARY_ROUTE = Object.freeze({ model: "openai/gpt-
|
|
32
|
+
const PREVIEW_OPERATIONS_ROUTE = Object.freeze({ model: "openai/gpt-6-sol", variant: "xhigh" });
|
|
33
|
+
const PREVIEW_PRIMARY_ROUTE = Object.freeze({ model: "openai/gpt-6-luna", variant: "max" });
|
|
34
34
|
/** Review must be able to reject the worker's output, so it never shares the worker's model family. */
|
|
35
|
-
const PREVIEW_REVIEW_ROUTE = Object.freeze({ model: "openai/gpt-
|
|
35
|
+
const PREVIEW_REVIEW_ROUTE = Object.freeze({ model: "openai/gpt-6-sol", variant: "xhigh" });
|
|
36
36
|
/** Every preview route the profile can bind a role to. Catalog declaration reads this one list. */
|
|
37
37
|
const PREVIEW_ROUTES = Object.freeze([
|
|
38
38
|
PREVIEW_PRIMARY_ROUTE, PREVIEW_WORKER_ROUTE, PREVIEW_SCOUT_ROUTE, PREVIEW_OPERATIONS_ROUTE,
|
|
@@ -55,9 +55,16 @@ export function processRemediationReplacementPacket(code, packet, cancelTool, pr
|
|
|
55
55
|
*/
|
|
56
56
|
export function previewModelCatalog(routes = PREVIEW_ROUTES, base = BUILT_IN_MODEL_CATALOG.global ?? []) {
|
|
57
57
|
const variantsOf = (model) => [...new Set(routes.filter(route => route.model === model).map(route => route.variant))];
|
|
58
|
-
const
|
|
58
|
+
const mergedBase = new Map();
|
|
59
|
+
for (const entry of base) {
|
|
60
|
+
const prior = mergedBase.get(entry.model);
|
|
61
|
+
mergedBase.set(entry.model, prior === undefined
|
|
62
|
+
? entry
|
|
63
|
+
: { model: entry.model, variants: [...new Set([...(prior.variants ?? []), ...(entry.variants ?? [])])] });
|
|
64
|
+
}
|
|
65
|
+
const listed = new Set(mergedBase.keys());
|
|
59
66
|
return [
|
|
60
|
-
...
|
|
67
|
+
...[...mergedBase.values()].map(entry => {
|
|
61
68
|
const variants = variantsOf(entry.model);
|
|
62
69
|
return variants.length === 0
|
|
63
70
|
? entry
|
|
@@ -398,6 +405,13 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
398
405
|
const revisionSchema = record(stringSchema) && typeof stringSchema.describe === "function"
|
|
399
406
|
? stringSchema.describe(OPERATOR_PROPOSAL_REVISION_CONTRACT)
|
|
400
407
|
: { ...(record(stringSchema) ? stringSchema : { type: "string" }), description: OPERATOR_PROPOSAL_REVISION_CONTRACT };
|
|
408
|
+
const approvedRevisionContract = "revision_json must encode exactly {proposal_id:string,revision:positive integer,content_hash:string,operator_run_id:string,rationale:nonblank single-line string,intent:object}. " +
|
|
409
|
+
"The intent has the exact begin_operator_proposal intent_json shape and a cumulative proposal_budget with room above all retained reads/submissions. " +
|
|
410
|
+
"Pin the approved proposal identity and the cancelled/completed run ID from operator_status. For the same goal, the new requirements must begin with every old ordered requirement byte-for-byte. Only a root acting for a newly authorized active goal may revise; active/prepared runs, stale identity or unchanged goal binding are denied. " +
|
|
411
|
+
"Old acceptance, terminal status and proposal accounting remain durable. This returns an investigation Task, not implementation or acceptance.";
|
|
412
|
+
const approvedRevisionSchema = record(stringSchema) && typeof stringSchema.describe === "function"
|
|
413
|
+
? stringSchema.describe(approvedRevisionContract)
|
|
414
|
+
: { ...(record(stringSchema) ? stringSchema : { type: "string" }), description: approvedRevisionContract };
|
|
401
415
|
const planContract = "plan_json must encode the exact operator plan object: schema_version, acceptance, acceptance_proof, source_refs, " +
|
|
402
416
|
"goal_declaration, units, and optional git_lifecycle only. git_lifecycle exact shape is " +
|
|
403
417
|
'{branch_create:{branch:string,start_ref:string},commit:{message:string},post_commit_validation:string[],remediation_reserve?:string[],remediation_scope_expansion?:string[]}. Its presence is root authorization for only a clean, non-overwriting ' +
|
|
@@ -424,6 +438,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
424
438
|
const submitProposal = profileTool(profile, "sortie_submit_operator_proposal");
|
|
425
439
|
const approveProposal = profileTool(profile, "sortie_approve_operator_proposal");
|
|
426
440
|
const reviseProposal = profileTool(profile, "sortie_revise_operator_proposal");
|
|
441
|
+
const reviseApprovedIntent = profileTool(profile, "sortie_revise_approved_operator_intent");
|
|
427
442
|
async function stop(root, reason, retireRoot = true) {
|
|
428
443
|
if (retireRoot)
|
|
429
444
|
retired.add(root);
|
|
@@ -805,6 +820,33 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
805
820
|
return JSON.stringify({ ...proposals.packet(state), task: proposals.referenceTask(state),
|
|
806
821
|
dispatch_instruction: "Pass this short Task reference verbatim; do not append or paraphrase it." });
|
|
807
822
|
} };
|
|
823
|
+
tools[reviseApprovedIntent] = { description: `Root-only: after a terminal cancelled/completed run, explicitly replace its approved proposal with a new user-authorized intent. Supply revision_json with exactly {proposal_id,revision,content_hash,operator_run_id,rationale,intent}; pin the approved identity and terminal run from operator_status. The intent has the exact ${beginProposal} intent_json shape and a cumulative proposal_budget strictly above retained reads/submissions. A current active goal with a changed binding and no outstanding reservations is required. The prior approved contract, ordered acceptance, terminal disposition and cumulative proposal spend are archived; the old run is never accepted, revived or overwritten. Active/prepared runs and stale identities are rejected. This grants one new investigation Task, not approval or execution.`,
|
|
824
|
+
args: { revision_json: approvedRevisionSchema }, execute: async (args, context) => {
|
|
825
|
+
await requireRoot(context.sessionID);
|
|
826
|
+
return serializeDispatchTransition(context.sessionID, async () => {
|
|
827
|
+
let request;
|
|
828
|
+
try {
|
|
829
|
+
request = JSON.parse(args.revision_json);
|
|
830
|
+
}
|
|
831
|
+
catch {
|
|
832
|
+
return JSON.stringify({ status: "invalid-approved-revision", code: "operator-proposal-approved-revision-json-invalid" });
|
|
833
|
+
}
|
|
834
|
+
try {
|
|
835
|
+
const binding = await control.proposalGoalBinding(context.sessionID);
|
|
836
|
+
await control.assertActiveGoal(context.sessionID, binding.acceptance_fingerprint);
|
|
837
|
+
const revised = await proposals.reviseApproved(context.sessionID, context.sessionID, request, () => new OperatorRuntime(input.directory, profile).read(context.sessionID), binding);
|
|
838
|
+
return JSON.stringify({ ...proposals.packet(revised), task: proposals.referenceTask(revised),
|
|
839
|
+
dispatch_instruction: "Dispatch this new exact Task reference once; do not reuse the prior approved contract or its child." });
|
|
840
|
+
}
|
|
841
|
+
catch (error) {
|
|
842
|
+
if (error instanceof OperatorProposalBudgetError)
|
|
843
|
+
return JSON.stringify(error.diagnostic);
|
|
844
|
+
if (!(error instanceof Error) || !error.message.startsWith("operator-proposal-"))
|
|
845
|
+
throw error;
|
|
846
|
+
return JSON.stringify({ status: "invalid-approved-revision", code: error.message });
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
} };
|
|
808
850
|
tools[submitProposal] = { description: "Proposal-child-only: submit a requirement-mapped contract proposal without editing source or starting workers. " + proposalContract + " Omit plan.acceptance; the host derives its exact ordered text from durable intent.requirements. A legacy explicit plan.acceptance is accepted only when byte-exact in content and order; null, subsets, reorder, normalization, and acceptance_ids aliases are rejected.",
|
|
809
851
|
args: { proposal_json: proposalSchema }, execute: async (args, context) => {
|
|
810
852
|
const root = await rootFor(context.sessionID);
|
|
@@ -886,7 +928,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
886
928
|
});
|
|
887
929
|
} };
|
|
888
930
|
const ownTools = new Set([prepare, repair, next, status, cancel, complete, resume, resolveContractRepair,
|
|
889
|
-
beginProposal, submitProposal, approveProposal, reviseProposal]);
|
|
931
|
+
beginProposal, submitProposal, approveProposal, reviseProposal, reviseApprovedIntent]);
|
|
890
932
|
const protocolMap = CANONICAL_AGENT_ROLES.map(role => `${role}=${profileAgent(profile, role)}`).join(", ");
|
|
891
933
|
function rememberRendered(key, text) {
|
|
892
934
|
renderedParts.set(key, goalFingerprint(text));
|
|
@@ -89,7 +89,7 @@ permission rejection shows a different project root, do not repeat that path; re
|
|
|
89
89
|
const coordinatorContent = `---
|
|
90
90
|
description: Sortie-dogs ${V010_RUNTIME_ASSET_VERSION} primary dog-operator — strategic authority with a bounded operations delegate.
|
|
91
91
|
mode: primary
|
|
92
|
-
model: openai/gpt-
|
|
92
|
+
model: openai/gpt-6-luna
|
|
93
93
|
variant: max
|
|
94
94
|
permission:
|
|
95
95
|
question: allow
|
|
@@ -153,6 +153,14 @@ Every requirement entry must include kind="requirement" | "negative" | "quality"
|
|
|
153
153
|
Use only authoritative_refs and allow_read for begin intent scope. project_root, source_refs, max_read_prefixes,
|
|
154
154
|
authoritative_references, and other aliases are invalid. Do not guess a smaller contract after rejection: use this exact
|
|
155
155
|
shape, preserving all ordered requirements, and omit proposal_budget only when the deterministic host default is intended.
|
|
156
|
+
If the root already has an approved proposal, first finish or cancel its operator run. After a genuinely new user-authorized
|
|
157
|
+
goal is active, use ${profile.toolPrefix}revise_approved_operator_intent with revision_json containing exactly the old
|
|
158
|
+
proposal_id, revision, content_hash, terminal operator_run_id, a single-line rationale, and the complete new intent object.
|
|
159
|
+
Pin the identity from operator_status. The host refuses active/prepared runs, stale identities, unchanged goal bindings,
|
|
160
|
+
and budgets without room above cumulative proposal spend. It archives the old approved intent, ordered acceptance and
|
|
161
|
+
terminal result before granting one new investigation Task. Within the same goal, retain the old ordered requirements
|
|
162
|
+
byte-for-byte as a prefix of the new intent; a separate user-authorized goal may have a different order. No child, unit,
|
|
163
|
+
acceptance or budget is revived or reset.
|
|
156
164
|
Freeze product requirements from the original request, not extra implementation criteria invented from workflow
|
|
157
165
|
bookkeeping. Keep proposal read/submission allowances in proposal_budget and host counters; do not turn spent
|
|
158
166
|
budgets or your own reporting obligations into worker validation commands. Preserve any explicit user requirement.
|
package/dist/runtime-assets.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare const runtimeAssets: readonly [{
|
|
|
12
12
|
readonly content: `---
|
|
13
13
|
description: Canonical MkII coordinator packaged by Sortie-dogs
|
|
14
14
|
mode: primary
|
|
15
|
-
model: openai/gpt-
|
|
15
|
+
model: openai/gpt-6-sol
|
|
16
16
|
variant: high
|
|
17
17
|
permission:
|
|
18
18
|
question: allow
|
|
@@ -414,7 +414,7 @@ uses the run's shared time/cost limits. Use the existing compiled plan and Luna
|
|
|
414
414
|
Call sortie_prepare_failure_swarm. Dispatch only its returned ready descriptors with
|
|
415
415
|
dog-luna-worker and one failure_swarm_descriptor JSON line. The plugin binds source scope,
|
|
416
416
|
read-only authority, distinct causes, cumulative budget, and the shared cancellable lifecycle.
|
|
417
|
-
No diagnosis child may write or select a remedy. After findings finish, the coordinator (
|
|
417
|
+
No diagnosis child may write or select a remedy. After findings finish, the coordinator (Sol 6 by
|
|
418
418
|
default, or the user's explicitly selected coordinator) calls sortie_select_failure_diagnosis
|
|
419
419
|
with swarm_id and one selection_json containing diagnosis_id, capsule_id, recovery_kind,
|
|
420
420
|
proposal, and budget_request. Preserve its immutable scope/acceptance/validation contract and
|
package/dist/runtime-assets.js
CHANGED
|
@@ -241,7 +241,7 @@ export const runtimeAssets = [
|
|
|
241
241
|
content: `---
|
|
242
242
|
description: Canonical MkII coordinator packaged by Sortie-dogs
|
|
243
243
|
mode: primary
|
|
244
|
-
model: openai/gpt-
|
|
244
|
+
model: openai/gpt-6-sol
|
|
245
245
|
variant: high
|
|
246
246
|
permission:
|
|
247
247
|
question: allow
|
|
@@ -643,7 +643,7 @@ uses the run's shared time/cost limits. Use the existing compiled plan and Luna
|
|
|
643
643
|
Call sortie_prepare_failure_swarm. Dispatch only its returned ready descriptors with
|
|
644
644
|
dog-luna-worker and one failure_swarm_descriptor JSON line. The plugin binds source scope,
|
|
645
645
|
read-only authority, distinct causes, cumulative budget, and the shared cancellable lifecycle.
|
|
646
|
-
No diagnosis child may write or select a remedy. After findings finish, the coordinator (
|
|
646
|
+
No diagnosis child may write or select a remedy. After findings finish, the coordinator (Sol 6 by
|
|
647
647
|
default, or the user's explicitly selected coordinator) calls sortie_select_failure_diagnosis
|
|
648
648
|
with swarm_id and one selection_json containing diagnosis_id, capsule_id, recovery_kind,
|
|
649
649
|
proposal, and budget_request. Preserve its immutable scope/acceptance/validation contract and
|