sortie-dogs 0.14.0 → 0.14.2
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 +32 -8
- package/dist/asset-version.d.ts +1 -1
- package/dist/asset-version.js +1 -1
- package/dist/cli/codex-mission.js +3 -0
- package/dist/codex/mission-session.d.ts +2 -1
- package/dist/codex/mission-session.js +57 -5
- package/dist/core/operator-mission.d.ts +8 -0
- package/dist/core/operator-mission.js +2 -1
- package/dist/plugin/mission-review.js +12 -3
- package/dist/plugin/profiled.js +79 -6
- package/dist/runtime-mission-assets.d.ts +3 -1
- package/dist/runtime-mission-assets.js +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,8 +19,8 @@ evidence-backed result, not more agents for their own sake.
|
|
|
19
19
|
[](https://www.npmjs.com/package/sortie-dogs)
|
|
20
20
|
[](LICENSE)
|
|
21
21
|
|
|
22
|
-
**Current release: [v0.14.
|
|
23
|
-
· [Release notes](docs/release-v0.14.
|
|
22
|
+
**Current release: [v0.14.2](https://github.com/zufall-upon/Sortie-dogs/releases/tag/v0.14.2)**
|
|
23
|
+
· [Release notes](docs/release-v0.14.2.md) · [Execution vision](docs/v0.14.0-execution-vision.md)
|
|
24
24
|
|
|
25
25
|
[Quick start](#quick-start) · [Workflow](#mission-workflow) · [Models](#default-models) ·
|
|
26
26
|
[Measured results](#measured-results) · [Configuration](#configuration) · [Documentation](#documentation)
|
|
@@ -57,7 +57,7 @@ Use an existing Codex CLI signed in with **ChatGPT**. On Windows, PowerShell **7
|
|
|
57
57
|
available; POSIX uses bash. Sortie does not install Codex, start login or use a metered API fallback.
|
|
58
58
|
|
|
59
59
|
```sh
|
|
60
|
-
npm install --save-dev sortie-dogs@0.14.
|
|
60
|
+
npm install --save-dev sortie-dogs@0.14.2
|
|
61
61
|
npx --no-install sortie-dogs codex init .
|
|
62
62
|
```
|
|
63
63
|
|
|
@@ -86,7 +86,7 @@ bridge. [Codex guide: SDK, permissions, progress, resume and manifest route](doc
|
|
|
86
86
|
Use **OpenCode V2**. In the target project:
|
|
87
87
|
|
|
88
88
|
```sh
|
|
89
|
-
npm install --save-dev sortie-dogs@0.14.
|
|
89
|
+
npm install --save-dev sortie-dogs@0.14.2
|
|
90
90
|
npx --no-install sortie-dogs init .
|
|
91
91
|
```
|
|
92
92
|
|
|
@@ -178,6 +178,30 @@ general speed or success-rate guarantee.
|
|
|
178
178
|
|
|
179
179
|
### SWE-bench evaluation
|
|
180
180
|
|
|
181
|
+
#### v0.14.0 dev23 (2026-10-15 UTC)
|
|
182
|
+
|
|
183
|
+
**Official resolution: 10/23 (43.48%); Mission completion: 22/23.** One pass through the normal
|
|
184
|
+
OpenCode CLI + Sortie Mission path, using the fixed released v0.14.0 package.
|
|
185
|
+
|
|
186
|
+
- All 23 frozen patches were officially scored: **10 resolved, 13 unresolved**, zero empty patches,
|
|
187
|
+
evaluation errors or infrastructure failures. The cost-stopped `sqlfluff__sqlfluff-2419` patch
|
|
188
|
+
resolved officially, but its Mission remains incomplete; official correctness does not imply acceptance.
|
|
189
|
+
- Pinned public Lite dev rows; one inference attempt per task, no retries. Official grading:
|
|
190
|
+
`split=dev`, `max_workers=1`, `retry_count=0`. Inference concurrency was **1** due to low host memory.
|
|
191
|
+
- Actual Operator/Coordinator/Reviewer model: `openai/gpt-6.1-sol#xhigh`;
|
|
192
|
+
Worker: `openai/gpt-6-luna-fast#max`. Ten cases used Workers; 13 used Coordinator direct execution.
|
|
193
|
+
- Inference wall time **2h53m28s**; separate official grading **7m19s**.
|
|
194
|
+
- Known estimated inference cost **$16.76**, with one pending usage record. Separate holds:
|
|
195
|
+
**$2** for unresolved usage and **$5** for implementation/supervision; these are not known expenses.
|
|
196
|
+
Costs are API-equivalent estimates, not invoices; the $2/task monitor is not an exact billing cap.
|
|
197
|
+
- Release/runner commit `e69a3b2317a76eeea1229034f52902812ff1d580`;
|
|
198
|
+
package SHA-256 `120922c31dd6d85040210d68456192b4e6aa45dc87a11451476f3ed576a68e30`.
|
|
199
|
+
|
|
200
|
+
Local evidence (generated artifacts are not committed):
|
|
201
|
+
`_testenv/autodev/sortie-dogs-dev23/benchmark-v0140-20261015/one-pass-summary.json`.
|
|
202
|
+
|
|
203
|
+
#### Historical v0.12.24 test300
|
|
204
|
+
|
|
181
205
|
**SWE-bench Lite test300: 170/300 (56.67%)**, fixed **v0.12.24**, one pass@1 campaign.
|
|
182
206
|
Nine empty patches, zero official evaluation errors, frozen predictions and trajectories for all
|
|
183
207
|
300 instances. Workers ran Luna Fast/max; management/review ran GPT-6 Sol/xhigh.
|
|
@@ -195,8 +219,8 @@ known expense. Official local evaluation and leaderboard acceptance are separate
|
|
|
195
219
|
**8/23 (34.8%)**, versus v0.12.25's 7/23; all seven prior resolutions retained, no empty patches or
|
|
196
220
|
official evaluation errors. [Fixed conditions, stopped-run accounting and costs](docs/benchmarks/swebench-lite-history.md#v0131-dev23-2026-09-30).
|
|
197
221
|
|
|
198
|
-
|
|
199
|
-
|
|
222
|
+
Each score belongs to its fixed candidate. SWE-bench remains an optional measurement, not a release
|
|
223
|
+
gate. Different splits, budgets, models and conditions are not controlled comparisons or proof of a fix's effect.
|
|
200
224
|
|
|
201
225
|
## Configuration
|
|
202
226
|
|
|
@@ -218,7 +242,7 @@ Install the desired package version and rerun **your host's** initializer:
|
|
|
218
242
|
|
|
219
243
|
An OpenCode config-local bridge may resolve a separate package; npm-global update alone does not
|
|
220
244
|
update it. [Global/update instructions](docs/configuration.md#global-availability).
|
|
221
|
-
The current Mission asset marker is `0.14.
|
|
245
|
+
The current Mission asset marker is `0.14.2-cold-resume-v1`; the unchanged Codex skill marker is
|
|
222
246
|
`0.13.11-codex-skill-v2`. Installed markers alone do not prove a running host reloaded the new version.
|
|
223
247
|
|
|
224
248
|
There is no supported uninstall command. Remove the dependency and only known Sortie-owned paths;
|
|
@@ -234,7 +258,7 @@ follow the [manual removal guide](docs/uninstall.md), never delete the entire `.
|
|
|
234
258
|
[SWE-bench history](docs/benchmarks/swebench-lite-history.md) · [Historical local case study](docs/benchmark-reference.md).
|
|
235
259
|
- **Development:** [Testing](docs/testing.md) · [CLI testing](docs/cli-testing.md) ·
|
|
236
260
|
[Windows tests](docs/windows-tests.md) · [Release routine](docs/release-batch.md).
|
|
237
|
-
- **Releases:** [v0.14.0](docs/release-v0.14.0.md) · [v0.13.22](docs/release-v0.13.22.md) · [v0.13.21](docs/release-v0.13.21.md) · [v0.13.20](docs/release-v0.13.20.md) · [v0.13.19](docs/release-v0.13.19.md) · [v0.13.18](docs/release-v0.13.18.md) · [v0.13.17](docs/release-v0.13.17.md) · [v0.13.16](docs/release-v0.13.16.md) · [v0.13.15](docs/release-v0.13.15.md) · [v0.13.14](docs/release-v0.13.14.md) · [v0.13.13](docs/release-v0.13.13.md) · [v0.13.12](docs/release-v0.13.12.md) · [v0.13.11](docs/release-v0.13.11.md) · [v0.13.10](docs/release-v0.13.10.md) ·
|
|
261
|
+
- **Releases:** [v0.14.2](docs/release-v0.14.2.md) · [v0.14.1](docs/release-v0.14.1.md) · [v0.14.0](docs/release-v0.14.0.md) · [v0.13.22](docs/release-v0.13.22.md) · [v0.13.21](docs/release-v0.13.21.md) · [v0.13.20](docs/release-v0.13.20.md) · [v0.13.19](docs/release-v0.13.19.md) · [v0.13.18](docs/release-v0.13.18.md) · [v0.13.17](docs/release-v0.13.17.md) · [v0.13.16](docs/release-v0.13.16.md) · [v0.13.15](docs/release-v0.13.15.md) · [v0.13.14](docs/release-v0.13.14.md) · [v0.13.13](docs/release-v0.13.13.md) · [v0.13.12](docs/release-v0.13.12.md) · [v0.13.11](docs/release-v0.13.11.md) · [v0.13.10](docs/release-v0.13.10.md) ·
|
|
238
262
|
[v0.13.9](docs/release-v0.13.9.md) · [All GitHub releases](https://github.com/zufall-upon/Sortie-dogs/releases).
|
|
239
263
|
|
|
240
264
|
## Community
|
package/dist/asset-version.d.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
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.14.
|
|
6
|
+
export declare const V010_RUNTIME_ASSET_VERSION = "0.14.2-cold-resume-v1";
|
|
7
7
|
export declare const CODEX_SKILL_ASSET_VERSION = "0.13.11-codex-skill-v2";
|
|
8
8
|
export type RuntimeAssetVersion = typeof RUNTIME_ASSET_VERSION | typeof V010_RUNTIME_ASSET_VERSION | typeof CODEX_SKILL_ASSET_VERSION;
|
package/dist/asset-version.js
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
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.14.
|
|
6
|
+
export const V010_RUNTIME_ASSET_VERSION = "0.14.2-cold-resume-v1";
|
|
7
7
|
export const CODEX_SKILL_ASSET_VERSION = "0.13.11-codex-skill-v2";
|
|
@@ -71,6 +71,9 @@ export function codexMissionProgress(event) {
|
|
|
71
71
|
native_status: event.params.turn?.status };
|
|
72
72
|
if (event.method === "sortie/continuation")
|
|
73
73
|
return { thread_id: event.threadId, turn_id: event.params.turnId, phase: event.params.phase, calls: event.params.calls };
|
|
74
|
+
if (event.method === "sortie/coordinatorRestored")
|
|
75
|
+
return { thread_id: event.threadId, phase: "coordinator-restored", mission_id: event.params.missionId,
|
|
76
|
+
coordinator_id: event.params.coordinatorId, call_id: event.params.callId, native_outcome: event.params.outcome, next_action: event.params.action };
|
|
74
77
|
if (event.method === "sortie/modelRoute")
|
|
75
78
|
return { thread_id: event.threadId, phase: "model-route", agent: event.params.agent, model: event.params.model,
|
|
76
79
|
effort: event.params.effort, service_tier: event.params.serviceTier };
|
|
@@ -79,8 +79,9 @@ export declare class CodexMissionSession {
|
|
|
79
79
|
close(): Promise<void>;
|
|
80
80
|
private claimOwner;
|
|
81
81
|
private rootOf;
|
|
82
|
+
private restoreCoordinator;
|
|
82
83
|
private recoverNotStarted;
|
|
83
|
-
private
|
|
84
|
+
private bindTaskDispatch;
|
|
84
85
|
private recoverCompletedWorker;
|
|
85
86
|
private required;
|
|
86
87
|
private executeHostCommand;
|
|
@@ -62,6 +62,7 @@ export class CodexMissionSession {
|
|
|
62
62
|
this.observations = missions.find(item => item.root === resume)?.codexUsage ?? [];
|
|
63
63
|
await this.restoreSession(resume, "dog-operator");
|
|
64
64
|
this.root = resume;
|
|
65
|
+
await this.restoreCoordinator(resume);
|
|
65
66
|
await this.claimOwner(resume);
|
|
66
67
|
await this.hooks.tool?.sortie_v010_operator_status?.execute({ view: "full" }, { sessionID: resume, agent: "dog-operator" });
|
|
67
68
|
}
|
|
@@ -118,6 +119,45 @@ export class CodexMissionSession {
|
|
|
118
119
|
current = this.required(current.parentID);
|
|
119
120
|
return current.id;
|
|
120
121
|
}
|
|
122
|
+
async restoreCoordinator(root) {
|
|
123
|
+
const missions = new OperatorMissionRuntime(this.directory, profile);
|
|
124
|
+
const mission = await missions.required(root);
|
|
125
|
+
if (!mission.coordinator || ["completed", "cancelled"].includes(mission.phase))
|
|
126
|
+
return;
|
|
127
|
+
if (!await codexOwnerGone(mission.codexOwner))
|
|
128
|
+
throw new Error("codex-mission-owner-active:no-resend");
|
|
129
|
+
// Codex can persist claim() and the child turn but omit the interrupted parent
|
|
130
|
+
// Task item. The existing Mission binding still owns this same Coordinator.
|
|
131
|
+
const coordinator = await this.restoreSession(mission.coordinator, "dogs-coordinator", root);
|
|
132
|
+
if (coordinator.parentID !== root || coordinator.agent !== "dogs-coordinator")
|
|
133
|
+
throw new Error("Retained Coordinator lineage mismatch.");
|
|
134
|
+
if (mission.dispatchOpen && mission.callID) {
|
|
135
|
+
// A retained terminal parent receipt already has the shared reconciliation path.
|
|
136
|
+
// The new binding is required only when that exact receipt is missing.
|
|
137
|
+
const parentReceipts = this.required(root).history.flatMap(message => Array.isArray(message.parts) ? message.parts.filter(object) : [])
|
|
138
|
+
.filter(part => part.type === "tool" && part.tool === "task" && part.callID === mission.callID && object(part.state) &&
|
|
139
|
+
["completed", "error"].includes(String(part.state.status)) && object(part.state.input) &&
|
|
140
|
+
part.state.input.subagent_type === coordinator.agent &&
|
|
141
|
+
(part.state.input.task_id === undefined || part.state.input.task_id === coordinator.id));
|
|
142
|
+
if (parentReceipts.length === 1)
|
|
143
|
+
return;
|
|
144
|
+
const binding = mission.codexCoordinatorDispatch;
|
|
145
|
+
if (!binding || binding.missionID !== mission.id || binding.threadID !== root || binding.callID !== mission.callID ||
|
|
146
|
+
binding.childThreadID !== coordinator.id || binding.ownerGeneration !== mission.codexOwner?.generation ||
|
|
147
|
+
coordinator.history.filter(message => object(message.info) && message.info.role === "user" &&
|
|
148
|
+
message.info.id === binding.clientUserMessageID).length !== 1)
|
|
149
|
+
throw new Error("Retained Coordinator has unproven execution for the current dispatch; no resend. Reconcile its exact native turn before resuming.");
|
|
150
|
+
await missions.codexRecovery(root, async (current) => {
|
|
151
|
+
if (current.codexOwner?.generation !== binding.ownerGeneration || !await codexOwnerGone(current.codexOwner) ||
|
|
152
|
+
JSON.stringify(current.codexCoordinatorDispatch) !== JSON.stringify(binding))
|
|
153
|
+
throw new Error("codex-mission-recovery-generation-stale");
|
|
154
|
+
await missions.reconcileFinishedDispatch(root, mission.id, mission.callID);
|
|
155
|
+
});
|
|
156
|
+
await this.options.onEvent?.({ method: "sortie/coordinatorRestored", threadId: root,
|
|
157
|
+
params: { missionId: mission.id, coordinatorId: coordinator.id, callId: mission.callID,
|
|
158
|
+
outcome: coordinator.outcome, action: "resume-existing-task" } });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
121
161
|
async recoverNotStarted(threadID, turn, item) {
|
|
122
162
|
if (item.tool !== "task" || !object(item.arguments) || item.arguments.task_id || typeof item.id !== "string" || typeof turn.id !== "string" ||
|
|
123
163
|
!["completed", "interrupted", "failed"].includes(String(turn.status)))
|
|
@@ -156,7 +196,18 @@ export class CodexMissionSession {
|
|
|
156
196
|
}
|
|
157
197
|
return false;
|
|
158
198
|
}
|
|
159
|
-
async
|
|
199
|
+
async bindTaskDispatch(parent, child, call, messageID) {
|
|
200
|
+
if (child.agent === "dogs-coordinator") {
|
|
201
|
+
await new OperatorMissionRuntime(this.directory, profile).update(this.rootOf(parent), state => {
|
|
202
|
+
if (state.root !== call.threadId || state.coordinator !== child.id || state.callID !== call.callId || !state.dispatchOpen ||
|
|
203
|
+
state.codexOwner?.generation !== this.owner.generation || state.codexOwner.closed)
|
|
204
|
+
throw new Error("codex-mission-dispatch-owner-stale");
|
|
205
|
+
state.codexCoordinatorDispatch = { missionID: state.id, threadID: call.threadId, turnID: call.turnId, callID: call.callId,
|
|
206
|
+
inputHash: createHash("sha256").update(JSON.stringify(call.arguments)).digest("hex"),
|
|
207
|
+
childThreadID: child.id, clientUserMessageID: messageID, ownerGeneration: this.owner.generation };
|
|
208
|
+
});
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
160
211
|
if (child.agent !== "dog-worker-v010" || !object(call.arguments) || call.arguments.task_id)
|
|
161
212
|
return;
|
|
162
213
|
const root = this.rootOf(parent), missions = new OperatorMissionRuntime(this.directory, profile);
|
|
@@ -365,7 +416,7 @@ export class CodexMissionSession {
|
|
|
365
416
|
throw new Error(`Codex thread ${id} has no matching repository history.`);
|
|
366
417
|
const turns = thread.turns.filter(object);
|
|
367
418
|
for (const turn of turns) {
|
|
368
|
-
if (!Array.isArray(turn.items) ||
|
|
419
|
+
if (!Array.isArray(turn.items) || !["completed", "failed", "interrupted", "cancelled"].includes(String(turn.status)) || turn.itemsView !== "full")
|
|
369
420
|
throw new Error(`Codex thread ${id} still has unproven execution; no resend. Reconcile its native execution before resuming.`);
|
|
370
421
|
for (const item of turn.items.filter(object)) {
|
|
371
422
|
// A terminal parent turn does not prove that its native executions or children stopped.
|
|
@@ -373,7 +424,8 @@ export class CodexMissionSession {
|
|
|
373
424
|
["commandExecution", "fileChange", "mcpToolCall"].includes(String(item.type)) &&
|
|
374
425
|
!["completed", "failed", ...(item.type === "mcpToolCall" ? [] : ["declined"])].includes(String(item.status)))
|
|
375
426
|
throw new Error(`Codex thread ${id} has an unresolved native execution; no resend. Reconcile its native execution before resuming.`);
|
|
376
|
-
if (item.type !== "dynamicToolCall" ||
|
|
427
|
+
if (item.type !== "dynamicToolCall" || ["completed", "failed"].includes(String(item.status)) &&
|
|
428
|
+
(turn.status === "completed" || item.success === true))
|
|
377
429
|
continue;
|
|
378
430
|
const unique = turns.flatMap(entry => Array.isArray(entry.items) ? entry.items.filter(object) : []).filter(entry => entry.id === item.id).length === 1;
|
|
379
431
|
if (!unique)
|
|
@@ -475,7 +527,7 @@ export class CodexMissionSession {
|
|
|
475
527
|
result = await this.promptTurn(session, "The previous native response ended while existing host tools were still running. Those exact calls have now returned:\n" +
|
|
476
528
|
JSON.stringify(result.deferredToolResults) +
|
|
477
529
|
"\nContinue this same Mission from these results through the remaining validation, delivery, review and root acceptance. " +
|
|
478
|
-
"Do not resend the original request or redispatch the completed Tasks. Preserve failures, ownership and cumulative budget; use existing Mission status for the next action.", undefined, true);
|
|
530
|
+
"Do not resend the original request or redispatch the completed Tasks. Preserve failures, ownership and cumulative budget; use existing Mission status for the next action.", session.agent === "dogs-coordinator" ? onDispatch : undefined, true);
|
|
479
531
|
}
|
|
480
532
|
return result;
|
|
481
533
|
}
|
|
@@ -577,7 +629,7 @@ export class CodexMissionSession {
|
|
|
577
629
|
});
|
|
578
630
|
await this.hooks["tool.execute.after"]?.({ tool: call.tool, sessionID: session.id, callID: call.callId, args }, { output: "", metadata: { sessionId: child.id, status: "running" } });
|
|
579
631
|
const result = await this.prompt(child, String(args.prompt), async (messageID) => {
|
|
580
|
-
await this.
|
|
632
|
+
await this.bindTaskDispatch(session, child, call, messageID);
|
|
581
633
|
dispatched = true;
|
|
582
634
|
});
|
|
583
635
|
text = result.finalResponse ?? "";
|
|
@@ -49,6 +49,7 @@ export interface CodexWorkerDispatch {
|
|
|
49
49
|
clientUserMessageID: string;
|
|
50
50
|
ownerGeneration: string;
|
|
51
51
|
}
|
|
52
|
+
export type CodexCoordinatorDispatch = Omit<CodexWorkerDispatch, "runID" | "unitID">;
|
|
52
53
|
export interface CodexCompletedTaskProof {
|
|
53
54
|
dispatch: CodexWorkerDispatch;
|
|
54
55
|
childTurnID: string;
|
|
@@ -209,6 +210,8 @@ export interface OperatorMission {
|
|
|
209
210
|
codexNotStarted?: CodexNotStartedProof[];
|
|
210
211
|
/** Missing parent receipts reconciled from exact completed native Worker turns. */
|
|
211
212
|
codexCompletedTasks?: CodexCompletedTaskProof[];
|
|
213
|
+
/** Current Coordinator dispatch bound before its exact native turn is sent. */
|
|
214
|
+
codexCoordinatorDispatch?: CodexCoordinatorDispatch;
|
|
212
215
|
version: "0.12";
|
|
213
216
|
id: string;
|
|
214
217
|
root: string;
|
|
@@ -319,6 +322,11 @@ export interface OperatorMission {
|
|
|
319
322
|
admittedAt: number;
|
|
320
323
|
reviewIdentity: string;
|
|
321
324
|
};
|
|
325
|
+
/** Exact terminal of an unused inline grant; no implementation calls followed admission. */
|
|
326
|
+
noWriteReceipt?: {
|
|
327
|
+
promptID: string;
|
|
328
|
+
messageID: string;
|
|
329
|
+
};
|
|
322
330
|
status: "prepared" | "running" | "ready" | "failed" | "cancelled";
|
|
323
331
|
selfRecheck?: MissionSelfRecheck;
|
|
324
332
|
}[];
|
|
@@ -891,7 +891,8 @@ export async function missionAcceptanceSummary(mission, run, operators, observe)
|
|
|
891
891
|
}
|
|
892
892
|
export function missionReviewIndependent(mission, child) {
|
|
893
893
|
return child !== undefined && !mission.sourceAuthors?.includes(child) &&
|
|
894
|
-
!(mission.corrections ?? []).some(correction => correction.author === child
|
|
894
|
+
!(mission.corrections ?? []).some(correction => correction.author === child &&
|
|
895
|
+
!(correction.status === "failed" && correction.noWriteReceipt));
|
|
895
896
|
}
|
|
896
897
|
export function missionPacket(mission, run, includeWorkQuantity = true) {
|
|
897
898
|
const predecessor = run && mission.runID !== run.runID && (mission.supersededRunID === run.runID || run.phase === "cancelled") ? run : undefined;
|
|
@@ -199,6 +199,14 @@ export function reviewerCorrectionValidation(validation, child, history, notBefo
|
|
|
199
199
|
continue;
|
|
200
200
|
}
|
|
201
201
|
previousEnd = attempt.completed;
|
|
202
|
+
// A final-check-only refresh must replace its old binding, not force the
|
|
203
|
+
// unchanged prefix to run again. Repeated declarations stay ambiguous;
|
|
204
|
+
// preserve their existing occurrence rules and validate every saved input.
|
|
205
|
+
if (completed && partial.length === required.length && members.length === 1 &&
|
|
206
|
+
members[0].command === required.at(-1) && required.indexOf(members[0].command) === required.length - 1) {
|
|
207
|
+
partial.splice(0, partial.length, ...completed.slice(0, -1));
|
|
208
|
+
completed = undefined;
|
|
209
|
+
}
|
|
202
210
|
if (members[0].command !== required[partial.length] || partial.length === required.length)
|
|
203
211
|
partial.length = 0;
|
|
204
212
|
failed = undefined;
|
|
@@ -366,7 +374,7 @@ export async function missionDeliveryObservation(directory, runID) {
|
|
|
366
374
|
}
|
|
367
375
|
/** A child ID alone cannot establish the initial phase after a restart or failed dispatch. */
|
|
368
376
|
export function initialMissionReviewPrompt(mission, prompts) {
|
|
369
|
-
return [mission.review?.initialPrompt, ...prompts].find(prompt => typeof prompt === "string" &&
|
|
377
|
+
return [mission.review?.initialPrompt, ...(mission.corrections ?? []).map(item => item.initialPrompt), ...prompts].find(prompt => typeof prompt === "string" &&
|
|
370
378
|
prompt.startsWith(`candidate_id: ${mission.id}\n`) && /^review_phase: initial$/mu.test(prompt) &&
|
|
371
379
|
/^canonical_validation_exit: 0$/mu.test(prompt));
|
|
372
380
|
}
|
|
@@ -377,8 +385,9 @@ export async function completedMissionReviewPrompts(mission, profile, root, requ
|
|
|
377
385
|
return [];
|
|
378
386
|
// The completion hook has already bound this prompt to a real independent Reviewer child.
|
|
379
387
|
// Avoid a second V2 history read when its page/list API is temporarily unavailable.
|
|
380
|
-
|
|
381
|
-
|
|
388
|
+
const initial = initialMissionReviewPrompt(mission, []);
|
|
389
|
+
if (initial)
|
|
390
|
+
return [initial];
|
|
382
391
|
const owner = mission.coordinator ?? root;
|
|
383
392
|
if (mission.coordinator !== null) {
|
|
384
393
|
const coordinator = await host.get(owner);
|
package/dist/plugin/profiled.js
CHANGED
|
@@ -355,6 +355,47 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
355
355
|
return who.role === "dog-reviewer" && who.parent === (mission.coordinator ?? root);
|
|
356
356
|
}
|
|
357
357
|
async function restoreReviewAuthorship(root, mission, id) {
|
|
358
|
+
// An inline correction admission can end without any implementation: the
|
|
359
|
+
// controller may be the designated writer. Recover that exact native return
|
|
360
|
+
// rather than permanently treating the unused grant as source authorship.
|
|
361
|
+
const unused = mission.sourceAuthors?.includes(id) ? [] : (mission.corrections ?? []).filter(item => item.author === id && item.inlineReview && item.status === "failed" && !item.noWriteReceipt);
|
|
362
|
+
if (unused.length) {
|
|
363
|
+
const history = await reviewMessages(id);
|
|
364
|
+
const receipts = unused.flatMap(correction => {
|
|
365
|
+
const inline = correction.inlineReview;
|
|
366
|
+
const prompt = history.findIndex(message => record(message.info) && message.info.id === inline.promptID &&
|
|
367
|
+
message.info.role === "user" && message.info.sessionID === id);
|
|
368
|
+
if (prompt < 0)
|
|
369
|
+
return [];
|
|
370
|
+
const response = reviewResponseMessages(history, prompt);
|
|
371
|
+
const last = [...response].reverse().find(message => record(message.info) && message.info.role === "assistant");
|
|
372
|
+
const info = record(last?.info) ? last.info : undefined;
|
|
373
|
+
if (!info || info.sessionID !== id || info.finish !== "stop" || info.error || typeof info.id !== "string" ||
|
|
374
|
+
!record(info.time) || typeof info.time.completed !== "number" || info.time.completed < inline.admittedAt)
|
|
375
|
+
return [];
|
|
376
|
+
const parts = response.flatMap(message => Array.isArray(message.parts) ? message.parts.filter(record) : []);
|
|
377
|
+
const admitted = parts.findIndex(part => part.type === "tool" && part.tool === repairReview && record(part.state) &&
|
|
378
|
+
part.state.status === "completed" && record(part.state.time) && typeof part.state.time.end === "number" &&
|
|
379
|
+
part.state.time.end >= inline.admittedAt);
|
|
380
|
+
// Before admission this Reviewer was read-only. After it, require the
|
|
381
|
+
// observed terminal and only read/search calls; unknown tools or failed
|
|
382
|
+
// writes cannot establish that no implementation occurred.
|
|
383
|
+
if (admitted < 0 || parts.slice(admitted + 1).some(part => part.type === "tool" &&
|
|
384
|
+
(!["read", "grep", "glob"].includes(String(part.tool)) || !record(part.state) ||
|
|
385
|
+
!["completed", "error"].includes(String(part.state.status)))))
|
|
386
|
+
return [];
|
|
387
|
+
return [{ runID: correction.runID, promptID: inline.promptID, messageID: info.id }];
|
|
388
|
+
});
|
|
389
|
+
if (receipts.length)
|
|
390
|
+
mission = await missions.update(root, current => {
|
|
391
|
+
for (const receipt of receipts) {
|
|
392
|
+
const correction = current.corrections?.find(item => item.runID === receipt.runID && item.author === id &&
|
|
393
|
+
item.status === "failed" && item.inlineReview?.promptID === receipt.promptID);
|
|
394
|
+
if (correction)
|
|
395
|
+
correction.noWriteReceipt = { promptID: receipt.promptID, messageID: receipt.messageID };
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
}
|
|
358
399
|
if (!missionReviewIndependent(mission, id) || !mission.attempts?.some(attempt => attempt.childSessionID === id))
|
|
359
400
|
return mission;
|
|
360
401
|
const history = await reviewMessages(id);
|
|
@@ -1187,6 +1228,9 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1187
1228
|
return { ...packet, next_action: "Fast-lane: dispatch the exact Reviewer Task from review_mission if not yet active; otherwise wait for that Reviewer. Do not start a Coordinator or another Worker while review is pending." };
|
|
1188
1229
|
}
|
|
1189
1230
|
if (mission.runID === run?.runID && run?.units.some(unit => unit.status === "running")) {
|
|
1231
|
+
if (mission.coordinator && !mission.dispatchOpen && !["completed", "cancelled"].includes(mission.phase))
|
|
1232
|
+
return { ...packet, task: missions.task(mission),
|
|
1233
|
+
next_action: "Resume this existing Coordinator Task with its task_id to continue the retained unit. Do not dispatch a replacement or wait for background work that has already ended." };
|
|
1190
1234
|
return { ...packet, next_action: "The current unit is active. Continue its owning session; do not dispatch a replacement Worker or Coordinator. Native background completion will return to the parent." };
|
|
1191
1235
|
}
|
|
1192
1236
|
if (mission.coordinator === null && mission.runID === run?.runID && !mission.dispatchOpen &&
|
|
@@ -2834,7 +2878,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2834
2878
|
}
|
|
2835
2879
|
async function declareMissionUnits(root, actor, mission, raw, reason, execution, planningCallID, handoffNotes, workQuantities) {
|
|
2836
2880
|
await control.currentBudget(root);
|
|
2837
|
-
mission = await missions.required(root);
|
|
2881
|
+
mission = actor === root ? await reconcileMissionDispatch(root) ?? await missions.required(root) : await missions.required(root);
|
|
2838
2882
|
let previous = await operators.read(root);
|
|
2839
2883
|
if (sourceReconciliationRequired(mission, previous))
|
|
2840
2884
|
return JSON.stringify({ ...missionDispatchPacket(mission, previous),
|
|
@@ -2849,8 +2893,34 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2849
2893
|
Array.isArray(execution.commands) && execution.commands.length === 0);
|
|
2850
2894
|
const plan = missionPlan(mission, raw, input.directory);
|
|
2851
2895
|
assertMissionWritePaths(mission, plan.units.flatMap(unit => unit.write));
|
|
2852
|
-
if (actor === root && (mission.coordinator !== null || plan.units.length !== 1))
|
|
2853
|
-
|
|
2896
|
+
if (actor === root && (mission.coordinator !== null || plan.units.length !== 1)) {
|
|
2897
|
+
// A submitted Coordinator still owns corrective planning. Return its actual
|
|
2898
|
+
// continuation instead of referring to a Task that the rejection never supplied.
|
|
2899
|
+
// This is routing advice only: no replacement plan, reservation or admission.
|
|
2900
|
+
// Routing below alone chooses whether to offer a Task. A resumable parent
|
|
2901
|
+
// packet can already contain one even while its Reviewer is still pending.
|
|
2902
|
+
const { task: _dispatchTask, ...packet } = missionDispatchPacket(mission, previous);
|
|
2903
|
+
const reviewPending = mission.runID === previous?.runID && mission.review?.verdict === "pending";
|
|
2904
|
+
const active = mission.dispatchOpen || reviewPending || mission.runID === previous?.runID &&
|
|
2905
|
+
previous?.units.some(unit => unit.status === "running");
|
|
2906
|
+
const continuation = !active ? missions.task(mission) : undefined;
|
|
2907
|
+
// Existing Coordinator resumes accept a concrete prompt. Do not use the opaque
|
|
2908
|
+
// initial reference here: claim() would expand it from unchanged Mission state
|
|
2909
|
+
// and lose the unadmitted correction that prompted this continuation.
|
|
2910
|
+
const task = continuation && mission.coordinator !== null ? { ...continuation,
|
|
2911
|
+
prompt: `Continue the same Mission ${mission.id} in this existing Coordinator session, in the user's language. ` +
|
|
2912
|
+
"Retain the saved original requests, requirements, candidate, checks and cumulative budget.\n" +
|
|
2913
|
+
"Proposed correction from Operator root (not admitted; preserve requirements, candidate and cumulative budget):\n" +
|
|
2914
|
+
JSON.stringify({ units: raw, reason, execution, handoff_context: handoffNotes, work_quantities: workQuantities }) } : continuation;
|
|
2915
|
+
return JSON.stringify({ ...packet,
|
|
2916
|
+
status: active ? "mission-coordinator-active" : "mission-coordinator-required",
|
|
2917
|
+
...(task ? { task } : {}),
|
|
2918
|
+
next_action: reviewPending
|
|
2919
|
+
? "Dispatch the exact Reviewer Task from review_mission if not yet active; otherwise wait for that Reviewer. Do not start a Coordinator or another Worker while review is pending. The proposed plan has not been admitted."
|
|
2920
|
+
: active
|
|
2921
|
+
? "Continue the active owning session or wait for its native completion; do not dispatch a duplicate Coordinator or Worker. The proposed plan has not been admitted."
|
|
2922
|
+
: "Dispatch this exact Task to continue the same Mission and Coordinator session with the concrete correction and retained checks. The proposed plan has not been admitted; keep requirements, candidate and cumulative budget unchanged." });
|
|
2923
|
+
}
|
|
2854
2924
|
const same = previous?.planHash === createHash("sha256").update(JSON.stringify(plan)).digest("hex");
|
|
2855
2925
|
const replanning = previous && !["completed", "cancelled"].includes(previous.phase) && !same;
|
|
2856
2926
|
const activeDirect = previous?.units.find(unit => unit.status === "running" && unit.directExecution?.actor === actor);
|
|
@@ -3034,7 +3104,10 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
3034
3104
|
if (args.executor === "worker" && args.units === undefined)
|
|
3035
3105
|
return handoffDirect(root, context.sessionID, context.callID, args.handoff_context);
|
|
3036
3106
|
const planned = await declareMissionUnits(root, context.sessionID, mission, args.units, args.reason, args.execution, context.callID, args.handoff_context, args.work_quantities);
|
|
3037
|
-
|
|
3107
|
+
const task = JSON.parse(planned).task;
|
|
3108
|
+
// A Coordinator continuation is not a newly prepared direct unit.
|
|
3109
|
+
return args.executor === "self" && record(task) && task.subagent_type !== profileAgent(profile, "dog-operator")
|
|
3110
|
+
? startDirect(root, context.sessionID) : planned;
|
|
3038
3111
|
});
|
|
3039
3112
|
}
|
|
3040
3113
|
catch (error) {
|
|
@@ -3178,7 +3251,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
3178
3251
|
current.verdict = "findings";
|
|
3179
3252
|
current.result = findings;
|
|
3180
3253
|
// The independent investigation is recorded by this real tool call, not a fictitious terminal.
|
|
3181
|
-
current.initialPrompt = current.task.prompt;
|
|
3254
|
+
current.initialPrompt = initialMissionReviewPrompt(item, [current.task.prompt]);
|
|
3182
3255
|
});
|
|
3183
3256
|
review = mission.review;
|
|
3184
3257
|
}
|
|
@@ -3375,7 +3448,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
3375
3448
|
// turn. Generate verification only when a completed initial review is recoverable;
|
|
3376
3449
|
// otherwise generate an admissible initial review instead of trapping the Coordinator.
|
|
3377
3450
|
const prior = mission.review?.task?.prompt;
|
|
3378
|
-
const completed = risk.length > 0 && prior && mission
|
|
3451
|
+
const completed = risk.length > 0 && prior && !initialMissionReviewPrompt(mission, [])
|
|
3379
3452
|
? await completedMissionReviewPrompts(mission, profile, root, prior, {
|
|
3380
3453
|
get: async (id) => payload(await session("get", { path: { id }, query: { directory: input.directory } })),
|
|
3381
3454
|
messages: reviewMessages,
|
|
@@ -18,6 +18,8 @@ export declare const MISSION_REFLECTION_WORKFLOW = "When bounded process reflect
|
|
|
18
18
|
export declare function missionOperatorContent(profile: RuntimeProfile, version: string): string;
|
|
19
19
|
/** Keep representation oracles consistent in direct execution, Worker and Review. */
|
|
20
20
|
export declare const MISSION_REPRESENTATION_ORACLE = "Same-type representation, not name/visitor analogy; resolve conflicts.";
|
|
21
|
+
/** Planning and Review use public type families instead of only issue-named examples. */
|
|
22
|
+
export declare const MISSION_TYPE_FAMILY_ORACLE = "When changing a dispatch/exclusion set, derive the affected same-representation family from an existing\nschema/registry and its public callers, not just issue examples. Compare sibling entries under that\ncontract; reuse suitable parameterized checks. Do not widen unrelated families or require an exhaustive\nmatrix, another unit or review lane.";
|
|
21
23
|
/** Coordinator preserves source-backed return semantics in direct work or a Worker's objective. */
|
|
22
24
|
export declare const MISSION_RETURN_CONTRACT = "For a changed value-producing operation, derive its return contract from public callers and unchanged source/tests.\nPreserve established return type/container, metadata and label alignment unless the original request changes them;\nequal numeric values alone do not prove that contract. Trace which inputs determine result shape and labels,\nincluding non-primary parameters; a scalar primary input need not yield a scalar result. For a mask or conditional\nreplacement, preserve established broadcasting and missing-value propagation; an unknown condition is not proof\nthat replacement is intended. Carry the affected contract into direct work or the Worker's objective.\nReuse an adequate focused assertion; add only the smallest source-backed regression when needed, not an input matrix,\nanother unit, validation lane or review.";
|
|
23
25
|
/** Coordinator preserves source-backed mutation semantics in direct work or a Worker's objective. */
|
|
@@ -25,7 +27,7 @@ export declare const MISSION_MUTATION_CONTRACT = "For a changed mutating operati
|
|
|
25
27
|
/** Coordinator authors and plans regressions without adding another validation/review lane. */
|
|
26
28
|
export declare const MISSION_REGRESSION_PLACEMENT = "Prefer an existing relevant test suite/subtest or fixture when it can express the regression assertion.\nIf a new test module is needed, prefer a distinctive behavior-specific name over automatically mirroring the implementation module.\nPreserve established assertions and project test discovery. This is placement guidance, not another test, unit or review requirement.";
|
|
27
29
|
/** Shared by the installed Reviewer and its host-generated mission prompt. */
|
|
28
|
-
export declare const MISSION_BEHAVIOR_REVIEW = "Establish the test oracle independently of the patch: tests added with the implementation are claims to\nreview, not established API behavior. For a changed failure path, compare a pre-existing analogous public\ntest and its shared assertion helper, including default expected outputs, with the new case. A new test\nthat asserts the implementation's current result can encode the defect rather than catch it. Preserve\nthe pre-change contract unless the request changes it; do not invent a universal failure-result convention.\nFor changed observable behavior, inspect affected public caller assertions/output snapshots found by search, not only implementation-local fixtures.\nReconcile expected outputs with the original requirements and reuse adequate checks; no extra review round.\nFor requested side-effect changes, check remaining controls with existing client-owned state, not only isolated defaults.\nJudge allowed effects from the original request; preserve authorized opt-in behavior.\nSame-type representation, not name/visitor analogy; resolve conflicts.\nTrace a concrete rejected input through the changed code back to the public caller, checking result,\nerror and observable state together, including earlier results that can survive failure. Missing assertions\nalone are not defects; a concrete contradiction with the established contract is a finding even if tests pass.\nDuring correction, reuse the established public test harness where applicable and exercise the smallest\nregression exposing the defect before the fix and passing afterward. Do not change expected values or\nhelper defaults merely to agree with the implementation; derive them from the original contract.\nPrefer existing suites/subtests for regressions. New test entry/helper names should be distinctive\nand compose with other same-package test files, not create generic package-level collisions.\n\nFor a requested per-call mode/option, trace where the setting is chosen and where changed code uses\nretained objects or closures. Distinguish the current caller's setting from a captured creation-time\nsetting; use the requested contract to decide which governs. If actual source crosses that boundary\nand existing tests do not cover it, exercise its smallest public case, including the disabled behavior.\nDo not invent a lifecycle matrix or infer that an opt-in feature is correct from only its enabled path.\n\nFor a changed failure handler, inspect the operation it calls and the public inputs reaching it,\nincluding failures not listed in the new handler. Use the supplied source/tests and established API behavior\nto identify a concrete input that could still violate the requested contract. A passing normal input does\nnot settle a different failure outcome of that same operation. A demonstrable material defect is FINDINGS; ask for\nan excerpt or result only when a specific material outcome cannot be settled. Do not invent new behavior,\nrequire an exhaustive exception inventory, or recommend catching every exception.\n\nReport FINDINGS only for concrete major or medium defects with a material impact on the original requirements,\npublic behavior, correctness or required validation. Name the consequence and smallest necessary fix.\nDo not turn minor style, wording, optional improvements or speculative edge cases into FINDINGS or EVIDENCE_GAPS.\nUse read/search to settle missing context in the current review. If a consequential uncertainty remains,\nrecord EVIDENCE_GAPS as an advisory limitation, not a demand for another evidence packet. Missing narration,\nrequirement mappings, hashes or clipped excerpts alone never justify a blocking finding.\n\nAssess behavioral requirements against actual source, tests and observed results. A required check known to\nhave failed or not run is a concrete finding; missing documentation of a check is not proof it did not run.\nFor incidental workflow constraints such as cache settings or command-path spelling, use existing host observations;\nabsence of a separate settings dump or historical log is not itself an evidence gap. Flag observed material\ncontradictions. The Operator owns final comparison with the original request. If a missing check genuinely\naffects correctness or a requested deliverable, name that consequence and the smallest useful next check.\nOn verification, compare the correction and its affected public outcomes with the original contract, not\nonly the wording of previous findings. Reuse unchanged evidence; do not expand into optional improvements\nor an exhaustive input matrix. PASS means no material finding, not exhaustive proof of every path.";
|
|
30
|
+
export declare const MISSION_BEHAVIOR_REVIEW = "Establish the test oracle independently of the patch: tests added with the implementation are claims to\nreview, not established API behavior. For a changed failure path, compare a pre-existing analogous public\ntest and its shared assertion helper, including default expected outputs, with the new case. A new test\nthat asserts the implementation's current result can encode the defect rather than catch it. Preserve\nthe pre-change contract unless the request changes it; do not invent a universal failure-result convention.\nFor changed observable behavior, inspect affected public caller assertions/output snapshots found by search, not only implementation-local fixtures.\nReconcile expected outputs with the original requirements and reuse adequate checks; no extra review round.\nFor requested side-effect changes, check remaining controls with existing client-owned state, not only isolated defaults.\nJudge allowed effects from the original request; preserve authorized opt-in behavior.\nSame-type representation, not name/visitor analogy; resolve conflicts.\nWhen changing a dispatch/exclusion set, derive the affected same-representation family from an existing\nschema/registry and its public callers, not just issue examples. Compare sibling entries under that\ncontract; reuse suitable parameterized checks. Do not widen unrelated families or require an exhaustive\nmatrix, another unit or review lane.\nTrace a concrete rejected input through the changed code back to the public caller, checking result,\nerror and observable state together, including earlier results that can survive failure. Missing assertions\nalone are not defects; a concrete contradiction with the established contract is a finding even if tests pass.\nDuring correction, reuse the established public test harness where applicable and exercise the smallest\nregression exposing the defect before the fix and passing afterward. Do not change expected values or\nhelper defaults merely to agree with the implementation; derive them from the original contract.\nPrefer existing suites/subtests for regressions. New test entry/helper names should be distinctive\nand compose with other same-package test files, not create generic package-level collisions.\n\nFor a requested per-call mode/option, trace where the setting is chosen and where changed code uses\nretained objects or closures. Distinguish the current caller's setting from a captured creation-time\nsetting; use the requested contract to decide which governs. If actual source crosses that boundary\nand existing tests do not cover it, exercise its smallest public case, including the disabled behavior.\nDo not invent a lifecycle matrix or infer that an opt-in feature is correct from only its enabled path.\n\nFor a changed failure handler, inspect the operation it calls and the public inputs reaching it,\nincluding failures not listed in the new handler. Use the supplied source/tests and established API behavior\nto identify a concrete input that could still violate the requested contract. A passing normal input does\nnot settle a different failure outcome of that same operation. A demonstrable material defect is FINDINGS; ask for\nan excerpt or result only when a specific material outcome cannot be settled. Do not invent new behavior,\nrequire an exhaustive exception inventory, or recommend catching every exception.\n\nReport FINDINGS only for concrete major or medium defects with a material impact on the original requirements,\npublic behavior, correctness or required validation. Name the consequence and smallest necessary fix.\nDo not turn minor style, wording, optional improvements or speculative edge cases into FINDINGS or EVIDENCE_GAPS.\nUse read/search to settle missing context in the current review. If a consequential uncertainty remains,\nrecord EVIDENCE_GAPS as an advisory limitation, not a demand for another evidence packet. Missing narration,\nrequirement mappings, hashes or clipped excerpts alone never justify a blocking finding.\n\nAssess behavioral requirements against actual source, tests and observed results. A required check known to\nhave failed or not run is a concrete finding; missing documentation of a check is not proof it did not run.\nFor incidental workflow constraints such as cache settings or command-path spelling, use existing host observations;\nabsence of a separate settings dump or historical log is not itself an evidence gap. Flag observed material\ncontradictions. The Operator owns final comparison with the original request. If a missing check genuinely\naffects correctness or a requested deliverable, name that consequence and the smallest useful next check.\nOn verification, compare the correction and its affected public outcomes with the original contract, not\nonly the wording of previous findings. Reuse unchanged evidence; do not expand into optional improvements\nor an exhaustive input matrix. PASS means no material finding, not exhaustive proof of every path.";
|
|
29
31
|
/** Mission Reviewer uses ordinary host read/search permissions, not a supplied-packet-only protocol. */
|
|
30
32
|
export declare function missionReviewerContent(profile: RuntimeProfile): string;
|
|
31
33
|
export declare function missionCoordinatorContent(profile: RuntimeProfile, version: string): string;
|
|
@@ -284,6 +284,11 @@ existing user authorization and project gates; npm publication remains manual.
|
|
|
284
284
|
}
|
|
285
285
|
/** Keep representation oracles consistent in direct execution, Worker and Review. */
|
|
286
286
|
export const MISSION_REPRESENTATION_ORACLE = `Same-type representation, not name/visitor analogy; resolve conflicts.`;
|
|
287
|
+
/** Planning and Review use public type families instead of only issue-named examples. */
|
|
288
|
+
export const MISSION_TYPE_FAMILY_ORACLE = `When changing a dispatch/exclusion set, derive the affected same-representation family from an existing
|
|
289
|
+
schema/registry and its public callers, not just issue examples. Compare sibling entries under that
|
|
290
|
+
contract; reuse suitable parameterized checks. Do not widen unrelated families or require an exhaustive
|
|
291
|
+
matrix, another unit or review lane.`;
|
|
287
292
|
/** Coordinator preserves source-backed return semantics in direct work or a Worker's objective. */
|
|
288
293
|
export const MISSION_RETURN_CONTRACT = `For a changed value-producing operation, derive its return contract from public callers and unchanged source/tests.
|
|
289
294
|
Preserve established return type/container, metadata and label alignment unless the original request changes them;
|
|
@@ -319,6 +324,7 @@ For changed observable behavior, inspect affected public caller assertions/outpu
|
|
|
319
324
|
Reconcile expected outputs with the original requirements and reuse adequate checks; no extra review round.
|
|
320
325
|
${MISSION_CLIENT_STATE_CHECK}
|
|
321
326
|
${MISSION_REPRESENTATION_ORACLE}
|
|
327
|
+
${MISSION_TYPE_FAMILY_ORACLE}
|
|
322
328
|
Trace a concrete rejected input through the changed code back to the public caller, checking result,
|
|
323
329
|
error and observable state together, including earlier results that can survive failure. Missing assertions
|
|
324
330
|
alone are not defects; a concrete contradiction with the established contract is a finding even if tests pass.
|
|
@@ -540,6 +546,7 @@ If peer source/tests expose a plausible related still-unhandled error, probe its
|
|
|
540
546
|
before choosing the fix; reuse adequate checks. Include this in the current author's objective/check
|
|
541
547
|
plan, not another unit or review round. Do not invent an exhaustive error matrix.
|
|
542
548
|
${MISSION_REPRESENTATION_ORACLE}
|
|
549
|
+
${MISSION_TYPE_FAMILY_ORACLE}
|
|
543
550
|
${MISSION_RETURN_CONTRACT}
|
|
544
551
|
${MISSION_MUTATION_CONTRACT}
|
|
545
552
|
${MISSION_REGRESSION_PLACEMENT}
|