sortie-dogs 0.13.13 → 0.13.15
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/asset-version.d.ts +1 -1
- package/dist/asset-version.js +1 -1
- package/dist/plugin/gate.d.ts +1 -1
- package/dist/plugin/gate.js +9 -1
- package/dist/plugin/index.js +9 -3
- package/dist/plugin/mission-review.js +3 -2
- package/dist/plugin/profiled.js +88 -38
- package/dist/plugin/v2.js +8 -3
- package/dist/runtime-mission-assets.d.ts +5 -1
- package/dist/runtime-mission-assets.js +38 -8
- 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.13.
|
|
23
|
-
· [Release notes](docs/release-v0.13.
|
|
22
|
+
**Current release: [v0.13.15](https://github.com/zufall-upon/Sortie-dogs/releases/tag/v0.13.15)**
|
|
23
|
+
· [Release notes](docs/release-v0.13.15.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.13.
|
|
60
|
+
npm install --save-dev sortie-dogs@0.13.15
|
|
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.13.
|
|
89
|
+
npm install --save-dev sortie-dogs@0.13.15
|
|
90
90
|
npx --no-install sortie-dogs init .
|
|
91
91
|
```
|
|
92
92
|
|
|
@@ -188,7 +188,7 @@ known expense. Official local evaluation and leaderboard acceptance are separate
|
|
|
188
188
|
**8/23 (34.8%)**, versus v0.12.25's 7/23; all seven prior resolutions retained, no empty patches or
|
|
189
189
|
official evaluation errors. [Fixed conditions, stopped-run accounting and costs](docs/benchmarks/swebench-lite-history.md#v0131-dev23-2026-09-30).
|
|
190
190
|
|
|
191
|
-
All scores belong to their fixed candidates, **not v0.13.
|
|
191
|
+
All scores belong to their fixed candidates, **not v0.13.15**. SWE-bench remains an optional
|
|
192
192
|
measurement, not a release gate. Different budgets, models and conditions are not controlled comparisons.
|
|
193
193
|
|
|
194
194
|
## Configuration
|
|
@@ -211,7 +211,7 @@ Install the desired package version and rerun **your host's** initializer:
|
|
|
211
211
|
|
|
212
212
|
An OpenCode config-local bridge may resolve a separate package; npm-global update alone does not
|
|
213
213
|
update it. [Global/update instructions](docs/configuration.md#global-availability).
|
|
214
|
-
The current Mission asset marker is `0.13.
|
|
214
|
+
The current Mission asset marker is `0.13.15-native-identity-v1`; the unchanged Codex skill marker is
|
|
215
215
|
`0.13.11-codex-skill-v2`. Installed markers alone do not prove a running host reloaded the new version.
|
|
216
216
|
|
|
217
217
|
There is no supported uninstall command. Remove the dependency and only known Sortie-owned paths;
|
|
@@ -227,7 +227,7 @@ follow the [manual removal guide](docs/uninstall.md), never delete the entire `.
|
|
|
227
227
|
[SWE-bench history](docs/benchmarks/swebench-lite-history.md) · [Historical local case study](docs/benchmark-reference.md).
|
|
228
228
|
- **Development:** [Testing](docs/testing.md) · [CLI testing](docs/cli-testing.md) ·
|
|
229
229
|
[Windows tests](docs/windows-tests.md) · [Release routine](docs/release-batch.md).
|
|
230
|
-
- **Releases:** [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) ·
|
|
230
|
+
- **Releases:** [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) ·
|
|
231
231
|
[v0.13.9](docs/release-v0.13.9.md) · [All GitHub releases](https://github.com/zufall-upon/Sortie-dogs/releases).
|
|
232
232
|
|
|
233
233
|
## 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.13.
|
|
6
|
+
export declare const V010_RUNTIME_ASSET_VERSION = "0.13.15-native-identity-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.13.
|
|
6
|
+
export const V010_RUNTIME_ASSET_VERSION = "0.13.15-native-identity-v1";
|
|
7
7
|
export const CODEX_SKILL_ASSET_VERSION = "0.13.11-codex-skill-v2";
|
package/dist/plugin/gate.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export declare function bootstrapWritePaths(tool: string, args: unknown): readon
|
|
|
62
62
|
export declare function isGitMutation(tool: string, args: unknown): boolean;
|
|
63
63
|
export declare function isRemoteMutation(tool: string, args: unknown): boolean;
|
|
64
64
|
/**
|
|
65
|
-
* Quoted segments keep their contents;
|
|
65
|
+
* Quoted segments and backslash escapes keep their contents; unquoted whitespace runs collapse so the
|
|
66
66
|
* same command written with different spacing compares equal.
|
|
67
67
|
*/
|
|
68
68
|
export declare function normalizeCommand(command: string): string;
|
package/dist/plugin/gate.js
CHANGED
|
@@ -858,14 +858,22 @@ export function isRemoteMutation(tool, args) {
|
|
|
858
858
|
return extractWritePaths(tool, args).remoteMutation === true;
|
|
859
859
|
}
|
|
860
860
|
/**
|
|
861
|
-
* Quoted segments keep their contents;
|
|
861
|
+
* Quoted segments and backslash escapes keep their contents; unquoted whitespace runs collapse so the
|
|
862
862
|
* same command written with different spacing compares equal.
|
|
863
863
|
*/
|
|
864
864
|
export function normalizeCommand(command) {
|
|
865
865
|
let quote;
|
|
866
|
+
let escaped = false;
|
|
866
867
|
let whitespace = false;
|
|
867
868
|
let normalized = "";
|
|
868
869
|
for (const character of command.trim()) {
|
|
870
|
+
if (escaped) {
|
|
871
|
+
normalized += character;
|
|
872
|
+
escaped = false;
|
|
873
|
+
continue;
|
|
874
|
+
}
|
|
875
|
+
if (character === "\\" && quote !== "'")
|
|
876
|
+
escaped = true;
|
|
869
877
|
if (quote !== undefined) {
|
|
870
878
|
normalized += character;
|
|
871
879
|
if (character === quote)
|
package/dist/plugin/index.js
CHANGED
|
@@ -8306,6 +8306,8 @@ export const SortieDogsPlugin = async (input, options) => {
|
|
|
8306
8306
|
const direct = await input.runtimeBridge?.directMissionExecution?.(actor);
|
|
8307
8307
|
if (!direct || direct.root !== root)
|
|
8308
8308
|
throw new Error("mission-direct-grant-stale");
|
|
8309
|
+
if (activeSessions.get(actor)?.inFlightCalls.size)
|
|
8310
|
+
throw new Error("mission-direct-tools-running");
|
|
8309
8311
|
// Cold terminal recovery can happen before the actor's next tool/context hook.
|
|
8310
8312
|
if (!goalReservations.has(direct.callID)) {
|
|
8311
8313
|
const snapshot = await (await goalLedger(root)).readGoal();
|
|
@@ -8317,9 +8319,13 @@ export const SortieDogsPlugin = async (input, options) => {
|
|
|
8317
8319
|
else
|
|
8318
8320
|
throw new Error("mission-direct-reservation-unavailable");
|
|
8319
8321
|
}
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8322
|
+
// Empty successful evidence forces a failed disposition. Reuse the saved
|
|
8323
|
+
// validation observation (including a cold recovered exit) without claiming
|
|
8324
|
+
// a failed native child terminal for this still-active controller.
|
|
8325
|
+
await settleGoalDispatch(direct.callID, {
|
|
8326
|
+
output: "Direct unit stopped incomplete; no successful validation or Mission acceptance.",
|
|
8327
|
+
metadata: { sessionId: actor }
|
|
8328
|
+
}, undefined, []);
|
|
8323
8329
|
await releaseWriteGate(actor);
|
|
8324
8330
|
releaseSessionEnforcement(actor);
|
|
8325
8331
|
},
|
|
@@ -73,7 +73,8 @@ export function observedMissionValidation(validation, childSessionID, history, n
|
|
|
73
73
|
!record(part.state) || !["completed", "error"].includes(String(part.state.status)) || !record(part.state.input) ||
|
|
74
74
|
typeof part.state.input.command !== "string")
|
|
75
75
|
return [];
|
|
76
|
-
|
|
76
|
+
// Match raw input first: whitespace normalization destroys Python heredoc boundaries.
|
|
77
|
+
const command = part.state.input.command;
|
|
77
78
|
const exit = record(part.state.metadata) ? part.state.metadata.exit : undefined;
|
|
78
79
|
const started = record(part.time) ? time(part.time.ran) : record(part.state.time) ? time(part.state.time.start) : null;
|
|
79
80
|
const completed = record(part.time) ? time(part.time.completed) : record(part.state.time) ? time(part.state.time.end) : null;
|
|
@@ -99,7 +100,7 @@ export function observedMissionValidation(validation, childSessionID, history, n
|
|
|
99
100
|
occurrence = (occurrence + 1) % declared.length;
|
|
100
101
|
}
|
|
101
102
|
const { directory: actual, ...visible } = attempt;
|
|
102
|
-
return [{ ...visible, ...(directory && resolve(directory, actual ?? ".") !== resolve(directory)
|
|
103
|
+
return [{ ...visible, command: members.join(" && "), ...(directory && resolve(directory, actual ?? ".") !== resolve(directory)
|
|
103
104
|
? { directory: resolve(directory, actual ?? ".") } : {}), ...(members.length > 1 ? { observed_members: members } : {}) }];
|
|
104
105
|
});
|
|
105
106
|
// Retain early attempts and the latest checks if a Worker retried many times.
|
package/dist/plugin/profiled.js
CHANGED
|
@@ -266,17 +266,21 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
266
266
|
async function identity(id) {
|
|
267
267
|
const info = payload(await session("get", { path: { id }, query: { directory: input.directory } }));
|
|
268
268
|
const parent = record(info) && typeof info.parentID === "string" ? info.parentID : undefined;
|
|
269
|
-
|
|
269
|
+
// Native session identity survives reload; a completion's metadata.agent is its
|
|
270
|
+
// child author, not a selection of the receiving session's agent.
|
|
271
|
+
let agent = selected.get(id) ?? (record(info) && typeof info.agent === "string" ? info.agent : undefined);
|
|
270
272
|
if (agent === undefined) {
|
|
271
273
|
const history = await messages(id);
|
|
272
274
|
for (const message of [...history].reverse()) {
|
|
275
|
+
if (Array.isArray(message.parts) && message.parts.length > 0 &&
|
|
276
|
+
message.parts.every(part => record(part) && part.synthetic === true))
|
|
277
|
+
continue;
|
|
273
278
|
const metadata = record(message.info) ? message.info : message;
|
|
274
279
|
if (metadata.role === "user" && typeof metadata.agent === "string") {
|
|
275
280
|
agent = metadata.agent;
|
|
276
281
|
break;
|
|
277
282
|
}
|
|
278
283
|
}
|
|
279
|
-
agent ??= record(info) && typeof info.agent === "string" ? info.agent : undefined;
|
|
280
284
|
}
|
|
281
285
|
return { role: canonicalAgent(profile, agent), ...(parent === undefined ? {} : { parent }) };
|
|
282
286
|
}
|
|
@@ -1001,6 +1005,14 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1001
1005
|
const detail = "Operation result: execution-failed (result accepted; process did not succeed).";
|
|
1002
1006
|
return text.includes(detail) ? text : text.replace(/^((?:[ \t]*\r?\n)*[^\r\n]+)/u, `$1 ${detail}`);
|
|
1003
1007
|
}
|
|
1008
|
+
function compactMissionEvidence(packet, run, root) {
|
|
1009
|
+
if (run && run.runID === packet.run_id && Array.isArray(packet.units)) {
|
|
1010
|
+
const validation = missionReviewValidation(run, operators.statePath(root));
|
|
1011
|
+
packet.units = packet.units.map((unit, index) => ({ ...unit, evidence: validation[index].evidence,
|
|
1012
|
+
evidence_details_ref: validation[index].details_ref }));
|
|
1013
|
+
}
|
|
1014
|
+
return packet;
|
|
1015
|
+
}
|
|
1004
1016
|
function missionDispatchPacket(mission, run) {
|
|
1005
1017
|
const packet = { ...missionPacket(mission, run), project_root: input.directory,
|
|
1006
1018
|
coordinator_dispatch: mission.dispatchOpen ? "active" : ["completed", "cancelled"].includes(mission.phase) ? "terminal" : "resumable" };
|
|
@@ -1512,12 +1524,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1512
1524
|
}
|
|
1513
1525
|
if (view === "progress")
|
|
1514
1526
|
return JSON.stringify(missionProgress(mission, run, budget, packet));
|
|
1515
|
-
|
|
1516
|
-
const validation = missionReviewValidation(run, operators.statePath(root));
|
|
1517
|
-
packet.units = packet.units.map((unit, index) => ({ ...unit, evidence: validation[index].evidence,
|
|
1518
|
-
evidence_details_ref: validation[index].details_ref }));
|
|
1519
|
-
}
|
|
1520
|
-
return JSON.stringify(packet);
|
|
1527
|
+
return JSON.stringify(view === "full" ? packet : compactMissionEvidence(packet, run, root));
|
|
1521
1528
|
}
|
|
1522
1529
|
if (root && context.sessionID !== root) {
|
|
1523
1530
|
const owned = await operators.read(root);
|
|
@@ -2026,8 +2033,12 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2026
2033
|
return JSON.stringify({ status: "correction-validated",
|
|
2027
2034
|
execution: "same-native-task", validation: direct.unit.unit.validation,
|
|
2028
2035
|
next_action: 'Compare the original requirements, retained findings and affected public behavior in this same context, then finish THIS native Task with SELF_RECHECKED and self_recheck: {"candidate":"current-validated","unresolved_findings":[],"residual_major":null}. No handoff reread, second Task or Operator round trip. This is author self-recheck; only the actual successful native terminal can bind it, never this tool result.' });
|
|
2029
|
-
|
|
2030
|
-
|
|
2036
|
+
const run = await operators.required(root);
|
|
2037
|
+
// Full protected path arrays can make V2 truncate this one-line JSON to zero lines,
|
|
2038
|
+
// hiding both the successful transition and the next action. Keep measured evidence
|
|
2039
|
+
// and durable detail references, as default status already does; never rewrite proof.
|
|
2040
|
+
return JSON.stringify({ ...compactMissionEvidence(missionPacket(await missions.required(root), run), run, root),
|
|
2041
|
+
next_action: `This direct unit is validated; do not repeat passed checks or finish this settled unit again. Continue remaining units with ${startDirectUnit}, or call ${reviewMission} with actual risk tags. Independent Review and Operator final acceptance remain required.` });
|
|
2031
2042
|
});
|
|
2032
2043
|
} };
|
|
2033
2044
|
const stringList = { type: "array", items: { type: "string" } };
|
|
@@ -2664,13 +2675,26 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2664
2675
|
}
|
|
2665
2676
|
const newFindings = review?.runID === run.runID && review.verdict === "findings" &&
|
|
2666
2677
|
existing?.reviewIdentity !== missionReviewIdentity(mission);
|
|
2667
|
-
|
|
2678
|
+
let validationRecovery = false;
|
|
2679
|
+
if (existing?.status === "ready" && run.phase === "awaiting-acceptance") {
|
|
2680
|
+
try {
|
|
2681
|
+
await assertCorrectionValidation(run);
|
|
2682
|
+
}
|
|
2683
|
+
catch (error) {
|
|
2684
|
+
if (!(error instanceof Error) || !error.message.startsWith("mission-review-correction-validation-stale:"))
|
|
2685
|
+
throw error;
|
|
2686
|
+
// Read-only self-recheck cannot repair stale checks. Reuse the existing
|
|
2687
|
+
// same-author correction admission, without blessing historical evidence.
|
|
2688
|
+
validationRecovery = true;
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
const recovery = existing !== undefined && ((existing.status === "failed" && run.phase === "awaiting-decision") || validationRecovery);
|
|
2668
2692
|
if (existing && ((!newFindings && !recovery) || ["prepared", "running"].includes(existing.status)))
|
|
2669
2693
|
return JSON.stringify({ status: `correction-${existing.status}`,
|
|
2670
2694
|
...(run.phase === "prepared" ? { task: operators.nextWorkerTask(run) } : {}),
|
|
2671
2695
|
next_action: "Continue only the existing correction Task. Ready requires explicit SAME-author native self-recheck; only residual concrete Major risk requires a different Reviewer. Failure retains the candidate and cumulative spend." });
|
|
2672
2696
|
if (!run.units.some(unit => unit.unit.write.length) ||
|
|
2673
|
-
(!recovery && (run.phase !== "awaiting-acceptance" || review?.runID !== run.runID)) || review
|
|
2697
|
+
(!recovery && (run.phase !== "awaiting-acceptance" || review?.runID !== run.runID)) || !review || (!validationRecovery && review.verdict !== "findings") ||
|
|
2674
2698
|
!review.child || !review.initialPrompt || !review.result)
|
|
2675
2699
|
throw new Error("mission-review-correction-unavailable");
|
|
2676
2700
|
const original = mission.corrections?.at(-1);
|
|
@@ -2696,7 +2720,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2696
2720
|
throw new Error("mission-review-correction-budget-unavailable");
|
|
2697
2721
|
const reviewIdentity = missionReviewIdentity(mission);
|
|
2698
2722
|
const plan = missionPlan(mission, [{ title: `Correct ${run.units[0].unit.title}`,
|
|
2699
|
-
objective:
|
|
2723
|
+
objective: `${validationRecovery ? "The prior correction completed, but its inherited validation is now stale. Preserve completed implementation, reproduction, original findings and historical checks; refresh only affected checks in this SAME author context. If the check recipe needs repair, use repair_review here as its existing author. Do not redo unchanged implementation/discovery or request another independent Review. " : ""}Correct all retained concrete Major/Medium findings in this SAME native conversation; preserve every original requirement. Exact findings are at correction_context.findings in the handoff; retained_findings_ref is optional lineage, not an instruction to reread/print the entire Mission or previous review prompt. Relevant search and focused diagnostics may widen normally; do not rediscover unchanged work. ${REVIEWER_VALIDATION_WORKFLOW} Retain the requested commit/clean boundary. THEN explicitly self-recheck the original requirements, ALL retained findings, correction and relevant impact in this Task. Correct known defects and revalidate affected checks before finishing. First line SELF_RECHECKED. Next line self_recheck: {"candidate":"current-validated","unresolved_findings":[],"residual_major":null}. The HOST binds current-validated to actual current source and fresh successful native checks after this exact prompt; never copy a pre-edit hash. Explain the actual comparison below. List unresolved concrete Major/Medium defects in unresolved_findings (no acceptance). Only concrete reachable residual Major risk uses residual_major:{"reachable_path":"...","consequence":"serious consequence"} and requires a different Reviewer. Tags/hashes/Medium/prose gaps alone never trigger it. This is author self-recheck, NOT independent PASS. Legacy CORRECTION_READY without self-recheck only permits a same-author read-only fallback Task, never acceptance.`,
|
|
2700
2724
|
read: [...new Set([...(mission.reviewScope?.read ?? []), ...run.units.flatMap(unit => unit.unit.read)])],
|
|
2701
2725
|
write: [...new Set([...(mission.reviewScope?.write ?? []), ...run.units.flatMap(unit => unit.unit.write)])],
|
|
2702
2726
|
validation: run.units.flatMap(unit => unit.unit.validation),
|
|
@@ -2881,15 +2905,20 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2881
2905
|
: { status: "skipped-low-risk" });
|
|
2882
2906
|
});
|
|
2883
2907
|
} };
|
|
2884
|
-
async function
|
|
2908
|
+
async function correctionValidationFailure(run) {
|
|
2885
2909
|
for (const unit of run.units) {
|
|
2886
2910
|
if (!unit.reviewerCorrection || !unit.childSessionID)
|
|
2887
2911
|
continue;
|
|
2888
2912
|
const checked = await reviewerCorrectionValidationFresh(unit.unit.validation, unit.childSessionID, await messages(unit.childSessionID), Date.parse(unit.reviewerCorrection.admittedAt ?? run.createdAt), unit.reviewerCorrection.checks ?? [], input.directory, unit.directExecution?.validationCwd ?? unit.unit.validation_cwd, unit.reviewerCorrection.validationRegisteredAt);
|
|
2889
2913
|
if (!checked.ready)
|
|
2890
|
-
|
|
2914
|
+
return checked.reason;
|
|
2891
2915
|
}
|
|
2892
2916
|
}
|
|
2917
|
+
async function assertCorrectionValidation(run) {
|
|
2918
|
+
const reason = await correctionValidationFailure(run);
|
|
2919
|
+
if (reason)
|
|
2920
|
+
throw new Error(reason);
|
|
2921
|
+
}
|
|
2893
2922
|
/** Shared inline/fallback proof: the exact admitted native prompt's actual successful terminal. */
|
|
2894
2923
|
async function observeNativeSelfRecheck(root, mission, run, author, callID, promptID, admittedAt, expectedSource, suppliedHistory) {
|
|
2895
2924
|
if (!promptID || !Number.isFinite(admittedAt) || mission.runID !== run.runID || run.phase !== "awaiting-acceptance")
|
|
@@ -2915,7 +2944,11 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2915
2944
|
const checked = missionSelfRecheckReport(text, expectedSource ?? source.fingerprint, true);
|
|
2916
2945
|
if (!checked)
|
|
2917
2946
|
return undefined;
|
|
2918
|
-
|
|
2947
|
+
// A stale/missing check is an incomplete self-recheck, not a native lifecycle
|
|
2948
|
+
// accounting error. Settle the real terminal so later prompts can repair it.
|
|
2949
|
+
// Explicit acceptance still requires assertCorrectionValidation.
|
|
2950
|
+
if (await correctionValidationFailure(run))
|
|
2951
|
+
return undefined;
|
|
2919
2952
|
if (expectedSource !== undefined && source.fingerprint !== expectedSource)
|
|
2920
2953
|
return undefined;
|
|
2921
2954
|
return { runID: run.runID, source: source.fingerprint, candidateSource: source.candidateFingerprint,
|
|
@@ -2933,27 +2966,39 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2933
2966
|
}
|
|
2934
2967
|
tools[submitMission] = { description: "Coordinator: return only a completion candidate, a user-only decision, or a proven external/scope/budget blocker. Continue ordinary investigation, scope extensions and corrections yourself. Unit progress is published automatically without waking Operator.",
|
|
2935
2968
|
args: { status: { type: "string", enum: ["ready", "needs-decision", "blocked"] }, summary: stringSchema }, execute: async (args, context) => {
|
|
2936
|
-
const { root
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
:
|
|
2969
|
+
const { root } = await missionAuthority(context.sessionID);
|
|
2970
|
+
return serializeDispatchTransition(root, async () => {
|
|
2971
|
+
const mission = await missions.required(root);
|
|
2972
|
+
if (args.status === "ready") {
|
|
2973
|
+
if (mission.kind === "operation" && !missionExecutionComplete(mission)) {
|
|
2974
|
+
return JSON.stringify({ ...missionPacket(mission, await operators.read(root)), status: "operation-incomplete",
|
|
2975
|
+
next_action: missionExecutionStatus(mission) === "running"
|
|
2976
|
+
? "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."
|
|
2977
|
+
: "Continue the requested operation or submit its actual blocker. A successful setup/NO_START check does not authorize ready." });
|
|
2978
|
+
}
|
|
2979
|
+
const run = await operators.required(root);
|
|
2980
|
+
if (run.phase !== "awaiting-acceptance")
|
|
2981
|
+
throw new Error("mission-units-incomplete");
|
|
2982
|
+
await assertMissionReview(root, mission);
|
|
2943
2983
|
}
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2984
|
+
else if (args.status === "blocked" || args.status === "needs-decision") {
|
|
2985
|
+
// This owner is stopping its direct work, not validating it. Keep the
|
|
2986
|
+
// failed checks/candidate and settle its existing reservation once.
|
|
2987
|
+
const direct = await activateDirect(context.sessionID);
|
|
2988
|
+
if (direct)
|
|
2989
|
+
await control.failDirectUnit(root, context.sessionID);
|
|
2990
|
+
}
|
|
2991
|
+
const updated = await missions.update(root, state => {
|
|
2992
|
+
state.phase = "submitted";
|
|
2993
|
+
state.submission = { status: args.status, summary: args.summary };
|
|
2994
|
+
});
|
|
2995
|
+
const submittedRun = await operators.read(root);
|
|
2996
|
+
return JSON.stringify({ acceptance_summary: await missionAcceptanceSummary(updated, submittedRun, operators, acceptanceValidationObservation),
|
|
2997
|
+
...compactMissionEvidence(missionPacket(updated, submittedRun), submittedRun, root),
|
|
2998
|
+
next_action: args.status === "ready"
|
|
2999
|
+
? "Return this result and acceptance_summary to Operator now. Compare the original requests with the candidate and actual evidence; inspect concrete gaps only, then complete_mission if satisfied. No routine archive search or full source reread. Completion still requires its final comparison and complete_mission receipt."
|
|
3000
|
+
: "Return the saved blocker or user-only decision to Operator now. This is incomplete delivery, not acceptance; retain the candidate, failed checks and cumulative spend. Do not repeat unchanged work or dispatch a replacement merely to finalize this result." });
|
|
2952
3001
|
});
|
|
2953
|
-
const submittedRun = await operators.read(root);
|
|
2954
|
-
return JSON.stringify({ acceptance_summary: await missionAcceptanceSummary(updated, submittedRun, operators, acceptanceValidationObservation),
|
|
2955
|
-
...missionPacket(updated, submittedRun),
|
|
2956
|
-
next_action: "Return this result and acceptance_summary to Operator now. Compare the original requests with the candidate and actual evidence; inspect concrete gaps only, then complete_mission if satisfied. No routine archive search or full source reread. Completion still requires its final comparison and complete_mission receipt." });
|
|
2957
3002
|
} };
|
|
2958
3003
|
tools[completeMission] = { description: "Operator only: after comparing the original request, source, actual checks and current review disposition (explicit native author self-recheck is not independent PASS), explicitly accept the whole mission. A collected terminal failure can satisfy a run-once/report request, not a request for successful execution. Returns operation outcome separately from the measured 🐾 Mission receipt; never treat Worker start, CORRECTION_READY or one passing check as completion.",
|
|
2959
3004
|
args: {}, execute: async (_args, context) => {
|
|
@@ -3720,14 +3765,19 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
3720
3765
|
admittedAt: inline.inlineReview.admittedAt, result: report.result, selfRecheck: report };
|
|
3721
3766
|
});
|
|
3722
3767
|
const latest = await missions.required(ownership.root);
|
|
3768
|
+
const validationFailure = !report && inline.status === "ready" && settled.phase === "awaiting-acceptance"
|
|
3769
|
+
? await correctionValidationFailure(settled) : undefined;
|
|
3723
3770
|
output.output = JSON.stringify({ status: report ? "review-correction-recorded" : "review-correction-incomplete",
|
|
3724
3771
|
reviewer_report: raw, independent: false,
|
|
3772
|
+
...(validationFailure ? { reason: validationFailure } : {}),
|
|
3725
3773
|
acceptance_summary: await missionAcceptanceSummary(latest, settled, operators, acceptanceValidationObservation),
|
|
3726
3774
|
next_action: report && !report.unresolvedFindings.length && !report.residualMajor
|
|
3727
3775
|
? `Host already recorded source, formal checks, delivery and actual native author self-recheck. Compare the original request with this candidate, then ${current.coordinator ? submitMission : completeMission}; no routine operator_status, new review or validation Worker.`
|
|
3728
|
-
:
|
|
3729
|
-
? `
|
|
3730
|
-
:
|
|
3776
|
+
: validationFailure
|
|
3777
|
+
? `No acceptance: ${validationFailure}. Call ${repairReview} to refresh affected checks in the SAME author/context. Preserve completed work and historical evidence; do not redo unchanged implementation/discovery or request another independent Reviewer.`
|
|
3778
|
+
: !report && inline.status === "ready" && settled.phase === "awaiting-acceptance"
|
|
3779
|
+
? `Formal correction validation remains current, but the actual native author self-recheck is missing/failed. No acceptance. Call ${reviewMission} only for the missing read-only self-recheck in the SAME author/context, without rerunning successful checks or requesting another Reviewer.`
|
|
3780
|
+
: `No acceptance. Continue the SAME author through ${repairReview} for actual defects; only a concrete residual Major risk after self-recheck calls for a different Reviewer.` });
|
|
3731
3781
|
taskOwners.delete(request.callID);
|
|
3732
3782
|
return;
|
|
3733
3783
|
}
|
package/dist/plugin/v2.js
CHANGED
|
@@ -147,7 +147,9 @@ function legacyClient(context) {
|
|
|
147
147
|
active: async () => ({ data: await (context.session.active ? context.session.active() : active()) }),
|
|
148
148
|
get: async (request) => {
|
|
149
149
|
const id = sessionID(request);
|
|
150
|
-
|
|
150
|
+
const info = id === undefined ? undefined : await context.session.get({ sessionID: id });
|
|
151
|
+
// The native correction alias is still this same Reviewer's logical role.
|
|
152
|
+
return { data: record(info) && correctionAgent(info.agent) ? { ...info, agent: "dog-reviewer-v010" } : info };
|
|
151
153
|
},
|
|
152
154
|
messages: async (request) => {
|
|
153
155
|
const id = sessionID(request);
|
|
@@ -511,7 +513,10 @@ async function registerV2Hooks(context, hooks, background, liveState) {
|
|
|
511
513
|
};
|
|
512
514
|
});
|
|
513
515
|
for (const [name, definition] of Object.entries(hooks.tool ?? {})) {
|
|
514
|
-
|
|
516
|
+
// The approved increase is discovered through execute/search. Direct-only registrations
|
|
517
|
+
// are absent from that catalog; retain the other controls' existing direct entrypoints.
|
|
518
|
+
editor.add({ name, description: definition.description, input: toolSchema(definition.args),
|
|
519
|
+
options: { codemode: name === "sortie_v010_extend_mission_budget" },
|
|
515
520
|
execute: async (input, execution) => {
|
|
516
521
|
await background.reconcile(String(execution.sessionID ?? ""));
|
|
517
522
|
let content;
|
|
@@ -693,7 +698,7 @@ async function registerV2Hooks(context, hooks, background, liveState) {
|
|
|
693
698
|
await reconcileCorrectionPermissions(String(event.sessionID));
|
|
694
699
|
if (record(event.tools)) {
|
|
695
700
|
const visible = {
|
|
696
|
-
"dog-operator": ["start_mission", "plan_units", "start_direct_unit", "finish_direct_unit", "retry_mission_unit", "operator_next", "operator_status", "expand_unit", "review_mission", "repair_review", "complete_mission", "cancel_operator", "reflection"],
|
|
701
|
+
"dog-operator": ["start_mission", "plan_units", "start_direct_unit", "finish_direct_unit", "retry_mission_unit", "operator_next", "operator_status", "extend_mission_budget", "expand_unit", "review_mission", "repair_review", "complete_mission", "cancel_operator", "reflection"],
|
|
697
702
|
"dogs-coordinator": ["plan_units", "start_direct_unit", "finish_direct_unit", "operator_next", "operator_status", "expand_unit", "review_mission", "repair_review", "submit_mission", "skip_mission_consultation", "retry_mission_unit", "rescue_mission_unit"],
|
|
698
703
|
"dog-worker-v010": ["bind_write_gate", "release_write_gate", "operator_status", "expand_unit"],
|
|
699
704
|
"dog-luna-worker-v010": ["bind_write_gate", "release_write_gate", "operator_status", "expand_unit"],
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { type RuntimeProfile } from "./core/runtime-profile.ts";
|
|
2
2
|
/** Repository-local dependency environment shared by all units; excluded from reviewed and captured source. */
|
|
3
3
|
export declare const TOOL_ENVIRONMENT = ".sortie-env";
|
|
4
|
+
/** Task-specific environment limits qualify general dependency setup guidance. */
|
|
5
|
+
export declare const MISSION_DEPENDENCY_WORKFLOW = "Honor original dependency limits in setup and unit objectives. If the user permits installs only for\nproven-missing packages, an installed but incompatible package is not missing: do not replace it or\ndescribe it as missing compatible tooling. General registry/compatible-version guidance does not widen\nthat task-specific limit. Reuse a supplied environment; create one only when the original request permits.\nOtherwise carry out authorized dependency repair normally. If required behavior remains unverified under\nthose limits, retain in-scope work and report the limitation, not successful verification.";
|
|
4
6
|
/** Ordinary requested Git delivery uses source scope, not repository control-storage scope. */
|
|
5
7
|
export declare const MISSION_GIT_SCOPE = "Requested git add <paths> (with optional --) and git commit -m ... are normal source-scope Git operations;\nthey do not require .git/** scope. Preserve explicit user ordering and host Git lifecycle; attempt supported\noperations and report actual denials, not inferred gaps. Stage actual changed deliverables only: permission\nfor an unchanged file or deleted untracked scratch does not require staging it. Repair a missing in-request\noutput via expand_unit, then continue the SAME Task; covered paths need no new grant or dispatch.";
|
|
6
|
-
export declare const VALIDATION_WORKFLOW = "## Time-aware validation workflow\n\nOperator/Coordinator: put the known meaningful formal check from the user, project or task context in validation,\nnot another objective copy. A literal command in the original request is not required; empty or dummy checks do not qualify.\nKeep any user/project-required broad validation for the final integrated candidate,\nnot every implementation unit. Do not add a full suite merely as a precaution or create a testing agent.\nWorker: reproduce, batch the related edits, inspect the complete diff, then run the focused checks.\nFix failures with the smallest exercising check before starting a costly suite. Do not execute the entire\nformal validation list after each patch; run it in declared order when the unit candidate is stable.\nIf broad validation is already declared, defer it until focused checks pass and known edits are finished;\ndo not remove it, substitute a tiny check for it, or claim an unrun requirement passed.\nAfter a late fix, select checks for the affected inputs; repeat broad validation when the requested\ncontract or host evidence freshness requires it, not solely because any file or Worker changed.\nDocumentation-only changes do not automatically invalidate unrelated runtime/test results; retain the\nchecked candidate and show why reuse is valid under project and host rules. Never promote stale proof.\nBefore a costly check, state its purpose and known duration (unknown if unmeasured). In the concise return,\nreport command, scope, actual exit/elapsed time and any rerun reason; never invent savings or timings.\nReview evidence gaps need original excerpts, not another patch or full test. Keep autonomous correction,\nrequired review, accepted criteria and cumulative budget intact; this workflow adds no approval or denial.\n";
|
|
8
|
+
export declare const VALIDATION_WORKFLOW = "## Time-aware validation workflow\n\nOperator/Coordinator: put the known meaningful formal check from the user, project or task context in validation,\nnot another objective copy. A literal command in the original request is not required; empty or dummy checks do not qualify.\nFor a concrete public reproduction, carry its entrypoint and relevant input into the unit objective and formal reproduction check.\nPreserve its fixture layout and working directory. A standalone example project belongs in its own fixture root within allowed paths;\ninvoke from there with the active environment, not the source checkout root where import paths or configuration may mask the failure.\nDerive the shell recipe without substituting lower-level library calls; those checks may supplement, never replace, the public entrypoint.\nReuse existing checks that already exercise it. If authorized setup cannot run it, retain useful work and report the verification gap, not a passing reproduction.\nFor direct work with an unknown reproduction recipe, resolve its flags, configuration and cwd with ordinary native diagnostics before formal registration.\nReuse an already observed failing baseline; do not rerun it merely to plan. A command that never exercises the reported path is not a passing reproduction.\nUse existing project configuration within the original path constraints. Known recipes and Worker-owned investigation need no extra preparation or unit.\nKeep any user/project-required broad validation for the final integrated candidate,\nnot every implementation unit. Do not add a full suite merely as a precaution or create a testing agent.\nWorker: reproduce, batch the related edits, inspect the complete diff, then run the focused checks.\nFix failures with the smallest exercising check before starting a costly suite. Do not execute the entire\nformal validation list after each patch; run it in declared order when the unit candidate is stable.\nIf broad validation is already declared, defer it until focused checks pass and known edits are finished;\ndo not remove it, substitute a tiny check for it, or claim an unrun requirement passed.\nAfter a late fix, select checks for the affected inputs; repeat broad validation when the requested\ncontract or host evidence freshness requires it, not solely because any file or Worker changed.\nDocumentation-only changes do not automatically invalidate unrelated runtime/test results; retain the\nchecked candidate and show why reuse is valid under project and host rules. Never promote stale proof.\nBefore a costly check, state its purpose and known duration (unknown if unmeasured). In the concise return,\nreport command, scope, actual exit/elapsed time and any rerun reason; never invent savings or timings.\nReview evidence gaps need original excerpts, not another patch or full test. Keep autonomous correction,\nrequired review, accepted criteria and cumulative budget intact; this workflow adds no approval or denial.\n";
|
|
7
9
|
/** Worker-only projection; planning/review authorities retain the complete shared workflow. */
|
|
8
10
|
export declare const WORKER_VALIDATION_WORKFLOW = "Batch edits, reconcile requirements/diff, run focused tests, then every registered formal check exactly in order:\nseparate foreground native shell calls, no extra tee, redirect or wrapper. Diagnostics are not formal evidence.\nRerun affected checks and required broad checks when contract/freshness requires; never drop required validation or claim stale/unrun proof.\n";
|
|
9
11
|
/** Correction uses the inherited command identities; diagnostics do not acquire formal evidence. */
|
|
@@ -11,6 +13,8 @@ export declare const REVIEWER_VALIDATION_WORKFLOW = "Run inherited formal comman
|
|
|
11
13
|
export declare function missionOperatorContent(profile: RuntimeProfile, version: string): string;
|
|
12
14
|
/** Keep representation oracles consistent in direct execution, Worker and Review. */
|
|
13
15
|
export declare const MISSION_REPRESENTATION_ORACLE = "Same-type representation, not name/visitor analogy; resolve conflicts.";
|
|
16
|
+
/** Coordinator authors and plans regressions without adding another validation/review lane. */
|
|
17
|
+
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.";
|
|
14
18
|
/** Shared by the installed Reviewer and its host-generated mission prompt. */
|
|
15
19
|
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.\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.";
|
|
16
20
|
/** Mission Reviewer uses ordinary host read/search permissions, not a supplied-packet-only protocol. */
|
|
@@ -3,6 +3,13 @@ import { STRATEGY_TRIGGERS, SOURCE_REVIEW_RISK_TAGS } from "./core/consultation.
|
|
|
3
3
|
import { SCOUT_EVIDENCE_CODES } from "./core/scout-contract.js";
|
|
4
4
|
/** Repository-local dependency environment shared by all units; excluded from reviewed and captured source. */
|
|
5
5
|
export const TOOL_ENVIRONMENT = ".sortie-env";
|
|
6
|
+
/** Task-specific environment limits qualify general dependency setup guidance. */
|
|
7
|
+
export const MISSION_DEPENDENCY_WORKFLOW = `Honor original dependency limits in setup and unit objectives. If the user permits installs only for
|
|
8
|
+
proven-missing packages, an installed but incompatible package is not missing: do not replace it or
|
|
9
|
+
describe it as missing compatible tooling. General registry/compatible-version guidance does not widen
|
|
10
|
+
that task-specific limit. Reuse a supplied environment; create one only when the original request permits.
|
|
11
|
+
Otherwise carry out authorized dependency repair normally. If required behavior remains unverified under
|
|
12
|
+
those limits, retain in-scope work and report the limitation, not successful verification.`;
|
|
6
13
|
/** Ordinary requested Git delivery uses source scope, not repository control-storage scope. */
|
|
7
14
|
export const MISSION_GIT_SCOPE = `Requested git add <paths> (with optional --) and git commit -m ... are normal source-scope Git operations;
|
|
8
15
|
they do not require .git/** scope. Preserve explicit user ordering and host Git lifecycle; attempt supported
|
|
@@ -13,6 +20,14 @@ export const VALIDATION_WORKFLOW = `## Time-aware validation workflow
|
|
|
13
20
|
|
|
14
21
|
Operator/Coordinator: put the known meaningful formal check from the user, project or task context in validation,
|
|
15
22
|
not another objective copy. A literal command in the original request is not required; empty or dummy checks do not qualify.
|
|
23
|
+
For a concrete public reproduction, carry its entrypoint and relevant input into the unit objective and formal reproduction check.
|
|
24
|
+
Preserve its fixture layout and working directory. A standalone example project belongs in its own fixture root within allowed paths;
|
|
25
|
+
invoke from there with the active environment, not the source checkout root where import paths or configuration may mask the failure.
|
|
26
|
+
Derive the shell recipe without substituting lower-level library calls; those checks may supplement, never replace, the public entrypoint.
|
|
27
|
+
Reuse existing checks that already exercise it. If authorized setup cannot run it, retain useful work and report the verification gap, not a passing reproduction.
|
|
28
|
+
For direct work with an unknown reproduction recipe, resolve its flags, configuration and cwd with ordinary native diagnostics before formal registration.
|
|
29
|
+
Reuse an already observed failing baseline; do not rerun it merely to plan. A command that never exercises the reported path is not a passing reproduction.
|
|
30
|
+
Use existing project configuration within the original path constraints. Known recipes and Worker-owned investigation need no extra preparation or unit.
|
|
16
31
|
Keep any user/project-required broad validation for the final integrated candidate,
|
|
17
32
|
not every implementation unit. Do not add a full suite merely as a precaution or create a testing agent.
|
|
18
33
|
Worker: reproduce, batch the related edits, inspect the complete diff, then run the focused checks.
|
|
@@ -89,6 +104,8 @@ ${controls(profile, ["start_mission", "plan_units", "start_direct_unit", "finish
|
|
|
89
104
|
You are Operator, the user-facing strategic authority. Preserve every current requirement, prohibition,
|
|
90
105
|
quality threshold and explicit model/budget choice. Follow AGENTS.md and use the user's language.
|
|
91
106
|
|
|
107
|
+
${MISSION_DEPENDENCY_WORKFLOW}
|
|
108
|
+
|
|
92
109
|
1. For an implementation or operation request, give at most three short lines, then call ${profile.toolPrefix}start_mission
|
|
93
110
|
with a few concise one-line requirements including negative constraints. The host saves the original
|
|
94
111
|
user message verbatim and recent public context and generates IDs; do not copy it or author contracts, hashes or a proposal.
|
|
@@ -233,6 +250,10 @@ existing user authorization and project gates; npm publication remains manual.
|
|
|
233
250
|
}
|
|
234
251
|
/** Keep representation oracles consistent in direct execution, Worker and Review. */
|
|
235
252
|
export const MISSION_REPRESENTATION_ORACLE = `Same-type representation, not name/visitor analogy; resolve conflicts.`;
|
|
253
|
+
/** Coordinator authors and plans regressions without adding another validation/review lane. */
|
|
254
|
+
export const MISSION_REGRESSION_PLACEMENT = `Prefer an existing relevant test suite/subtest or fixture when it can express the regression assertion.
|
|
255
|
+
If a new test module is needed, prefer a distinctive behavior-specific name over automatically mirroring the implementation module.
|
|
256
|
+
Preserve established assertions and project test discovery. This is placement guidance, not another test, unit or review requirement.`;
|
|
236
257
|
/** Shared by the installed Reviewer and its host-generated mission prompt. */
|
|
237
258
|
export const MISSION_BEHAVIOR_REVIEW = `Establish the test oracle independently of the patch: tests added with the implementation are claims to
|
|
238
259
|
review, not established API behavior. For a changed failure path, compare a pre-existing analogous public
|
|
@@ -445,7 +466,14 @@ existing analogous source/tests for the expected contract when available. Avoid
|
|
|
445
466
|
units just to restate the issue. A test of a neighboring name is not an adjacent check unless it runs
|
|
446
467
|
the changed branch on a relevant different input; keep validation focused and do not require an extra
|
|
447
468
|
test when the existing checks already exercise that boundary.
|
|
469
|
+
When changing an error fallback, distinguish already handled errors from errors the called operation
|
|
470
|
+
can still raise. Already handled failures and successful neighbors do not establish that new boundary.
|
|
471
|
+
Repeating the reported error with another input does not cover still-unhandled related errors.
|
|
472
|
+
If peer source/tests expose a plausible related still-unhandled error, probe its expected fallback
|
|
473
|
+
before choosing the fix; reuse adequate checks. Include this in the current author's objective/check
|
|
474
|
+
plan, not another unit or review round. Do not invent an exhaustive error matrix.
|
|
448
475
|
${MISSION_REPRESENTATION_ORACLE}
|
|
476
|
+
${MISSION_REGRESSION_PLACEMENT}
|
|
449
477
|
For read-only verification, use write: []; do not invent an output file or request write access to inputs.
|
|
450
478
|
If declared build or tests create known generated paths, include those outputs in the initial write scope;
|
|
451
479
|
do not add a separate setup unit just to prepare them.
|
|
@@ -458,8 +486,9 @@ Use absolute native paths for requested global installations or other external o
|
|
|
458
486
|
a directory including a not-yet-created tree. These are execution/evidence scopes, not an additional
|
|
459
487
|
permission grant: the host's native permissions still apply. Include the actual external input/output
|
|
460
488
|
paths in read/write so validation and review observe them; do not substitute a repository symlink.
|
|
489
|
+
${MISSION_DEPENDENCY_WORKFLOW}
|
|
461
490
|
Keep all original requirements covered. Last validation command checks
|
|
462
|
-
that unit. If your quick check shows repository-declared dependencies or the test runner are missing, keep
|
|
491
|
+
that unit. If your quick check shows repository-declared dependencies or the test runner are missing and setup is allowed, keep
|
|
463
492
|
setup inside the first unit: declare its checks through the repository-local tool environment ${TOOL_ENVIRONMENT}/
|
|
464
493
|
(for Python, ${TOOL_ENVIRONMENT}/bin/python -m pytest ...) and let that Worker create it. Never plan a separate setup
|
|
465
494
|
unit or put ${TOOL_ENVIRONMENT}/ in a write scope. Host generates IDs, proof mapping, handoff, manifest and Task references. Dispatch the returned
|
|
@@ -558,17 +587,18 @@ Reuse supplied AGENTS.md; for gaps prefer exact ancestor files/affected subtrees
|
|
|
558
587
|
Read handoff_path in full first: task.objective, verbatim original_requests/unit_instruction, constraints/continuity,
|
|
559
588
|
coverage. Preserve user scope and ordering; prove assigned criteria, not Mission completion.
|
|
560
589
|
Denied: reason/remedy. No routine manifest/goal/status/bind.
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
After compaction recover handoff; inspect diff/results
|
|
590
|
+
${profile.toolPrefix}bind_write_gate with exact project_root and manifest_path=operation_manifest.
|
|
591
|
+
cwd/project_root/paths: opaque; never shorten or normalize segments.
|
|
592
|
+
After compaction recover handoff; inspect diff/results.
|
|
564
593
|
Read/search: existing permissions. Fix unit.write/outputs/checks
|
|
565
|
-
here via ${profile.toolPrefix}expand_unit/contract updates
|
|
594
|
+
here via ${profile.toolPrefix}expand_unit/contract updates; host repair diagnostics;
|
|
566
595
|
no extra approval, restart or delegation. Keep prohibitions, host Git lifecycle, cumulative budget.
|
|
567
596
|
Requested add/commit needs source paths, not .git/** scope.
|
|
568
|
-
|
|
569
|
-
|
|
597
|
+
Pre-change oracles, not new tests; check result/error/state. Fallback: probe other unhandled errors from peer source/tests.
|
|
598
|
+
No exhaustive matrix. Keep reproduction entrypoint/input/layout; rerun or report why unverified.
|
|
570
599
|
${MISSION_REPRESENTATION_ORACLE}
|
|
571
|
-
|
|
600
|
+
Use bounded documented setup in ${TOOL_ENVIRONMENT}/; reuse, never delete.
|
|
601
|
+
User missing-only: installed/incompatible is not missing.
|
|
572
602
|
Per-call modes: check retained creation/use for captured vs current settings.
|
|
573
603
|
Tests: existing suites/subtests or distinctive regression entry names.
|
|
574
604
|
${WORKER_VALIDATION_WORKFLOW}
|