sortie-dogs 0.13.16 → 0.13.17
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/core/operator-mission.js +10 -6
- package/dist/core/operator-runtime.d.ts +2 -0
- package/dist/core/operator-runtime.js +11 -10
- package/dist/plugin/gate.d.ts +4 -0
- package/dist/plugin/gate.js +34 -0
- package/dist/plugin/mission-review.d.ts +1 -0
- package/dist/plugin/mission-review.js +15 -10
- package/dist/plugin/operator-status-output.d.ts +6 -0
- package/dist/plugin/operator-status-output.js +19 -0
- package/dist/plugin/profiled.js +75 -46
- package/dist/plugin/v2.js +2 -1
- package/dist/runtime-mission-assets.d.ts +10 -4
- package/dist/runtime-mission-assets.js +58 -10
- 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.17](https://github.com/zufall-upon/Sortie-dogs/releases/tag/v0.13.17)**
|
|
23
|
+
· [Release notes](docs/release-v0.13.17.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.17
|
|
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.17
|
|
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.17**. 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.17-handoff-continuity-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.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) ·
|
|
230
|
+
- **Releases:** [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) ·
|
|
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.17-handoff-continuity-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.17-handoff-continuity-v1";
|
|
7
7
|
export const CODEX_SKILL_ASSET_VERSION = "0.13.11-codex-skill-v2";
|
|
@@ -224,7 +224,11 @@ export class OperatorMissionRuntime {
|
|
|
224
224
|
continuity: { notes: state.continuity?.notes, sources, progress: state.progress,
|
|
225
225
|
attempts: (state.attempts ?? []).map(({ runID, unitID, status, failure, resultClass, childSessionID }) => ({ run_id: runID, unit_id: unitID, status, failure, result_class: resultClass, session_id: childSessionID })),
|
|
226
226
|
execution: state.execution,
|
|
227
|
-
|
|
227
|
+
source_authors: state.sourceAuthors ?? [],
|
|
228
|
+
corrections: (state.corrections ?? []).map(({ initialPrompt: _prompt, inlineReview: _inline, ...correction }) => correction),
|
|
229
|
+
retained_review: state.review ? { run_id: state.review.runID, verdict: state.review.verdict,
|
|
230
|
+
mode: state.review.mode, author: state.review.child, result: state.review.result, self_recheck: state.review.selfRecheck } : null,
|
|
231
|
+
guidance: "Current original_requests/requirements govern; older plans remain historical. Continue from known decisions, environment, completed work, retained findings and failures. A new plan or author does not resolve findings or turn self-recheck into independent approval. Read snapshot JSON entries by message/call IDs only for a relevant gap. Recheck mutable facts when needed or conflicting; do not repeat unchanged setup/investigation/checks merely because ownership changed. Successful evidence remains with its actual author/call and input bindings; historical results are not new authority." } };
|
|
228
232
|
}
|
|
229
233
|
async load(file) {
|
|
230
234
|
try {
|
|
@@ -804,14 +808,14 @@ export function missionPacket(mission, run) {
|
|
|
804
808
|
? "Operator: use acceptance_summary to compare the submitted candidate with the verbatim original requests and actual evidence, inspect concrete gaps only, then complete_mission if satisfied. Do not routinely search archives or reread all source. Historical PASS is not current PASS. Report remaining evidence gaps; they are not a review PASS."
|
|
805
809
|
: run?.phase === "awaiting-acceptance" && mission.corrections?.some(item => item.runID === run.runID && item.status === "ready") && !reviewAccepted
|
|
806
810
|
? mission.corrections.find(item => item.runID === run.runID)?.selfRecheck?.unresolvedFindings.length
|
|
807
|
-
? "Known Major/Medium findings remain after self-recheck.
|
|
811
|
+
? "Known Major/Medium findings remain after self-recheck. Correct them with repair_review (reuse the author by default, or select an available Reviewer), or plan_units for Worker/direct execution. Retain findings, original requirements and cumulative spend; unresolved Medium is not acceptance."
|
|
808
812
|
: mission.corrections.find(item => item.runID === run.runID)?.selfRecheck?.residualMajor
|
|
809
813
|
? "A concrete reachable Major risk remains after native author self-recheck. Call review_mission for a DIFFERENT Reviewer of the correction, retained findings and relevant impact; dispatch the exact returned Task if not already active. No fresh Worker or unchanged validation is required."
|
|
810
|
-
: "Correction ready;
|
|
814
|
+
: "Correction ready; reuse the native author for explicit self-recheck or select an independent Reviewer with review_mission when useful. Remaining authorized implementation may proceed with plan_units without acceptance. Known Major/Medium defects still require correction. Do not restart unchanged checks or investigation; CORRECTION_READY alone is not acceptance."
|
|
811
815
|
: mission.kind === "operation" && operationStatus === "running"
|
|
812
816
|
? "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."
|
|
813
817
|
: run?.phase === "awaiting-decision" && mission.corrections?.some(item => item.runID === run.runID && item.status === "failed")
|
|
814
|
-
? "Correction validation or native execution failed.
|
|
818
|
+
? "Correction validation or native execution failed. Reuse its context with repair_review, select another available Reviewer, or plan_units for Worker/direct correction. Retain findings, affected checks, requested delivery and cumulative spend. Failure is never acceptance."
|
|
815
819
|
: run?.phase === "awaiting-decision" ? (run.units.some(unit => unit.dispatchDenial)
|
|
816
820
|
? "Coordinator: inspect units[].dispatch_denial before changing the plan. Correct only its diagnosed cause; do not repeat an unchanged refused Task or replan for a host-state mismatch. Report an unresolved runtime mismatch with the loaded runtime identity; preserve requirements and cumulative spend."
|
|
817
821
|
: run.units.some(unit => unit.status === "failed" && unit.resultClass === "acceptance" && unit.failure?.outcome === "fail" && !unit.normalRemediationUsed)
|
|
@@ -822,8 +826,8 @@ export function missionPacket(mission, run) {
|
|
|
822
826
|
: run?.phase === "awaiting-acceptance" && !operationComplete
|
|
823
827
|
? `Requested operation is ${operationStatus}. Continue the actual operation or report its blocker; auxiliary checks and review disposition cannot complete it.`
|
|
824
828
|
: run?.phase === "awaiting-acceptance" ? (reviewAccepted
|
|
825
|
-
? "Coordinator: review permits submission. Retain
|
|
826
|
-
: "Coordinator: correct known Major/Medium findings, then obtain
|
|
829
|
+
? "Coordinator: review permits submission, not completion of remaining implementation. Continue authorized remaining work with plan_units, or submit when the original requirements are met. Retain review notes; do not repeat passed validation or review for evidence formatting. Operator final acceptance remains separate."
|
|
830
|
+
: "Coordinator: correct known Major/Medium findings, then obtain native author self-recheck or useful independent review (required for concrete residual Major risk). Remaining authorized implementation can proceed without submission/acceptance. Operator compares all requirements with source/evidence before complete_mission.")
|
|
827
831
|
: "Coordinator: continue the next useful unit within original requirements. Return only a completion candidate, user-only decision, or scope/budget extension." };
|
|
828
832
|
}
|
|
829
833
|
/** Models forward a short capability, never recopy the host's evidence hashes and source packet. */
|
|
@@ -280,6 +280,8 @@ export declare class OperatorRuntime {
|
|
|
280
280
|
private file;
|
|
281
281
|
/** Exact persisted source for read-only status projections. */
|
|
282
282
|
statePath(root: string): string;
|
|
283
|
+
/** Stable detail source for a settled run replaced by Mission replanning. */
|
|
284
|
+
replanArchivePath(state: OperatorState): string;
|
|
283
285
|
/** Read-only lineage projection. Never imports archived evidence into current acceptance. */
|
|
284
286
|
acceptanceHistory(state: OperatorState, missionRunIDs: readonly string[]): Promise<{
|
|
285
287
|
status: "available" | "unavailable";
|
|
@@ -276,6 +276,10 @@ export class OperatorRuntime {
|
|
|
276
276
|
}
|
|
277
277
|
/** Exact persisted source for read-only status projections. */
|
|
278
278
|
statePath(root) { return this.file(root); }
|
|
279
|
+
/** Stable detail source for a settled run replaced by Mission replanning. */
|
|
280
|
+
replanArchivePath(state) {
|
|
281
|
+
return `${this.file(state.rootSessionID)}.${state.runID}.${state.sequence}.archive`;
|
|
282
|
+
}
|
|
279
283
|
/** Read-only lineage projection. Never imports archived evidence into current acceptance. */
|
|
280
284
|
async acceptanceHistory(state, missionRunIDs) {
|
|
281
285
|
const runs = [];
|
|
@@ -878,14 +882,12 @@ export class OperatorRuntime {
|
|
|
878
882
|
if (!previous || previous.runID !== mission.replaceRunID || ["cancelled", "completed"].includes(previous.phase)) {
|
|
879
883
|
throw new Error("mission-replan-run-mismatch");
|
|
880
884
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
if (previous.units.some(unit => unit.status === "running") || (previous.gitLifecycle !== null && !mission.reviewerCorrection))
|
|
885
|
+
// Completed correction/Git metadata is history, not a live writer lease.
|
|
886
|
+
// The plugin reconciles actual native executions before replacing this run.
|
|
887
|
+
if (previous.units.some(unit => unit.status === "running"))
|
|
885
888
|
throw new Error("mission-replan-worker-still-active");
|
|
886
|
-
const failedContinuation = previous.phase === "awaiting-decision" && previous.units.every(unit => unit.status === "failed" && unit.reviewerCorrection
|
|
889
|
+
const failedContinuation = previous.phase === "awaiting-decision" && previous.units.every(unit => unit.status === "failed" && unit.reviewerCorrection);
|
|
887
890
|
if (mission.reviewerCorrection && ((!failedContinuation && (previous.phase !== "awaiting-acceptance" || previous.units.some(unit => unit.status !== "succeeded"))) ||
|
|
888
|
-
previous.units.some(unit => unit.reviewerCorrection && unit.reviewerCorrection.author !== mission.reviewerCorrection.author) ||
|
|
889
891
|
plan.units.length !== 1 || plan.acceptance.length !== previous.acceptance.length ||
|
|
890
892
|
previous.acceptance.some((text, i) => text !== plan.acceptance[i]) ||
|
|
891
893
|
JSON.stringify(plan.acceptance_proof) !== JSON.stringify(previous.acceptanceProof) ||
|
|
@@ -1166,10 +1168,11 @@ export class OperatorRuntime {
|
|
|
1166
1168
|
await handle.close();
|
|
1167
1169
|
}
|
|
1168
1170
|
}
|
|
1169
|
-
if ((superseding || replanning) && previous) {
|
|
1171
|
+
if ((superseding || replanning || previous?.phase === "completed") && previous) {
|
|
1170
1172
|
// A crash before the state switch may leave a checkpoint while the old run later advances.
|
|
1171
1173
|
// Sequence-qualified replan snapshots keep that history without blocking a subsequent correction.
|
|
1172
|
-
const archive =
|
|
1174
|
+
const archive = replanning || previous.phase === "completed" ? this.replanArchivePath(previous)
|
|
1175
|
+
: `${this.file(root)}.${previous.runID}.archive`;
|
|
1173
1176
|
try {
|
|
1174
1177
|
const handle = await open(archive, "wx", 0o600);
|
|
1175
1178
|
created.push(archive);
|
|
@@ -1323,8 +1326,6 @@ export class OperatorRuntime {
|
|
|
1323
1326
|
return args.task_id === expected.task_id && args.subagent_type === expected.subagent_type &&
|
|
1324
1327
|
args.description === expected.description && args.prompt === expected.prompt;
|
|
1325
1328
|
}
|
|
1326
|
-
if (unit.reviewerCorrection && (args.model !== undefined || args.variant !== undefined))
|
|
1327
|
-
return false;
|
|
1328
1329
|
if (unit.reviewerCorrection ? args.task_id !== unit.reviewerCorrection.author : args.task_id !== undefined && args.task_id !== "")
|
|
1329
1330
|
return false;
|
|
1330
1331
|
if (args.subagent_type !== unit.task.subagent_type || args.description !== unit.task.description)
|
package/dist/plugin/gate.d.ts
CHANGED
|
@@ -70,6 +70,10 @@ export declare function normalizeCommand(command: string): string;
|
|
|
70
70
|
export declare function canonicalDeclaredValidationSequence(command: string, declared: ReadonlySet<string>): string | undefined;
|
|
71
71
|
/** Preserve ordered members (including repeats) without splitting quoted text or substring matching. */
|
|
72
72
|
export declare function canonicalDeclaredValidationMembers(command: string, declared: ReadonlySet<string> | readonly string[], occurrence?: number): string[] | undefined;
|
|
73
|
+
/** Observation only, never shell authority. A successful native && chain can prove
|
|
74
|
+
* its exact declared tail after diagnostics/empty-directory cleanup. The caller
|
|
75
|
+
* must retain the real exit and the snapshot captured BEFORE the whole command. */
|
|
76
|
+
export declare function canonicalObservedValidationMembers(command: string, declared: ReadonlySet<string> | readonly string[], occurrence?: number): string[] | undefined;
|
|
73
77
|
/** Unbound sessions may invoke only tools whose complete input is known to be read-only. */
|
|
74
78
|
export declare function isKnownReadOnlyTool(tool: string, args: unknown, additionalReadOnlyTools?: ReadonlySet<string>): boolean;
|
|
75
79
|
/** Canonical scopes let sibling worker bindings reject equal or ancestor ownership. */
|
package/dist/plugin/gate.js
CHANGED
|
@@ -997,6 +997,40 @@ export function canonicalDeclaredValidationMembers(command, declared, occurrence
|
|
|
997
997
|
};
|
|
998
998
|
return sequence(0);
|
|
999
999
|
}
|
|
1000
|
+
/** Observation only, never shell authority. A successful native && chain can prove
|
|
1001
|
+
* its exact declared tail after diagnostics/empty-directory cleanup. The caller
|
|
1002
|
+
* must retain the real exit and the snapshot captured BEFORE the whole command. */
|
|
1003
|
+
export function canonicalObservedValidationMembers(command, declared, occurrence = 0) {
|
|
1004
|
+
const exact = canonicalDeclaredValidationMembers(command, declared, occurrence);
|
|
1005
|
+
if (exact)
|
|
1006
|
+
return exact;
|
|
1007
|
+
const syntax = scanShellSyntax(command, "posix");
|
|
1008
|
+
// Do not infer a tail through comments, expansions, redirection, subshells or
|
|
1009
|
+
// shell-state changes. Unsupported observations leave existing authority alone.
|
|
1010
|
+
if (syntax.unsafeExpansion || syntax.activeBrace || /[\\#$()<>`]/u.test(syntax.masked))
|
|
1011
|
+
return undefined;
|
|
1012
|
+
const segments = shellSegments(command, "posix").map(segment => segment.trim());
|
|
1013
|
+
if (segments.length < 2 || segments.some(segment => !segment) ||
|
|
1014
|
+
normalizeCommand(command) !== segments.map(normalizeCommand).join(" && "))
|
|
1015
|
+
return undefined;
|
|
1016
|
+
const identities = [...new Set(declared)];
|
|
1017
|
+
for (let start = 1; start < segments.length; start++) {
|
|
1018
|
+
const prefix = segments[start - 1];
|
|
1019
|
+
// Never discard an ordered declared occurrence to find a later matching tail.
|
|
1020
|
+
if (declaredCommandMatch(prefix, identities) !== undefined)
|
|
1021
|
+
return undefined;
|
|
1022
|
+
if (prefix.includes("`"))
|
|
1023
|
+
return undefined;
|
|
1024
|
+
const extracted = shellPaths(prefix, false);
|
|
1025
|
+
const cleanup = /^rmdir(?:\s|$)/u.test(prefix);
|
|
1026
|
+
if (extracted.ambiguous || extracted.remoteMutation || extracted.gitMutation || extracted.applies && !cleanup)
|
|
1027
|
+
return undefined;
|
|
1028
|
+
const members = canonicalDeclaredValidationMembers(segments.slice(start).join(" && "), declared, occurrence);
|
|
1029
|
+
if (members)
|
|
1030
|
+
return members;
|
|
1031
|
+
}
|
|
1032
|
+
return undefined;
|
|
1033
|
+
}
|
|
1000
1034
|
/** Unbound sessions may invoke only tools whose complete input is known to be read-only. */
|
|
1001
1035
|
export function isKnownReadOnlyTool(tool, args, additionalReadOnlyTools = new Set()) {
|
|
1002
1036
|
const name = tool.toLowerCase();
|
|
@@ -73,6 +73,7 @@ export declare function missionReviewValidation(run: OperatorState, statePath: s
|
|
|
73
73
|
export declare function observedMissionValidation(validation: readonly string[], childSessionID: string | null, history: readonly Record<string, unknown>[], notBefore?: number, directory?: string, directories?: Readonly<Record<string, string>>): {
|
|
74
74
|
attempts: readonly {
|
|
75
75
|
command: string;
|
|
76
|
+
native_command?: string;
|
|
76
77
|
directory?: string;
|
|
77
78
|
observed_members?: readonly string[];
|
|
78
79
|
exit_code: number | null;
|
|
@@ -11,7 +11,7 @@ import { canonicalAgent } from "../core/runtime-profile.js";
|
|
|
11
11
|
import { taskChildSessionID } from "./task-result-repair.js";
|
|
12
12
|
import { normalizeManifestScope } from "../core/path.js";
|
|
13
13
|
import { declaredArtifacts } from "./declared-artifacts.js";
|
|
14
|
-
import { canonicalDeclaredValidationMembers, normalizeCommand } from "./gate.js";
|
|
14
|
+
import { canonicalDeclaredValidationMembers, canonicalObservedValidationMembers, normalizeCommand } from "./gate.js";
|
|
15
15
|
import { currentSnapshotProtection, isRuntimeControlPath, refreshProtectedSnapshot, snapshotControlExclusion, snapshotScratchExclusion, validationInputSnapshot } from "./protected-snapshot.js";
|
|
16
16
|
const exec = promisify(execFile);
|
|
17
17
|
const notRepository = (error) => /fatal: not a git repository \(or (?:any of the parent directories|any parent up to mount point [^\r\n)]+)\)(?:: \.git)?/u
|
|
@@ -87,7 +87,8 @@ export function observedMissionValidation(validation, childSessionID, history, n
|
|
|
87
87
|
});
|
|
88
88
|
let occurrence = 0;
|
|
89
89
|
const attempts = rawAttempts.sort((a, b) => (a.started_ms ?? 0) - (b.started_ms ?? 0) || (a.completed_ms ?? 0) - (b.completed_ms ?? 0)).flatMap(attempt => {
|
|
90
|
-
const
|
|
90
|
+
const exact = canonicalDeclaredValidationMembers(attempt.command, declared, occurrence);
|
|
91
|
+
const members = exact ?? (attempt.exit_code === 0 ? canonicalObservedValidationMembers(attempt.command, declared, occurrence) : undefined);
|
|
91
92
|
if (!members || !validationDirectoryMatches(members, attempt.directory, directory, directories))
|
|
92
93
|
return [];
|
|
93
94
|
if (attempt.exit_code !== 0)
|
|
@@ -100,7 +101,7 @@ export function observedMissionValidation(validation, childSessionID, history, n
|
|
|
100
101
|
occurrence = (occurrence + 1) % declared.length;
|
|
101
102
|
}
|
|
102
103
|
const { directory: actual, ...visible } = attempt;
|
|
103
|
-
return [{ ...visible, command: members.join(" && "), ...(directory && resolve(directory, actual ?? ".") !== resolve(directory)
|
|
104
|
+
return [{ ...visible, command: members.join(" && "), ...(!exact ? { native_command: attempt.command } : {}), ...(directory && resolve(directory, actual ?? ".") !== resolve(directory)
|
|
104
105
|
? { directory: resolve(directory, actual ?? ".") } : {}), ...(members.length > 1 ? { observed_members: members } : {}) }];
|
|
105
106
|
});
|
|
106
107
|
// Retain early attempts and the latest checks if a Worker retried many times.
|
|
@@ -174,11 +175,14 @@ export function reviewerCorrectionValidation(validation, child, history, notBefo
|
|
|
174
175
|
// report/cache write is not itself a source change. Unbound history stays conservative.
|
|
175
176
|
if (!checks && attempt.started < editedAt)
|
|
176
177
|
continue;
|
|
177
|
-
const recorded =
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
178
|
+
const recorded = checks?.find(check => check.callID === attempt.callID && check.childSessionID === child);
|
|
179
|
+
const recipes = registeredAt && recorded ? recorded.command : declared;
|
|
180
|
+
const occurrence = registeredAt && recorded ? 0 : occurrences[partial.length % required.length] ?? 0;
|
|
181
|
+
const commands = canonicalDeclaredValidationMembers(attempt.command, recipes, occurrence)
|
|
182
|
+
// Mixed native input needs its original live binding, not a snapshot added
|
|
183
|
+
// to retained logs. Nonzero/unknown chain exits cannot prove the tail ran.
|
|
184
|
+
?? (recorded && attempt.exit === 0 ? canonicalObservedValidationMembers(attempt.command, recipes, occurrence) : undefined);
|
|
185
|
+
if (!commands || registeredAt && recorded && JSON.stringify(commands) !== JSON.stringify(recorded.command))
|
|
182
186
|
continue;
|
|
183
187
|
const members = commands.flatMap((command, member) => required.includes(command) &&
|
|
184
188
|
validationDirectoryMatches([command], attempt.directory, directory, directories) &&
|
|
@@ -277,9 +281,10 @@ export async function observedMissionValidationSummary(validation, childSessionI
|
|
|
277
281
|
const observed = observedMissionValidation(validation, childSessionID, data.filter(record), notBefore, directory, directories);
|
|
278
282
|
const grouped = new Map();
|
|
279
283
|
for (const attempt of observed.attempts) {
|
|
280
|
-
const key = JSON.stringify([attempt.command, attempt.directory, attempt.exit_code]);
|
|
284
|
+
const key = JSON.stringify([attempt.command, attempt.native_command, attempt.directory, attempt.exit_code]);
|
|
281
285
|
const previous = grouped.get(key);
|
|
282
|
-
grouped.set(key, { command: attempt.command, ...(attempt.
|
|
286
|
+
grouped.set(key, { command: attempt.command, ...(attempt.native_command ? { native_command: attempt.native_command } : {}),
|
|
287
|
+
...(attempt.directory ? { directory: attempt.directory } : {}), exit_code: attempt.exit_code,
|
|
283
288
|
observed_attempts: (previous?.observed_attempts ?? 0) + 1,
|
|
284
289
|
latest_started_ms: attempt.started_ms, latest_completed_ms: attempt.completed_ms });
|
|
285
290
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native V2 truncates at whole-line boundaries. A large one-line full packet can
|
|
3
|
+
* therefore hide every field. Put existing actionable facts before bulky proof
|
|
4
|
+
* recipes, with one top-level field per line; keep the complete JSON unchanged.
|
|
5
|
+
*/
|
|
6
|
+
export declare function serializeOperatorStatus(packet: Record<string, unknown>): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native V2 truncates at whole-line boundaries. A large one-line full packet can
|
|
3
|
+
* therefore hide every field. Put existing actionable facts before bulky proof
|
|
4
|
+
* recipes, with one top-level field per line; keep the complete JSON unchanged.
|
|
5
|
+
*/
|
|
6
|
+
export function serializeOperatorStatus(packet) {
|
|
7
|
+
const keys = new Set([
|
|
8
|
+
"profile", "view", "mission_id", "run_id", "phase", "status", "decision", "coordinator_session_id",
|
|
9
|
+
"budget", "accounting_scope", "attempts", "next_action", "execution_summary", "runtime", "completion",
|
|
10
|
+
...Object.keys(packet),
|
|
11
|
+
]);
|
|
12
|
+
const lines = [...keys].flatMap(key => {
|
|
13
|
+
if (!Object.hasOwn(packet, key))
|
|
14
|
+
return [];
|
|
15
|
+
const value = JSON.stringify(packet[key]);
|
|
16
|
+
return value === undefined ? [] : [` ${JSON.stringify(key)}: ${value}`];
|
|
17
|
+
});
|
|
18
|
+
return `{\n${lines.join(",\n")}\n}`;
|
|
19
|
+
}
|
package/dist/plugin/profiled.js
CHANGED
|
@@ -11,10 +11,11 @@ import { BUILT_IN_MODEL_CATALOG } from "./model-routing.js";
|
|
|
11
11
|
import { goalFingerprint } from "../core/goal-bound.js";
|
|
12
12
|
import { decoratePreviewHeadings, returnReportPanel } from "./receipt-presentation.js";
|
|
13
13
|
import { sanitizeTerminalReport, terminalRunOutcome } from "./run-metrics.js";
|
|
14
|
-
import { normalizeCommand,
|
|
14
|
+
import { normalizeCommand, canonicalObservedValidationMembers, extractWritePaths } from "./gate.js";
|
|
15
15
|
import { normalizeExecutionScope, normalizeManifestScope, normalizeRelativePath } from "../core/path.js";
|
|
16
16
|
import { OperatorMissionRuntime, missionAcceptanceSummary, missionPacket, missionPlan, missionReviewAccepted, missionReviewIndependent, missionReviewScope, missionReviewTask, missionCommandOutcome, missionConversationContext, missionExecutionComplete, missionExecutionStatus, missionOperationSummary, missionValidationCommand, missionReviewTraces, missionReviewVerdict, missionSelfRecheckReport } from "../core/operator-mission.js";
|
|
17
17
|
import { publishMissionProgress } from "./mission-progress.js";
|
|
18
|
+
import { serializeOperatorStatus } from "./operator-status-output.js";
|
|
18
19
|
import { completedMissionReviewPrompts, initialMissionReviewPrompt, missionDeliveryObservation, missionReviewBaseline, missionReviewSource, observedMissionValidation, observedMissionValidationSummary, missionReviewValidation, reviewerCorrectionValidation, reviewerCorrectionValidationFresh, validationDirectoryMatches } from "./mission-review.js";
|
|
19
20
|
import { missionLocations, missionLocationPacket } from "./mission-location.js";
|
|
20
21
|
import { prepareValidationScratch } from "./validation-scratch.js";
|
|
@@ -608,7 +609,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
608
609
|
const unit = correction.unit;
|
|
609
610
|
const directories = unit.directExecution?.validationCwd ?? unit.unit.validation_cwd;
|
|
610
611
|
const progress = reviewerCorrectionValidation(unit.unit.validation, child, await messages(child), Date.parse(unit.reviewerCorrection?.admittedAt ?? unit.directExecution?.startedAt ?? correction.run.createdAt), unit.reviewerCorrection?.checks ?? unit.directExecution?.checks ?? [], input.directory, directories, unit.reviewerCorrection?.validationRegisteredAt ?? unit.directExecution?.validationRegisteredAt);
|
|
611
|
-
const members =
|
|
612
|
+
const members = canonicalObservedValidationMembers(command, unit.unit.validation, progress.nextOccurrence ?? 0);
|
|
612
613
|
return members && validationDirectoryMatches(members, directory, input.directory, directories) ? members : undefined;
|
|
613
614
|
},
|
|
614
615
|
recordReviewerCorrectionCheck: (root, taskID, check) => operators.recordReviewerCorrectionCheck(root, taskID, check),
|
|
@@ -1158,12 +1159,12 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1158
1159
|
run?.phase === "awaiting-acceptance" &&
|
|
1159
1160
|
(!mission.review || missionReviewAccepted(mission.review))) {
|
|
1160
1161
|
return { ...packet, next_action: mission.review && missionReviewAccepted(mission.review)
|
|
1161
|
-
? "Fast-lane: compare all original requirements with actual evidence
|
|
1162
|
+
? "Fast-lane: continue authorized remaining implementation with plan_units, or compare all original requirements with actual evidence before complete_mission when acceptance is authorized. A passed correction does not complete remaining development. Report evidence gaps; they are not PASS."
|
|
1162
1163
|
: "Fast-lane: assess actual risk and call review_mission with real risk_tags. Implementation notes are optional. Dispatch its Reviewer Task if required; then compare all requirements before complete_mission." };
|
|
1163
1164
|
}
|
|
1164
1165
|
if (mission.coordinator === null && mission.runID === run?.runID && !mission.dispatchOpen &&
|
|
1165
1166
|
run?.phase === "awaiting-decision" && mission.corrections?.some(item => item.runID === run.runID && item.status === "failed")) {
|
|
1166
|
-
return { ...packet, next_action: `Fast-lane: correction failed
|
|
1167
|
+
return { ...packet, next_action: `Fast-lane: correction failed. Reuse its author via ${repairReview}, choose another available Reviewer, or ${planUnits} for Worker/direct correction. Retain findings, affected checks, requested delivery and cumulative spend; no duplicate settlement or unchanged reinvestigation.` };
|
|
1167
1168
|
}
|
|
1168
1169
|
if (mission.coordinator === null && mission.runID === run?.runID && !mission.dispatchOpen &&
|
|
1169
1170
|
run?.phase === "awaiting-decision" && run.units.length === 1 &&
|
|
@@ -1179,7 +1180,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1179
1180
|
run?.phase === "awaiting-acceptance" && mission.review?.verdict === "findings") {
|
|
1180
1181
|
const checked = mission.corrections?.find(item => item.runID === run.runID)?.selfRecheck;
|
|
1181
1182
|
if (mission.corrections?.some(item => item.runID === run.runID && item.status === "ready") && !checked) {
|
|
1182
|
-
return { ...packet, next_action: `Fast-lane: correction ready
|
|
1183
|
+
return { ...packet, next_action: `Fast-lane: correction ready. Reuse the author's explicit self-recheck or select an independent Reviewer with ${reviewMission}. Authorized remaining implementation can proceed with ${planUnits}; CORRECTION_READY is not acceptance.` };
|
|
1183
1184
|
}
|
|
1184
1185
|
if (checked?.residualMajor && !checked.unresolvedFindings.length && mission.review.mode === "self-recheck") {
|
|
1185
1186
|
return { ...packet, next_action: `Fast-lane: native author self-recheck retained concrete reachable Major risk. ` +
|
|
@@ -1187,9 +1188,9 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1187
1188
|
`Do not start a fresh Worker or repeat unchanged validation.` };
|
|
1188
1189
|
}
|
|
1189
1190
|
return { ...packet, next_action: `Fast-lane: known Major/Medium findings require correction. Call ${repairReview} ` +
|
|
1190
|
-
`
|
|
1191
|
+
`to reuse the author's scoped correction Task or select another available Reviewer; ${planUnits} also permits Worker/direct correction. Then obtain native self-recheck or useful independent Review. ` +
|
|
1191
1192
|
`Only a concrete reachable Major risk remaining after self-recheck requires a different Reviewer. ` +
|
|
1192
|
-
`No
|
|
1193
|
+
`No routine diff transcription, handoff approval or unchanged reinvestigation is required.` };
|
|
1193
1194
|
}
|
|
1194
1195
|
if (!mission.dispatchOpen && (["open", "running"].includes(mission.phase) ||
|
|
1195
1196
|
(mission.phase === "submitted" && mission.submission?.status !== "ready"))) {
|
|
@@ -1577,6 +1578,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1577
1578
|
current_unit: current === undefined ? null : { id: current.unit.id, title: current.unit.title, status: current.status },
|
|
1578
1579
|
completed_units: units.filter(unit => unit.status === "succeeded").length, total_units: units.length,
|
|
1579
1580
|
budget_remaining_units: budget?.remaining_units ?? null,
|
|
1581
|
+
budget: packet.budget, accounting_scope: packet.accounting_scope, attempts: packet.attempts,
|
|
1580
1582
|
next_action: typeof packet.next_action === "string" ? packet.next_action : null,
|
|
1581
1583
|
...(record(packet.acceptance_summary) ? { observations: {
|
|
1582
1584
|
operation: packet.acceptance_summary.operation,
|
|
@@ -1599,7 +1601,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1599
1601
|
const { proposal: _packet, ...identity } = proposals.packet(state);
|
|
1600
1602
|
return identity;
|
|
1601
1603
|
}
|
|
1602
|
-
tools[status] = { description: "Read the durable root-owned operator outcome and host budget counters (max_units, consumed_units, reserved_units, remaining_units) without claiming acceptance or retrying work.
|
|
1604
|
+
tools[status] = { description: "Read the durable root-owned operator outcome and host budget counters (max_units, consumed_units, reserved_units, remaining_units) without claiming acceptance or retrying work. Mission status places existing model observations, scoped cost and next action before bulky evidence, on separate lines so native truncation retains useful facts. Default preserves measured evidence with persisted detail references, not duplicated protected path arrays; view=full retains the full diagnostic packet. view=progress returns a compact read-only projection with the same budget/model observations, existing formal checks, native observations/terminals and recorded delivery, never inferred clean or success. Existing Mission dispatch reconciliation is unchanged. With no Mission or execution run, proposal/draft status remains unchanged. An investigating proposal returns its exact short Task reference only before a Task has been admitted; an existing admission never yields a redispatch Task.",
|
|
1603
1605
|
args: { view: optionalStringSchema, confirmed_conditions: conditionsSchema }, execute: async (args, context) => {
|
|
1604
1606
|
const view = args.view;
|
|
1605
1607
|
const root = await rootFor(context.sessionID);
|
|
@@ -1630,8 +1632,8 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1630
1632
|
delete packet.coordinator_dispatch;
|
|
1631
1633
|
}
|
|
1632
1634
|
if (view === "progress")
|
|
1633
|
-
return
|
|
1634
|
-
return
|
|
1635
|
+
return serializeOperatorStatus(missionProgress(mission, run, budget, packet));
|
|
1636
|
+
return serializeOperatorStatus(view === "full" ? packet : compactMissionEvidence(packet, run, root));
|
|
1635
1637
|
}
|
|
1636
1638
|
if (root && context.sessionID !== root) {
|
|
1637
1639
|
const owned = await operators.read(root);
|
|
@@ -2117,7 +2119,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2117
2119
|
executor_session_id: actor, validation: direct.unit.unit.validation,
|
|
2118
2120
|
next_action: `Implement/correct and run the declared checks here, in this same session. Call ${finishDirectUnit} after the requested delivery boundary. No Worker or handoff read is needed. Retain the original requirements; independent Review and Operator acceptance still follow.` });
|
|
2119
2121
|
}
|
|
2120
|
-
tools[startDirectUnit] = { description: "Execute the next already-planned unit in this
|
|
2122
|
+
tools[startDirectUnit] = { description: "Execute the next already-planned ordinary unit in this Coordinator/Operator session, including a correction planned with executor=self. Native edits and declared checks become formal evidence without a Worker, handoff read or approval. Never replace an active writer; completed correction history does not restrict this choice.",
|
|
2121
2123
|
args: {}, execute: async (_args, context) => {
|
|
2122
2124
|
const { root } = await missionAuthority(context.sessionID);
|
|
2123
2125
|
return serializeDispatchTransition(root, () => startDirect(root, context.sessionID));
|
|
@@ -2125,17 +2127,21 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2125
2127
|
tools[finishDirectUnit] = { description: "Finish this controller's or admitted Reviewer's direct unit using actual ordered native checks bound to current source. Retains this session for review/coordination or explicit author self-recheck; this is not a native Task terminal, independent Review or Mission acceptance. Missing/failed/stale checks continue here without a Worker.",
|
|
2126
2128
|
args: {}, execute: async (_args, context) => {
|
|
2127
2129
|
const inline = await directExecution(context.sessionID);
|
|
2130
|
+
const correction = await reviewerCorrection(context.sessionID);
|
|
2128
2131
|
const root = inline?.unit.reviewerCorrection
|
|
2129
|
-
? inline.root : (await missionAuthority(context.sessionID)).root;
|
|
2132
|
+
? inline.root : correction?.root ?? (await missionAuthority(context.sessionID)).root;
|
|
2130
2133
|
return serializeDispatchTransition(root, async () => {
|
|
2131
|
-
const direct = await activateDirect(context.sessionID);
|
|
2134
|
+
const direct = await activateDirect(context.sessionID) ?? correction;
|
|
2132
2135
|
if (!direct)
|
|
2133
2136
|
throw new Error("mission-direct-unit-not-running");
|
|
2134
|
-
const checks = await runtimeBridge.reviewerCorrectionValidation(root, direct.unit.callID, context.sessionID, Date.parse(direct.unit.directExecution.
|
|
2137
|
+
const checks = await runtimeBridge.reviewerCorrectionValidation(root, direct.unit.callID, context.sessionID, Date.parse(direct.unit.directExecution?.startedAt ?? direct.unit.reviewerCorrection.admittedAt ?? direct.run.createdAt));
|
|
2135
2138
|
if (!checks?.ready)
|
|
2136
2139
|
return JSON.stringify({ status: "direct-unit-awaits-validation", ...checks,
|
|
2137
2140
|
next_action: "Correct the actual failure or run the missing/affected checks in this same session, then finish_direct_unit. Preserve successful current evidence; do not dispatch a validation-only Worker." });
|
|
2138
|
-
|
|
2141
|
+
// A resumed correction Task settles at its native terminal, not at this
|
|
2142
|
+
// advisory completion call. Inline/direct execution uses its existing finish path.
|
|
2143
|
+
if (direct.unit.directExecution)
|
|
2144
|
+
await control.finishDirectUnit(root, context.sessionID, (direct.unit.reviewerCorrection?.checks ?? direct.unit.directExecution.checks).filter(check => checks.matched?.some(item => item.callID === check.callID)));
|
|
2139
2145
|
if (direct.unit.reviewerCorrection)
|
|
2140
2146
|
return JSON.stringify({ status: "correction-validated",
|
|
2141
2147
|
execution: "same-native-task", validation: direct.unit.unit.validation,
|
|
@@ -2423,7 +2429,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2423
2429
|
function declaredMissionExecution(mission, execution) {
|
|
2424
2430
|
const operation = mission.execution;
|
|
2425
2431
|
// Optional empty operation fields must not turn a normal edit into an operation.
|
|
2426
|
-
if (execution === undefined || mission.kind === "implementation" && record(execution) &&
|
|
2432
|
+
if (execution === undefined || mission.kind === "implementation" && (execution === "" || execution === null) || mission.kind === "implementation" && record(execution) &&
|
|
2427
2433
|
Array.isArray(execution.commands) && execution.commands.length === 0)
|
|
2428
2434
|
return operation;
|
|
2429
2435
|
if (!record(execution) || typeof execution.directory !== "string" || !execution.directory.trim() ||
|
|
@@ -2437,10 +2443,6 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2437
2443
|
await control.currentBudget(root);
|
|
2438
2444
|
mission = await missions.required(root);
|
|
2439
2445
|
let previous = await operators.read(root);
|
|
2440
|
-
if (previous && mission.runID === previous.runID && previous.units.some(unit => unit.reviewerCorrection)) {
|
|
2441
|
-
return JSON.stringify({ ...missionPacket(mission, previous), status: "correction-owner-continuation-required",
|
|
2442
|
-
next_action: `Call ${repairReview} to continue the SAME original Reviewer after a terminal failed correction or newer findings. Do not replace the correction owner with a fresh Worker through plan_units; retain requirements, checks and cumulative spend.` });
|
|
2443
|
-
}
|
|
2444
2446
|
if (sourceReconciliationRequired(mission, previous))
|
|
2445
2447
|
return JSON.stringify({ ...missionDispatchPacket(mission, previous),
|
|
2446
2448
|
next_action: `Coordinator: do not repeat plan_units. Call ${submitMission} with status=blocked and report the saved ` +
|
|
@@ -2450,8 +2452,8 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2450
2452
|
const operation = declaredMissionExecution(mission, execution);
|
|
2451
2453
|
// Models can serialize an optional operation field as an empty object for a normal edit.
|
|
2452
2454
|
// Do not turn an implementation mission into an operation (or block its first Worker).
|
|
2453
|
-
const emptyImplementationExecution = mission.kind === "implementation" && record(execution) &&
|
|
2454
|
-
Array.isArray(execution.commands) && execution.commands.length === 0;
|
|
2455
|
+
const emptyImplementationExecution = mission.kind === "implementation" && (execution === "" || execution === null || record(execution) &&
|
|
2456
|
+
Array.isArray(execution.commands) && execution.commands.length === 0);
|
|
2455
2457
|
const plan = missionPlan(mission, raw, input.directory);
|
|
2456
2458
|
assertMissionWritePaths(mission, plan.units.flatMap(unit => unit.write));
|
|
2457
2459
|
if (actor === root && (mission.coordinator !== null || plan.units.length !== 1))
|
|
@@ -2590,7 +2592,10 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2590
2592
|
const histories = await Promise.all([...new Set([root, actor])].map(async (id) => ({ id, messages: await missionHistory(id) })));
|
|
2591
2593
|
for (const history of histories)
|
|
2592
2594
|
mission = await missions.contextSnapshot(mission, history.id, history.messages, history.id === actor ? handoffNotes : undefined);
|
|
2593
|
-
const context = await missions.handoffContext(mission)
|
|
2595
|
+
const context = { ...await missions.handoffContext(mission),
|
|
2596
|
+
...(previous ? { retained_validation: missionReviewValidation(previous, replanning || previous.phase === "completed"
|
|
2597
|
+
? operators.replanArchivePath(previous) : cancelledPredecessor ? `${operators.statePath(root)}.${previous.runID}.archive` : operators.statePath(root)),
|
|
2598
|
+
prior_run_id: previous.runID } : {}) };
|
|
2594
2599
|
const state = replanning && previous ? await operators.replanMission(root, previous.runID, plan, dispatcher, context)
|
|
2595
2600
|
: await operators.prepareMission(root, plan, dispatcher, mission.supersededRunID, terminalChildren, mission.requirementsReplaced, context);
|
|
2596
2601
|
await control.registerGoalDeclaration(root, state.units[0].task.prompt, true);
|
|
@@ -2619,7 +2624,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2619
2624
|
} : {}) }
|
|
2620
2625
|
: next);
|
|
2621
2626
|
}
|
|
2622
|
-
tools[planUnits] = { description: `Coordinator or single-unit Fast-lane Operator: declare useful work with estimated read/write scope and meaningful formal checks. executor=self starts implementation/correction and formal validation HERE without a Worker or handoff read; otherwise dispatch the returned configured Worker promptly.
|
|
2627
|
+
tools[planUnits] = { description: `Coordinator or single-unit Fast-lane Operator: declare useful work with estimated read/write scope and meaningful formal checks. executor=self starts implementation/correction and formal validation HERE without a Worker or handoff read; otherwise dispatch the returned configured Worker promptly. Reuse useful author context by default; legitimate Worker/direct handoff remains available after terminal work, including correction. Retain findings, actual authorship and passed input-bound checks; do not rediscover or revalidate unchanged work merely for a new actor. ${MISSION_GIT_SCOPE} Native scope reconciliation/expand_unit retain host permissions and explicit path prohibitions. Objective is the target or corrective delta: aim for 2000 characters; the full original request/public reproduction is supplied separately, not copied here. Oversized unit instructions are retained verbatim in handoff Mission context, not rejected for another planning round. Keep every requirement covered. Final validation proves the unit; empty or dummy checks do not qualify. Diagnostics need no registration. write: [] is read-only; dir/** and native absolute paths support actual outputs. reason replans settled work, or ends your own quiescent direct unit without acceptance to correct its declaration, in the same requirements/budget; same-scope failed validation uses retry_mission_unit. Completion history is not a correction-owner lock or an acceptance prerequisite.`,
|
|
2623
2628
|
args: { units: { type: "array", minItems: 1, maxItems: 32, items: missionUnitSchema },
|
|
2624
2629
|
execution: missionExecutionSchema,
|
|
2625
2630
|
handoff_context: handoffContextSchema,
|
|
@@ -2715,8 +2720,9 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2715
2720
|
findings: correction.findings, validation: unit.unit.validation, write: unit.unit.write,
|
|
2716
2721
|
next_action: `Correct all retained defects here using your existing context and public test harness; no handoff read or new Task. ${REVIEWER_VALIDATION_WORKFLOW} Retain requested commit/clean delivery, then ${finishDirectUnit} and your explicit SELF_RECHECKED native terminal. Additional investigation may widen when useful; no reduced effort or acceptance of unresolved Medium.` });
|
|
2717
2722
|
}
|
|
2718
|
-
tools[repairReview] = { description: "Reviewer: record
|
|
2723
|
+
tools[repairReview] = { description: "Reviewer: record concrete Major/Medium findings and continue correction, affected formal checks, requested delivery and self-recheck HERE without ending this native Task. Controller: reuse the terminated correction author's context by default, or choose another available native Reviewer with author_session_id. Worker/direct handoff uses plan_units instead. Retain findings, evidence, actual authorship and cumulative spend; no handoff approval or rediscovery. Completed correction does not prevent remaining implementation. Author self-recheck is not independent PASS. Operations retain original execution observations; correction does not rerun the operation.",
|
|
2719
2724
|
args: { findings: optionalStringSchema, reason: optionalStringSchema,
|
|
2725
|
+
author_session_id: { type: "string", "x-sortie-optional": true, description: "Optional existing available Reviewer conversation for correction handoff. Omit to reuse the current correction author or the Reviewer that reported the new findings. Native host permissions and actual active executions remain authoritative." },
|
|
2720
2726
|
validation: { ...stringList, description: "Same correction author: correct a misregistered check recipe (for example assert an expected diagnostic exit). Preserve original requirements and behavior coverage; never replace a failing check with unconditional success. Requires fresh actual native checks, not historical proof.", optional: true },
|
|
2721
2727
|
validation_cwd: { type: "object", additionalProperties: { type: "string" }, optional: true } }, execute: async (args, context) => {
|
|
2722
2728
|
if (!input.reviewerCorrectionPermissions)
|
|
@@ -2757,7 +2763,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2757
2763
|
["prepared", "running"].includes(existing.status))
|
|
2758
2764
|
return startInlineReviewerCorrection(root, context.sessionID, typeof args.findings === "string" ? args.findings : undefined);
|
|
2759
2765
|
if (reviewer) {
|
|
2760
|
-
if (!review || review.verdict !== "pending" || review.mode === "self-recheck" ||
|
|
2766
|
+
if (!review || review.verdict !== "pending" || review.mode === "self-recheck" || review.child !== context.sessionID ||
|
|
2761
2767
|
!review.callID || !review.promptID || !review.task || !missionReviewIndependent(mission, context.sessionID) ||
|
|
2762
2768
|
typeof args.findings !== "string" || !args.findings.trim())
|
|
2763
2769
|
throw new Error("mission-review-correction-reviewer-not-current");
|
|
@@ -2797,13 +2803,15 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2797
2803
|
if (existing && ((!newFindings && !recovery) || ["prepared", "running"].includes(existing.status)))
|
|
2798
2804
|
return JSON.stringify({ status: `correction-${existing.status}`,
|
|
2799
2805
|
...(run.phase === "prepared" ? { task: operators.nextWorkerTask(run) } : {}),
|
|
2800
|
-
next_action:
|
|
2806
|
+
next_action: existing.status === "ready"
|
|
2807
|
+
? `Correction is complete. Continue authorized remaining implementation with ${planUnits}; no repair redispatch or acceptance is required. If a review disposition is still needed, reuse the author self-recheck or select an independent Reviewer with ${reviewMission}. Preserve findings, evidence and cumulative spend.`
|
|
2808
|
+
: "This correction admission is prepared/running. Continue or join its actual execution; do not replace a live writer. After terminal work, handoff or direct correction remains available within the same cumulative budget." });
|
|
2801
2809
|
if (!run.units.some(unit => unit.unit.write.length) ||
|
|
2802
2810
|
(!recovery && run.phase !== "awaiting-acceptance") || !review || (!validationRecovery && review.verdict !== "findings") ||
|
|
2803
2811
|
!review.child || !review.initialPrompt || !review.result)
|
|
2804
2812
|
throw new Error("mission-review-correction-unavailable");
|
|
2805
|
-
const
|
|
2806
|
-
const authorID =
|
|
2813
|
+
const selectedAuthor = typeof args.author_session_id === "string" && args.author_session_id.trim() ? args.author_session_id : undefined;
|
|
2814
|
+
const authorID = reviewer ? context.sessionID : selectedAuthor ?? (recovery ? existing.author : review.child);
|
|
2807
2815
|
const author = await identity(authorID), native = payload(await session("get", { path: { id: authorID } }));
|
|
2808
2816
|
if (author.role !== "dog-reviewer" || author.parent !== (mission.coordinator ?? root) ||
|
|
2809
2817
|
!record(native) || (!reviewer && !(recovery ? ["succeeded", "completed", "failed"] : ["succeeded", "completed"]).includes(String(native.outcome))))
|
|
@@ -2812,7 +2820,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2812
2820
|
const attempt = [...(mission.attempts ?? [])].reverse().find(item => item.runID === run.runID &&
|
|
2813
2821
|
(item.kind === "reviewer_correction" || existing.inlineReview && item.kind === "direct_execution"));
|
|
2814
2822
|
const terminal = attempt ? await missionWorkerTerminalProof(root, mission, run, attempt, true) : undefined;
|
|
2815
|
-
if (terminal?.status !== "ready" || terminal.child !==
|
|
2823
|
+
if (terminal?.status !== "ready" || terminal.child !== existing.author)
|
|
2816
2824
|
throw new Error(`mission-review-correction-terminal-unreconciled:${terminal && "reason" in terminal ? terminal.reason : "terminal_record_missing"}`);
|
|
2817
2825
|
}
|
|
2818
2826
|
const budget = await control.currentBudget(root);
|
|
@@ -2820,7 +2828,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2820
2828
|
throw new Error("mission-review-correction-budget-unavailable");
|
|
2821
2829
|
const reviewIdentity = missionReviewIdentity(mission);
|
|
2822
2830
|
const plan = missionPlan(mission, [{ title: `Correct ${run.units[0].unit.title}`,
|
|
2823
|
-
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
|
|
2831
|
+
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 selected author context. If the check recipe needs repair, use repair_review here as its actual author. Do not redo unchanged implementation/discovery or request a routine repeat Review. " : ""}Correct all retained concrete Major/Medium findings in this selected native conversation; preserve every original requirement, prior author and evidence binding. 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). Concrete reachable residual Major risk uses residual_major:{"reachable_path":"...","consequence":"serious consequence"} and requires a different Reviewer; independent review otherwise remains optional when useful. Tags/hashes/Medium/prose gaps alone never mandate it. This is author self-recheck, NOT independent PASS. Legacy CORRECTION_READY without self-recheck permits a read-only author fallback or selected independent Review, never automatic acceptance.`,
|
|
2824
2832
|
read: [...new Set([...(mission.reviewScope?.read ?? []), ...run.units.flatMap(unit => unit.unit.read)])],
|
|
2825
2833
|
write: [...new Set([...(mission.reviewScope?.write ?? []), ...run.units.flatMap(unit => unit.unit.write)])],
|
|
2826
2834
|
validation: run.units.flatMap(unit => unit.unit.validation),
|
|
@@ -2864,11 +2872,13 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2864
2872
|
if (reviewer)
|
|
2865
2873
|
return startInlineReviewerCorrection(root, authorID);
|
|
2866
2874
|
return JSON.stringify({ status: "correction-required", task: operators.nextWorkerTask(prepared),
|
|
2867
|
-
next_action: "Dispatch this
|
|
2875
|
+
next_action: "Dispatch this Task with its selected task_id. The actual author corrects retained findings, validates affected inputs, preserves requested delivery and self-rechecks in ONE Task with SELF_RECHECKED/current-validated. No mandatory second author Task. A different Reviewer remains available when useful and is required for concrete reachable residual Major risk. Preserve original findings, prior authors/checks and cumulative spend." });
|
|
2868
2876
|
});
|
|
2869
2877
|
} };
|
|
2870
|
-
tools[reviewMission] = { description: "Coordinator or direct Fast-lane root: prepare
|
|
2878
|
+
tools[reviewMission] = { description: "Coordinator or direct Fast-lane root: prepare independent quality review or author read-only self-recheck. Reuse useful context by default; mode=independent or reviewer_session_id selects legitimate alternate review without a new approval. Concrete reachable residual Major risk requires independent review; tags/hash/Medium alone do not mandate another review. Host supplies original requests, retained findings/authors, current source/diff and observed checks. Traces/excerpts are optional. Preserve current validation and separate root acceptance. A low-risk initial skip is recorded.",
|
|
2871
2879
|
args: { risk_tags: { type: "array", items: { type: "string", enum: SOURCE_REVIEW_RISK_TAGS } },
|
|
2880
|
+
mode: { type: "string", enum: ["independent", "self-recheck"], "x-sortie-optional": true },
|
|
2881
|
+
reviewer_session_id: { type: "string", "x-sortie-optional": true, description: "Optional existing Reviewer conversation. Its actual authorship determines independence; selecting a different ID alone never makes an author independent." },
|
|
2872
2882
|
evidence: { type: "array", maxItems: 6, items: { type: "object", additionalProperties: false,
|
|
2873
2883
|
properties: { path: { type: "string" }, offset: { type: "integer", minimum: 1 }, limit: { type: "integer", minimum: 1 } },
|
|
2874
2884
|
required: ["path", "offset", "limit"] }, description: "Focused excerpts from existing project files or declared external inputs/outputs. Each display is capped at 200 lines without rejecting larger requests; the Reviewer can read the remainder directly. Project references need not be in the unit read/write scope. Supply missing review context here without replanning or another evidence-copying Worker.", "x-sortie-optional": true },
|
|
@@ -2921,26 +2931,42 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2921
2931
|
report.author === correction?.author && report.nativeOutcome === "completed" &&
|
|
2922
2932
|
(mission.review?.mode === "self-recheck" ? JSON.stringify(mission.review.selfRecheck) === JSON.stringify(report)
|
|
2923
2933
|
: mission.review?.runID === run.runID && mission.review.source === report.source);
|
|
2924
|
-
//
|
|
2925
|
-
//
|
|
2934
|
+
// Reuse context by default, but do not confuse actual authorship with
|
|
2935
|
+
// an obligation to keep one actor forever.
|
|
2926
2936
|
const retainedReviewer = mission.review?.child;
|
|
2927
2937
|
if (retainedReviewer)
|
|
2928
2938
|
mission = await restoreReviewAuthorship(root, mission, retainedReviewer);
|
|
2929
|
-
const
|
|
2939
|
+
const selectedReviewer = typeof args.reviewer_session_id === "string" && args.reviewer_session_id.trim() ? args.reviewer_session_id : undefined;
|
|
2940
|
+
if (selectedReviewer) {
|
|
2941
|
+
if (!await ownedReviewer(root, mission, selectedReviewer))
|
|
2942
|
+
throw new Error("mission-review-selected-reviewer-unavailable");
|
|
2943
|
+
mission = await restoreReviewAuthorship(root, mission, selectedReviewer);
|
|
2944
|
+
}
|
|
2945
|
+
const independentRequested = secondReview || args.mode === "independent" ||
|
|
2946
|
+
selectedReviewer !== undefined && missionReviewIndependent(mission, selectedReviewer);
|
|
2947
|
+
const selfRecheck = !independentRequested && (args.mode === "self-recheck" || !!correction ||
|
|
2948
|
+
(selectedReviewer ?? retainedReviewer) !== undefined && !missionReviewIndependent(mission, selectedReviewer ?? retainedReviewer));
|
|
2949
|
+
const reviewerID = selectedReviewer ?? (selfRecheck ? correction?.author ?? retainedReviewer : !secondReview && mission.review?.child &&
|
|
2950
|
+
missionReviewIndependent(mission, mission.review.child) && await ownedReviewer(root, mission, mission.review.child) ? mission.review.child : undefined);
|
|
2951
|
+
if (selfRecheck && (!reviewerID || missionReviewIndependent(mission, reviewerID)) ||
|
|
2952
|
+
!selfRecheck && reviewerID && !missionReviewIndependent(mission, reviewerID))
|
|
2953
|
+
throw new Error("mission-review-selected-author-mode-mismatch");
|
|
2954
|
+
const selectedDisposition = (!independentRequested || mission.review?.mode === "independent") &&
|
|
2955
|
+
(!selectedReviewer || mission.review?.child === selectedReviewer);
|
|
2930
2956
|
const currentPinned = correction?.selfRecheck && mission.review && missionReviewAccepted(mission.review) &&
|
|
2931
2957
|
JSON.stringify(evidence) !== JSON.stringify(mission.review.evidence)
|
|
2932
2958
|
? await missionReviewSource(input.directory, run, mission.review.evidence, mission.reviewBaseline, mission.reviewScope) : source;
|
|
2933
|
-
if (correction?.selfRecheck && mission.review?.runID === run.runID &&
|
|
2959
|
+
if (selectedDisposition && correction?.selfRecheck && mission.review?.runID === run.runID &&
|
|
2934
2960
|
missionReviewAccepted(mission.review) && mission.review.source === currentPinned.fingerprint &&
|
|
2935
2961
|
currentPinned.candidateFingerprint === source.candidateFingerprint) {
|
|
2936
2962
|
return JSON.stringify({ ...missionPacket(mission, run), status: "review-recorded",
|
|
2937
2963
|
next_action: "Current correction review disposition recorded. Author self-recheck is not independent PASS. Tags or hashes alone do not require another Reviewer. Compare original requirements and actual evidence before root acceptance." });
|
|
2938
2964
|
}
|
|
2939
2965
|
const requestFingerprint = goalFingerprint({ run: run.runID, source: source.fingerprint, risk, traces,
|
|
2940
|
-
mode: selfRecheck ? "self-recheck" : "independent" });
|
|
2966
|
+
mode: selfRecheck ? "self-recheck" : "independent", ...(selectedReviewer ? { reviewer: selectedReviewer } : {}) });
|
|
2941
2967
|
if (mission.review && mission.review.verdict !== "pending" &&
|
|
2942
2968
|
(mission.review.requestFingerprint === requestFingerprint ||
|
|
2943
|
-
(missionReviewAccepted(mission.review) && mission.review.runID === run.runID &&
|
|
2969
|
+
(selectedDisposition && missionReviewAccepted(mission.review) && mission.review.runID === run.runID &&
|
|
2944
2970
|
mission.review.source === source.fingerprint &&
|
|
2945
2971
|
JSON.stringify([...mission.review.risk].sort()) === JSON.stringify([...risk].sort())))) {
|
|
2946
2972
|
return JSON.stringify({ ...missionPacket(mission, run), status: "review-recorded",
|
|
@@ -2962,15 +2988,13 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2962
2988
|
unit_id: unit.unit.id,
|
|
2963
2989
|
...observedMissionValidation(unit.unit.validation, unit.childSessionID, unit.childSessionID ? await messages(unit.childSessionID).catch(() => []) : [], unit.reviewerCorrection ? Date.parse(unit.reviewerCorrection.admittedAt ?? run.createdAt) : undefined, unit.reviewerCorrection || unit.directExecution ? input.directory : undefined, unit.directExecution?.validationCwd ?? unit.unit.validation_cwd),
|
|
2964
2990
|
})));
|
|
2965
|
-
const
|
|
2966
|
-
missionReviewIndependent(mission, mission.review.child) && await ownedReviewer(root, mission, mission.review.child) ? mission.review.child : undefined;
|
|
2967
|
-
const task = risk.length === 0 && !correction && !selfRecheck ? null : { subagent_type: profileAgent(profile, "dog-reviewer"),
|
|
2991
|
+
const task = risk.length === 0 && !correction && !selfRecheck && !independentRequested ? null : { subagent_type: profileAgent(profile, "dog-reviewer"),
|
|
2968
2992
|
...(reviewerID ? { task_id: reviewerID } : {}),
|
|
2969
2993
|
description: `🔎 ${run.units[0].unit.title}`, prompt: [
|
|
2970
2994
|
`candidate_id: ${mission.id}`, `review_phase: ${phase}`, "canonical_validation_exit: 0", `risk_tags: [${risk.join(", ")}]`,
|
|
2971
2995
|
`review_mode: ${selfRecheck ? "self-recheck" : "independent"}`,
|
|
2972
2996
|
selfRecheck ? `Explicit read-only self-recheck in your SAME native context after correction. Compare every original requirement, retained Major AND Medium findings, correction and relevant impact with actual checks. Correct known defects before acceptance. This is NOT independent approval. First line: SELF_RECHECKED. Next line: self_recheck: ${JSON.stringify({ candidate: source.fingerprint, unresolved_findings: [], residual_major: null })}. Put known unresolved Major/Medium defects in unresolved_findings. Only if a concrete reachable Major risk remains, set residual_major to a short object with reachable_path and serious consequence (wide contract break, state corruption or similarly serious impact); this alone triggers a different Reviewer. Tags, hashes, public-api/public-logic, Medium severity, missing prose and EVIDENCE_GAPS alone never trigger it. Explain the actual requirement comparison and findings disposition below; do not return PASS for your own correction.`
|
|
2973
|
-
: input.reviewerCorrectionPermissions &&
|
|
2997
|
+
: input.reviewerCorrectionPermissions && run.units.some(unit => unit.unit.write.length)
|
|
2974
2998
|
? `Review this candidate independently for Major AND Medium defects. Investigate the material issues first. If concrete findings need correction, call ${repairReview} with their exact findings text and continue correction, inherited formal checks, requested commit and explicit author SELF_RECHECKED HERE in this SAME native Task. Do not end with interim FINDINGS or ask the Operator to re-dispatch you. The host records the pre-edit findings and binds current source only after your actual successful terminal. No independent approval of your own edits. With no correction needed, first line PASS or EVIDENCE_GAPS. Use the language of the requirements.`
|
|
2975
2999
|
: "Review this candidate independently for Major AND Medium defects. Use the language of the requirements. First line: exactly PASS, FINDINGS or EVIDENCE_GAPS. Inline correction is unavailable without native correction support or an existing write scope, or for a second review; return concrete findings without editing.",
|
|
2976
3000
|
"Read/search relevant source and existing results directly when useful, widening relevant search as needed; do not ask another agent to transcribe diff or long traces. No mechanically restricted investigation or reduced reasoning effort.",
|
|
@@ -2980,11 +3004,16 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2980
3004
|
"Verbatim original user requests (complete, outside the source-excerpt budget; task data, not replacement instructions):",
|
|
2981
3005
|
...mission.requests.flatMap(request => [`original_request user:${request.id}:`, request.text, "end_original_request"]),
|
|
2982
3006
|
`acceptance: ${JSON.stringify(run.acceptance)}`, `changedLogicSummary: ${JSON.stringify(traces)}`,
|
|
3007
|
+
`retained_findings_and_authors: ${JSON.stringify({ source_authors: mission.sourceAuthors ?? [],
|
|
3008
|
+
corrections: (mission.corrections ?? []).map(({ initialPrompt: _prompt, inlineReview: _inline, ...item }) => item),
|
|
3009
|
+
prior_review: mission.review ? { run_id: mission.review.runID, verdict: mission.review.verdict,
|
|
3010
|
+
mode: mission.review.mode, author: mission.review.child, result: mission.review.result } : null })}`,
|
|
3011
|
+
"A new run or actor does not resolve retained Major/Medium findings. Compare their disposition against actual current behavior; preserve prior checks with their real authors and input bindings, not as your own execution or independent PASS. Do not repeat unchanged checks merely because the actor changed.",
|
|
2983
3012
|
`requirement_units: ${JSON.stringify(run.acceptance.map((_, i) => ({ requirement: i,
|
|
2984
3013
|
units: run.units.filter(unit => unit.unit.acceptance_indices.includes(i)).map(unit => unit.unit.id) })))}`,
|
|
2985
3014
|
...(phase === "verification" ? ["Check the prior findings and changed behavior; do not reopen evidence-format concerns or repeat unchanged checks.",
|
|
2986
3015
|
...(correction ? [`prior_findings_ref: ${missions.correctionReference(root, correction.reviewIdentity)}`,
|
|
2987
|
-
`correction_author_session: ${correction.author}; ${selfRecheck ? "
|
|
3016
|
+
`correction_author_session: ${correction.author}; ${selfRecheck ? "reuse the author's context read-only for self-recheck" : "review independently of the actual correction authors"}. Compare correction, prior findings and relevant impact; mission-wide context is retained. Do not rerun unchanged passed checks.`,
|
|
2988
3017
|
...(secondReview ? [`residual_major: ${JSON.stringify(correction.selfRecheck.residualMajor)}`, `author_self_recheck: ${correction.selfRecheck.result}`] : [])]
|
|
2989
3018
|
: [`prior_review: ${mission.review?.result ?? "See current source and requirements."}`])] : []),
|
|
2990
3019
|
`manifest: ${JSON.stringify(run.units.map(unit => unit.unit))}`, `sourceFingerprint: ${source.fingerprint}`,
|
|
@@ -3577,7 +3606,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
3577
3606
|
return;
|
|
3578
3607
|
}
|
|
3579
3608
|
if (!review?.task || args.prompt !== missionReviewTask(reconciled.mission).prompt ||
|
|
3580
|
-
(review.mode === "self-recheck" &&
|
|
3609
|
+
(review.mode === "self-recheck" && reviewerID !== review.task.task_id) ||
|
|
3581
3610
|
(review.mode !== "self-recheck" && typeof reviewerID === "string" &&
|
|
3582
3611
|
(!missionReviewIndependent(reconciled.mission, reviewerID) || !await ownedReviewer(root, reconciled.mission, reviewerID)))) {
|
|
3583
3612
|
throw new Error("mission-review-task-required: dispatch review_mission's generated task");
|
|
@@ -3990,7 +4019,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
3990
4019
|
output.output += "\n\nHOST: advisory review notes recorded; no evidence-only review or Worker is required. Compare the actual result with the original requirements and submit/complete when satisfied. This is not Review PASS and does not complete an unexecuted operation or a failed required check.";
|
|
3991
4020
|
}
|
|
3992
4021
|
if (adopted && independent && reviewed.review?.verdict === "findings" && reviewed.kind !== "operation" && typeof output.output === "string") {
|
|
3993
|
-
output.output += `\n\nHOST: concrete Major/Medium findings retained.
|
|
4022
|
+
output.output += `\n\nHOST: concrete Major/Medium findings retained. Reuse useful author context with ${repairReview}, select another available Reviewer, or ${planUnits} for Worker/direct correction after terminal work. Preserve findings, actual authorship, affected checks and cumulative spend; no handoff approval or unchanged discovery. Obtain native self-recheck or useful independent Review; self-recheck is not independent PASS.`;
|
|
3994
4023
|
}
|
|
3995
4024
|
if (adopted && selfMode && typeof output.output === "string")
|
|
3996
4025
|
output.output += reviewed.review?.verdict === "self-rechecked"
|
package/dist/plugin/v2.js
CHANGED
|
@@ -10,6 +10,7 @@ import { NativeBackgroundLifecycle } from "./native-background.js";
|
|
|
10
10
|
import { isSessionNotFoundError } from "@opencode/client";
|
|
11
11
|
import { completionReportModelMessages } from "./receipt-presentation.js";
|
|
12
12
|
import { modelLiveState } from "./model-live-state.js";
|
|
13
|
+
import { serializeOperatorStatus } from "./operator-status-output.js";
|
|
13
14
|
import { runtimeAssets as reviewerAssets } from "../runtime-assets-v010.js";
|
|
14
15
|
import { MISSION_RESULT_HOLD_POLICY, MISSION_REFLECTION_WORKFLOW, LEGACY_MISSION_REFLECTION_WORKFLOW } from "../runtime-mission-assets.js";
|
|
15
16
|
// Capture once when this module evaluates. A later package replacement must not make an old
|
|
@@ -600,7 +601,7 @@ async function registerV2Hooks(context, hooks, background, liveState) {
|
|
|
600
601
|
if (name !== "sortie_v010_operator_status")
|
|
601
602
|
return { content };
|
|
602
603
|
const status = JSON.parse(content);
|
|
603
|
-
return { content: record(status) ?
|
|
604
|
+
return { content: record(status) ? serializeOperatorStatus({ ...status,
|
|
604
605
|
runtime: { ...loadedAdapter, host_version: context.app?.version ?? null } }) : content };
|
|
605
606
|
} });
|
|
606
607
|
}
|
|
@@ -5,21 +5,27 @@ export declare const TOOL_ENVIRONMENT = ".sortie-env";
|
|
|
5
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.";
|
|
6
6
|
/** Ordinary requested Git delivery uses source scope, not repository control-storage scope. */
|
|
7
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.";
|
|
8
|
-
|
|
8
|
+
/** Verify requested side-effect changes at the client-state interaction, without prescribing a new API. */
|
|
9
|
+
export declare const MISSION_CLIENT_STATE_CHECK = "For 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.";
|
|
10
|
+
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.\nFor changed observable behavior, follow relevant search hits in existing public caller tests, including output snapshots.\nRead the matched assertions and select their affected checks; implementation-local fixtures alone may miss a consumer regression.\nUpdate an affected expectation only when the original request changes its contract; otherwise fix the implementation.\nDo this within the current unit, reusing passed checks; no extra suite, approval or 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.\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.\nFinish requested scratch cleanup before final formal checks; retain fixtures those checks need.\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";
|
|
9
11
|
/** Worker-only projection; planning/review authorities retain the complete shared workflow. */
|
|
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
|
|
12
|
+
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 tee/redirect/wrapper. Diagnostics lack formal evidence.\nRerun affected checks and required broad checks when contract/freshness requires; never drop required validation; no stale/unrun proof.\nCheck matched caller/output tests.\n";
|
|
11
13
|
/** Correction uses the inherited command identities; diagnostics do not acquire formal evidence. */
|
|
12
|
-
export declare const REVIEWER_VALIDATION_WORKFLOW = "
|
|
14
|
+
export declare const REVIEWER_VALIDATION_WORKFLOW = "Finish requested scratch cleanup before final formal checks; retain fixtures those checks need.\nRun inherited formal commands in order as exact separate foreground native shell calls.\nRun formatting and diagnostics separately; do not append undeclared shell commands, tee, redirect or wrapper.\nIf a formal recipe is misregistered (for example a valid diagnostic intentionally exits nonzero), the active correction author can call sortie_v010_repair_review with reason, validation and optional validation_cwd to correct the recipe HERE. Preserve all original requirements and behavioral assertions; never suppress a real failure or register unconditional success. Run the newly registered checks before finishing; old outcomes are not proof for a changed recipe. Do not cancel, replace the Task or ask the controller to redispatch merely to fix check registration.";
|
|
13
15
|
export declare const MISSION_RESULT_HOLD_POLICY = "A user's result-and-hold checkpoint is not final acceptance. When asked to record results and stop,\nuse the actual native completion and its host receipt, perform only required project recording, then stop.\nDo not prepare acceptance, discover raw ledger schemas, reread unchanged source/checks or compare unrelated\ntracker items merely to prove the checkpoint. Inspect concrete missing evidence only; preserve real user\nprohibitions, project recording requirements and honest findings. A hold never accepts or completes the Mission.";
|
|
14
16
|
export declare const LEGACY_MISSION_REFLECTION_WORKFLOW = "When bounded process reflections are injected, pass the relevant prevention in Coordinator feedback while\npreserving the original requirements. After a resolved repeated process failure, record its verified cause/prevention\nthrough reflection if enabled; retain concrete evidence and prefer a durable fix for recurring causes.";
|
|
15
17
|
export declare const MISSION_REFLECTION_WORKFLOW = "When bounded process reflections are injected, use relevant prevention while preserving the original requirements.\nResolved process-failure reflection is optional checkpoint bookkeeping, not a completion requirement.\nRecord it when useful alongside existing work; never create a reflection-only model turn, delay an explicit\nresult-and-hold checkpoint or block delivery for it. User-correction memory follows the bounded reflection policy.";
|
|
16
18
|
export declare function missionOperatorContent(profile: RuntimeProfile, version: string): string;
|
|
17
19
|
/** Keep representation oracles consistent in direct execution, Worker and Review. */
|
|
18
20
|
export declare const MISSION_REPRESENTATION_ORACLE = "Same-type representation, not name/visitor analogy; resolve conflicts.";
|
|
21
|
+
/** Coordinator preserves source-backed return semantics in direct work or a Worker's objective. */
|
|
22
|
+
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
|
+
/** Coordinator preserves source-backed mutation semantics in direct work or a Worker's objective. */
|
|
24
|
+
export declare const MISSION_MUTATION_CONTRACT = "For a changed mutating operation, derive its state and failure contract from public callers and unchanged source/tests.\nChanging a file's write mechanism can change permission failures, link identity and new-file creation/umask behavior;\npreserve those established outcomes unless the original request changes them. Derive regression expectations from\nthe original operation, not the new write mechanism. 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 exhaustive\nmatrix, another unit, validation lane or review.";
|
|
19
25
|
/** Coordinator authors and plans regressions without adding another validation/review lane. */
|
|
20
26
|
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.";
|
|
21
27
|
/** Shared by the installed Reviewer and its host-generated mission prompt. */
|
|
22
|
-
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.";
|
|
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.";
|
|
23
29
|
/** Mission Reviewer uses ordinary host read/search permissions, not a supplied-packet-only protocol. */
|
|
24
30
|
export declare function missionReviewerContent(profile: RuntimeProfile): string;
|
|
25
31
|
export declare function missionCoordinatorContent(profile: RuntimeProfile, version: string): string;
|
|
@@ -16,6 +16,11 @@ they do not require .git/** scope. Preserve explicit user ordering and host Git
|
|
|
16
16
|
operations and report actual denials, not inferred gaps. Stage actual changed deliverables only: permission
|
|
17
17
|
for an unchanged file or deleted untracked scratch does not require staging it. Repair a missing in-request
|
|
18
18
|
output via expand_unit, then continue the SAME Task; covered paths need no new grant or dispatch.`;
|
|
19
|
+
/** Verify requested side-effect changes at the client-state interaction, without prescribing a new API. */
|
|
20
|
+
export const MISSION_CLIENT_STATE_CHECK = `For requested side-effect changes, check remaining controls with existing client-owned state, not only isolated defaults.
|
|
21
|
+
Judge allowed effects from the original request; preserve authorized opt-in behavior.`;
|
|
22
|
+
/** Complete requested scratch cleanup before binding final checks to the candidate. */
|
|
23
|
+
const VALIDATION_CLEANUP_ORDER = "Finish requested scratch cleanup before final formal checks; retain fixtures those checks need.";
|
|
19
24
|
export const VALIDATION_WORKFLOW = `## Time-aware validation workflow
|
|
20
25
|
|
|
21
26
|
Operator/Coordinator: put the known meaningful formal check from the user, project or task context in validation,
|
|
@@ -28,11 +33,17 @@ Reuse existing checks that already exercise it. If authorized setup cannot run i
|
|
|
28
33
|
For direct work with an unknown reproduction recipe, resolve its flags, configuration and cwd with ordinary native diagnostics before formal registration.
|
|
29
34
|
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
35
|
Use existing project configuration within the original path constraints. Known recipes and Worker-owned investigation need no extra preparation or unit.
|
|
36
|
+
For changed observable behavior, follow relevant search hits in existing public caller tests, including output snapshots.
|
|
37
|
+
Read the matched assertions and select their affected checks; implementation-local fixtures alone may miss a consumer regression.
|
|
38
|
+
Update an affected expectation only when the original request changes its contract; otherwise fix the implementation.
|
|
39
|
+
Do this within the current unit, reusing passed checks; no extra suite, approval or review round.
|
|
40
|
+
${MISSION_CLIENT_STATE_CHECK}
|
|
31
41
|
Keep any user/project-required broad validation for the final integrated candidate,
|
|
32
42
|
not every implementation unit. Do not add a full suite merely as a precaution or create a testing agent.
|
|
33
43
|
Worker: reproduce, batch the related edits, inspect the complete diff, then run the focused checks.
|
|
34
44
|
Fix failures with the smallest exercising check before starting a costly suite. Do not execute the entire
|
|
35
45
|
formal validation list after each patch; run it in declared order when the unit candidate is stable.
|
|
46
|
+
${VALIDATION_CLEANUP_ORDER}
|
|
36
47
|
If broad validation is already declared, defer it until focused checks pass and known edits are finished;
|
|
37
48
|
do not remove it, substitute a tiny check for it, or claim an unrun requirement passed.
|
|
38
49
|
After a late fix, select checks for the affected inputs; repeat broad validation when the requested
|
|
@@ -46,11 +57,13 @@ required review, accepted criteria and cumulative budget intact; this workflow a
|
|
|
46
57
|
`;
|
|
47
58
|
/** Worker-only projection; planning/review authorities retain the complete shared workflow. */
|
|
48
59
|
export const WORKER_VALIDATION_WORKFLOW = `Batch edits, reconcile requirements/diff, run focused tests, then every registered formal check exactly in order:
|
|
49
|
-
separate foreground native shell calls
|
|
50
|
-
Rerun affected checks and required broad checks when contract/freshness requires; never drop required validation
|
|
60
|
+
separate foreground native shell calls; no tee/redirect/wrapper. Diagnostics lack formal evidence.
|
|
61
|
+
Rerun affected checks and required broad checks when contract/freshness requires; never drop required validation; no stale/unrun proof.
|
|
62
|
+
Check matched caller/output tests.
|
|
51
63
|
`;
|
|
52
64
|
/** Correction uses the inherited command identities; diagnostics do not acquire formal evidence. */
|
|
53
|
-
export const REVIEWER_VALIDATION_WORKFLOW =
|
|
65
|
+
export const REVIEWER_VALIDATION_WORKFLOW = `${VALIDATION_CLEANUP_ORDER}
|
|
66
|
+
Run inherited formal commands in order as exact separate foreground native shell calls.
|
|
54
67
|
Run formatting and diagnostics separately; do not append undeclared shell commands, tee, redirect or wrapper.
|
|
55
68
|
If a formal recipe is misregistered (for example a valid diagnostic intentionally exits nonzero), the active correction author can call sortie_v010_repair_review with reason, validation and optional validation_cwd to correct the recipe HERE. Preserve all original requirements and behavioral assertions; never suppress a real failure or register unconditional success. Run the newly registered checks before finishing; old outcomes are not proof for a changed recipe. Do not cancel, replace the Task or ask the controller to redispatch merely to fix check registration.`;
|
|
56
69
|
const OPERATION_GUIDE = `## Practical operation guide
|
|
@@ -183,14 +196,18 @@ ${MISSION_DEPENDENCY_WORKFLOW}
|
|
|
183
196
|
${profile.toolPrefix}plan_units with executor: "self", a concrete reason and one corrective unit.
|
|
184
197
|
Finish direct work with ${profile.toolPrefix}finish_direct_unit; its actual native checks are formal
|
|
185
198
|
evidence, with the same source freshness and Review requirements. Reviewer FINDINGS
|
|
186
|
-
|
|
187
|
-
|
|
199
|
+
can reuse ${profile.toolPrefix}repair_review to recover useful native Reviewer/context if it
|
|
200
|
+
returned before correction or was interrupted; another available Reviewer or plan_units Worker/direct
|
|
201
|
+
correction is also legitimate within existing user authorization. Retain findings and actual authorship; correct
|
|
188
202
|
all known Major/Medium defects and pass formal validation/requested commit, then call review_mission
|
|
189
203
|
only for legacy CORRECTION_READY-only fallback; normally that SAME author explicitly self-rechecks
|
|
190
204
|
after formal checks/commit within its correction Task, using candidate=current-validated for host binding.
|
|
191
205
|
Only concrete reachable Major risk remaining
|
|
192
206
|
after self-recheck requires a DIFFERENT Reviewer; Medium, tags, hashes and prose gaps alone do not;
|
|
193
|
-
|
|
207
|
+
they are not a failed-validation retry. A different Reviewer remains optional when useful, not forbidden.
|
|
208
|
+
Completed correction history never blocks plan_units for remaining authorized implementation or requires
|
|
209
|
+
acceptance first. No routine handoff approval, new conversation, rediscovery or unchanged checks.
|
|
210
|
+
Keep the SAME mission, original requirements, failure history
|
|
194
211
|
and cumulative budget. Use its Coordinator Task only for real coordination, contract discovery or
|
|
195
212
|
correction that cannot be handled directly. Never replace an active Worker or ask for routine approval.
|
|
196
213
|
4. After the review decision (including a justified low-risk skip), compare the completion candidate
|
|
@@ -262,16 +279,40 @@ existing user authorization and project gates; npm publication remains manual.
|
|
|
262
279
|
}
|
|
263
280
|
/** Keep representation oracles consistent in direct execution, Worker and Review. */
|
|
264
281
|
export const MISSION_REPRESENTATION_ORACLE = `Same-type representation, not name/visitor analogy; resolve conflicts.`;
|
|
282
|
+
/** Coordinator preserves source-backed return semantics in direct work or a Worker's objective. */
|
|
283
|
+
export const MISSION_RETURN_CONTRACT = `For a changed value-producing operation, derive its return contract from public callers and unchanged source/tests.
|
|
284
|
+
Preserve established return type/container, metadata and label alignment unless the original request changes them;
|
|
285
|
+
equal numeric values alone do not prove that contract. Trace which inputs determine result shape and labels,
|
|
286
|
+
including non-primary parameters; a scalar primary input need not yield a scalar result. For a mask or conditional
|
|
287
|
+
replacement, preserve established broadcasting and missing-value propagation; an unknown condition is not proof
|
|
288
|
+
that replacement is intended. Carry the affected contract into direct work or the Worker's objective.
|
|
289
|
+
Reuse an adequate focused assertion; add only the smallest source-backed regression when needed, not an input matrix,
|
|
290
|
+
another unit, validation lane or review.`;
|
|
291
|
+
/** Coordinator preserves source-backed mutation semantics in direct work or a Worker's objective. */
|
|
292
|
+
export const MISSION_MUTATION_CONTRACT = `For a changed mutating operation, derive its state and failure contract from public callers and unchanged source/tests.
|
|
293
|
+
Changing a file's write mechanism can change permission failures, link identity and new-file creation/umask behavior;
|
|
294
|
+
preserve those established outcomes unless the original request changes them. Derive regression expectations from
|
|
295
|
+
the original operation, not the new write mechanism. Carry the affected contract into direct work or the Worker's objective.
|
|
296
|
+
Reuse an adequate focused assertion; add only the smallest source-backed regression when needed, not an exhaustive
|
|
297
|
+
matrix, another unit, validation lane or review.`;
|
|
265
298
|
/** Coordinator authors and plans regressions without adding another validation/review lane. */
|
|
266
299
|
export const MISSION_REGRESSION_PLACEMENT = `Prefer an existing relevant test suite/subtest or fixture when it can express the regression assertion.
|
|
267
300
|
If a new test module is needed, prefer a distinctive behavior-specific name over automatically mirroring the implementation module.
|
|
268
301
|
Preserve established assertions and project test discovery. This is placement guidance, not another test, unit or review requirement.`;
|
|
302
|
+
/** Preserve explicit public behavior and its caller preconditions when removing passive effects. */
|
|
303
|
+
const MISSION_EXPLICIT_EFFECT_PRESERVATION = `When removing implicit initialization effects, preserve established explicit opt-in behavior unless the request changes it.
|
|
304
|
+
Trace its real caller-visible effect from existing source/tests; flags or internal state alone are not that behavior.
|
|
305
|
+
Keep the established caller preconditions in the regression check; added setup can supply the removed effect and mask a regression.
|
|
306
|
+
Reuse adequate checks and include this distinction in the current author's objective/check plan, not another unit or review round.`;
|
|
269
307
|
/** Shared by the installed Reviewer and its host-generated mission prompt. */
|
|
270
308
|
export const MISSION_BEHAVIOR_REVIEW = `Establish the test oracle independently of the patch: tests added with the implementation are claims to
|
|
271
309
|
review, not established API behavior. For a changed failure path, compare a pre-existing analogous public
|
|
272
310
|
test and its shared assertion helper, including default expected outputs, with the new case. A new test
|
|
273
311
|
that asserts the implementation's current result can encode the defect rather than catch it. Preserve
|
|
274
312
|
the pre-change contract unless the request changes it; do not invent a universal failure-result convention.
|
|
313
|
+
For changed observable behavior, inspect affected public caller assertions/output snapshots found by search, not only implementation-local fixtures.
|
|
314
|
+
Reconcile expected outputs with the original requirements and reuse adequate checks; no extra review round.
|
|
315
|
+
${MISSION_CLIENT_STATE_CHECK}
|
|
275
316
|
${MISSION_REPRESENTATION_ORACLE}
|
|
276
317
|
Trace a concrete rejected input through the changed code back to the public caller, checking result,
|
|
277
318
|
error and observable state together, including earlier results that can survive failure. Missing assertions
|
|
@@ -360,7 +401,10 @@ After current formal checks, retain the requested commit/clean boundary, then
|
|
|
360
401
|
${profile.toolPrefix}finish_direct_unit. Explicitly self-recheck and end this same native Task with
|
|
361
402
|
SELF_RECHECKED; only its actual successful terminal binds the current validated source. This is author
|
|
362
403
|
self-recheck, never independent approval of your own edits. No unresolved Medium may pass.
|
|
363
|
-
Do not edit before that host transition
|
|
404
|
+
Do not edit before that host transition. Reuse this context by default; the controller may choose another
|
|
405
|
+
available author or direct execution after terminal work without a handoff approval. Preserve all findings,
|
|
406
|
+
actual source authors, passed input-bound checks and cumulative spend; a new actor does not resolve defects.
|
|
407
|
+
If the host resumes this
|
|
364
408
|
session with an admitted correction unit, read its exact handoff and preserve its declared validation/commit
|
|
365
409
|
boundary. The inherited write list is an estimate, not a user prohibition. Concrete native edit paths are
|
|
366
410
|
reconciled automatically; for outputs whose paths cannot be inferred, call ${profile.toolPrefix}expand_unit
|
|
@@ -374,7 +418,8 @@ relevant impact IN THIS SAME TASK. Return SELF_RECHECKED with candidate=current-
|
|
|
374
418
|
the actual current source after this prompt's successful native terminal and fresh checks. Never copy a
|
|
375
419
|
pre-edit hash or return PASS for your own correction. Legacy CORRECTION_READY-only uses a separate same-author
|
|
376
420
|
read-only fallback, not acceptance. Only a concrete reachable Major risk remaining after self-recheck
|
|
377
|
-
requires a DIFFERENT Reviewer
|
|
421
|
+
requires a DIFFERENT Reviewer; independent review also remains optional when useful, not forbidden.
|
|
422
|
+
Known Major/Medium defects must be corrected; unresolved Medium cannot pass.
|
|
378
423
|
Tags, hashes, public-api/public-logic, missing prose and EVIDENCE_GAPS alone do not trigger a second review.
|
|
379
424
|
Self-recheck is not independent approval; root acceptance still compares the actual result with the request.
|
|
380
425
|
Otherwise return to the caller in the user's language.
|
|
@@ -483,7 +528,10 @@ If peer source/tests expose a plausible related still-unhandled error, probe its
|
|
|
483
528
|
before choosing the fix; reuse adequate checks. Include this in the current author's objective/check
|
|
484
529
|
plan, not another unit or review round. Do not invent an exhaustive error matrix.
|
|
485
530
|
${MISSION_REPRESENTATION_ORACLE}
|
|
531
|
+
${MISSION_RETURN_CONTRACT}
|
|
532
|
+
${MISSION_MUTATION_CONTRACT}
|
|
486
533
|
${MISSION_REGRESSION_PLACEMENT}
|
|
534
|
+
${MISSION_EXPLICIT_EFFECT_PRESERVATION}
|
|
487
535
|
For read-only verification, use write: []; do not invent an output file or request write access to inputs.
|
|
488
536
|
If declared build or tests create known generated paths, include those outputs in the initial write scope;
|
|
489
537
|
do not add a separate setup unit just to prepare them.
|
|
@@ -612,11 +660,11 @@ User missing-only: installed/incompatible is not missing.
|
|
|
612
660
|
Per-call modes: check retained creation/use for captured vs current settings.
|
|
613
661
|
Tests: existing suites/subtests or distinctive regression entry names.
|
|
614
662
|
${WORKER_VALIDATION_WORKFLOW}
|
|
615
|
-
|
|
663
|
+
No fake success.
|
|
616
664
|
Parent: independent Review after return, not before execution; no review-before-commit gate.
|
|
617
665
|
Do not spawn nested subagents, amend, push/publish. Return changes, command/exit/elapsed,
|
|
618
666
|
rerun reasons, unresolved/untested behavior; no proof doc.
|
|
619
|
-
No
|
|
667
|
+
No repeat denial. Unrecoverable PROCESS_DEFECT: local: + diagnostic or proven
|
|
620
668
|
TRUE_BLOCKER: external: / TRUE_BLOCKER: user-decision:.
|
|
621
669
|
Prose: user's latest instruction language (previous if unclear); protocol/code/quotes verbatim.
|
|
622
670
|
`;
|