sortie-dogs 0.12.18 → 0.12.19
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/dist/asset-version.d.ts +1 -1
- package/dist/asset-version.js +1 -1
- package/dist/core/contract-limits.d.ts +1 -1
- package/dist/core/contract-limits.js +1 -1
- package/dist/core/operator-mission.d.ts +1 -0
- package/dist/core/operator-mission.js +16 -9
- package/dist/plugin/mission-review.js +72 -15
- package/dist/plugin/profiled.js +18 -4
- package/dist/runtime-assets-v010.js +4 -5
- package/dist/runtime-assets.d.ts +1 -1
- package/dist/runtime-assets.js +2 -2
- package/dist/runtime-mission-assets.d.ts +2 -0
- package/dist/runtime-mission-assets.js +30 -10
- package/package.json +1 -1
package/dist/asset-version.d.ts
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* installed project marker without importing every asset body.
|
|
4
4
|
*/
|
|
5
5
|
export declare const RUNTIME_ASSET_VERSION = "0.3.89-completion-proof-v1";
|
|
6
|
-
export declare const V010_RUNTIME_ASSET_VERSION = "0.12.
|
|
6
|
+
export declare const V010_RUNTIME_ASSET_VERSION = "0.12.19-focused-behavior-review-v1";
|
|
7
7
|
export type RuntimeAssetVersion = typeof RUNTIME_ASSET_VERSION | typeof V010_RUNTIME_ASSET_VERSION;
|
package/dist/asset-version.js
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* installed project marker without importing every asset body.
|
|
4
4
|
*/
|
|
5
5
|
export const RUNTIME_ASSET_VERSION = "0.3.89-completion-proof-v1";
|
|
6
|
-
export const V010_RUNTIME_ASSET_VERSION = "0.12.
|
|
6
|
+
export const V010_RUNTIME_ASSET_VERSION = "0.12.19-focused-behavior-review-v1";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Common text bounds shared by handoff, manifest and goal evidence validation. */
|
|
2
|
-
export const CONTRACT_TEXT_LIMITS = Object.freeze({ title: 160, objective: 2000, statement: 1000, command:
|
|
2
|
+
export const CONTRACT_TEXT_LIMITS = Object.freeze({ title: 160, objective: 2000, statement: 1000, command: 8192, path: 512 });
|
|
@@ -130,6 +130,7 @@ export declare class OperatorMissionRuntime {
|
|
|
130
130
|
start(root: string, requirements: unknown, replaceRequirements?: boolean, options?: {
|
|
131
131
|
kind?: OperatorMission["kind"];
|
|
132
132
|
context?: MissionContext[];
|
|
133
|
+
cancelledRunID?: string;
|
|
133
134
|
}): Promise<OperatorMission>;
|
|
134
135
|
update(root: string, change: (state: OperatorMission) => void): Promise<OperatorMission>;
|
|
135
136
|
/** Keep host-accepted criteria ahead of new text, including an exactly linked settled predecessor. */
|
|
@@ -240,16 +240,19 @@ export class OperatorMissionRuntime {
|
|
|
240
240
|
}
|
|
241
241
|
if (previous)
|
|
242
242
|
await this.save(this.file(root, `.${previous.id}`), previous);
|
|
243
|
+
// A cancelled standalone/legacy run has no mission-owned runID. Only an explicit
|
|
244
|
+
// replacement may link it; normal continuation must not silently inherit its goal.
|
|
245
|
+
const predecessor = previous?.runID ?? previous?.supersededRunID ??
|
|
246
|
+
(replaceRequirements ? options.cancelledRunID : undefined);
|
|
243
247
|
const state = { version: "0.12", id: `mission-${randomUUID()}`, root, requests: [request],
|
|
244
248
|
kind: options.kind ?? "implementation",
|
|
245
249
|
context: (options.context ?? []).filter(item => item.id !== request.id),
|
|
246
250
|
requirements: requirements.map((text, index) => ({ id: `R${index + 1}`, text })), phase: "open",
|
|
247
251
|
...(replaceRequirements ? { requirementsReplaced: true } : {}),
|
|
248
252
|
coordinator: null, callID: null, dispatchOpen: false, runID: null, plans: 0, progress: [], submission: null,
|
|
249
|
-
...(previous
|
|
250
|
-
(previous
|
|
251
|
-
|
|
252
|
-
? { supersededRunID: (previous.runID ?? previous.supersededRunID) } : {}) };
|
|
253
|
+
...((previous === undefined || previous.phase === "cancelled") &&
|
|
254
|
+
(previous?.runID === null || previous === undefined || request.id !== previous.requests[0]?.id) && predecessor
|
|
255
|
+
? { supersededRunID: predecessor } : {}) };
|
|
253
256
|
await this.save(this.file(root), state);
|
|
254
257
|
return state;
|
|
255
258
|
});
|
|
@@ -356,17 +359,20 @@ export function missionPlan(mission, raw) {
|
|
|
356
359
|
throw new Error(`mission-unit-${index + 1}: ${field} must be paths`);
|
|
357
360
|
return [...new Set(entries.map(item => normalizeExecutionScope(item)))];
|
|
358
361
|
};
|
|
359
|
-
//
|
|
360
|
-
const ids = value.requirement_ids ?? (mission.requirements.length === 1 ?
|
|
362
|
+
// A sole unit owns the whole request. This schedules work; it does not prove acceptance.
|
|
363
|
+
const ids = value.requirement_ids ?? (raw.length === 1 || mission.requirements.length === 1 ? mission.requirements.map(item => item.id) : []);
|
|
361
364
|
if (!Array.isArray(ids) || ids.length === 0 || !ids.every(id => mission.requirements.some(item => item.id === id))) {
|
|
362
|
-
throw new Error(`mission-unit-${index + 1}: requirement_ids must name the related R IDs;
|
|
365
|
+
throw new Error(`mission-unit-${index + 1}: requirement_ids must name the related R IDs; splitting multiple requirements across units needs explicit coverage`);
|
|
363
366
|
}
|
|
364
367
|
if (!Array.isArray(value.validation) || value.validation.length === 0 ||
|
|
365
368
|
!value.validation.every(command => typeof command === "string" && command.trim())) {
|
|
366
369
|
throw new Error(`mission-unit-${index + 1}: validation must contain exact commands; final command proves the unit`);
|
|
367
370
|
}
|
|
371
|
+
const validation = value.validation.map(missionValidationCommand);
|
|
372
|
+
// Retain last occurrences so removing a redundant check preserves the final proof command.
|
|
368
373
|
return { id: `unit-${index + 1}`, title: line("title"), objective: line("objective"), read: paths("read"), write: paths("write"),
|
|
369
|
-
validation:
|
|
374
|
+
validation: validation.filter((command, i) => validation.lastIndexOf(command) === i),
|
|
375
|
+
acceptance_indices: [...new Set(ids.map(id => mission.requirements.findIndex(item => item.id === id)))] };
|
|
370
376
|
});
|
|
371
377
|
// The serial engine counts new proof milestones. Units sharing the same final suite are one
|
|
372
378
|
// milestone, so coalesce them instead of making the model repair a bookkeeping rejection.
|
|
@@ -462,7 +468,8 @@ export function missionReviewTraces(mission, raw) {
|
|
|
462
468
|
throw new Error("mission-review-traces: supply concise implementation/test traces");
|
|
463
469
|
}
|
|
464
470
|
const grouped = raw.map(text => ({ text,
|
|
465
|
-
ids:
|
|
471
|
+
ids: [...text.matchAll(/(?:^|[.;]\s+|[\r\n])\s*((?:R\d+\s*[/,]?\s*)+):/gu)]
|
|
472
|
+
.flatMap(match => match[1].match(/R\d+/gu) ?? []) }));
|
|
466
473
|
if (grouped.every(item => item.ids.length === 0) && raw.length === mission.requirements.length)
|
|
467
474
|
return raw;
|
|
468
475
|
const unknown = grouped.flatMap(item => item.ids).filter(id => !mission.requirements.some(requirement => requirement.id === id));
|
|
@@ -13,6 +13,40 @@ import { normalizeManifestScope } from "../core/path.js";
|
|
|
13
13
|
import { declaredArtifacts } from "./declared-artifacts.js";
|
|
14
14
|
const exec = promisify(execFile);
|
|
15
15
|
const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
16
|
+
/** Use the space left by short references for longer requested branches, without starving later references. */
|
|
17
|
+
function focusedAllowances(sizes, budget) {
|
|
18
|
+
const allowances = sizes.map(() => 0);
|
|
19
|
+
let remaining = budget;
|
|
20
|
+
let pending = sizes.map((_, index) => index);
|
|
21
|
+
while (pending.length && remaining > 0) {
|
|
22
|
+
const share = Math.floor(remaining / pending.length);
|
|
23
|
+
const complete = pending.filter(index => sizes[index] <= share);
|
|
24
|
+
if (!complete.length) {
|
|
25
|
+
for (const index of pending)
|
|
26
|
+
allowances[index] = share;
|
|
27
|
+
for (const index of pending.slice(0, remaining - share * pending.length))
|
|
28
|
+
allowances[index]++;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
for (const index of complete) {
|
|
32
|
+
allowances[index] = sizes[index];
|
|
33
|
+
remaining -= sizes[index];
|
|
34
|
+
}
|
|
35
|
+
pending = pending.filter(index => !complete.includes(index));
|
|
36
|
+
}
|
|
37
|
+
return allowances;
|
|
38
|
+
}
|
|
39
|
+
function visibleLineCount(lines, allowance) {
|
|
40
|
+
let bytes = 0, count = 0;
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
const size = Buffer.byteLength(line);
|
|
43
|
+
if (bytes + size > allowance)
|
|
44
|
+
break;
|
|
45
|
+
bytes += size;
|
|
46
|
+
count++;
|
|
47
|
+
}
|
|
48
|
+
return count;
|
|
49
|
+
}
|
|
16
50
|
export async function missionReviewBaseline(directory) {
|
|
17
51
|
try {
|
|
18
52
|
const { stdout } = await exec("git", ["rev-parse", "--verify", "HEAD^{commit}"], { cwd: directory });
|
|
@@ -99,7 +133,8 @@ export async function completedMissionReviewPrompts(mission, profile, root, requ
|
|
|
99
133
|
export async function missionReviewSource(directory, run, evidence = [], baseline, priorScope) {
|
|
100
134
|
const scope = missionReviewScope(priorScope, run);
|
|
101
135
|
const hash = createHash("sha256").update(JSON.stringify({ baseline, scope, units: run.units.map(unit => ({ unit: unit.unit, hashes: unit.hashes })) }));
|
|
102
|
-
|
|
136
|
+
const writes = [...new Set(scope.write.map(path => path === "." ? path : normalizeManifestScope(path).path))];
|
|
137
|
+
const focused = [];
|
|
103
138
|
for (const entry of evidence) {
|
|
104
139
|
const absolute = resolve(directory, entry.path);
|
|
105
140
|
const local = relative(resolve(directory), absolute);
|
|
@@ -125,21 +160,15 @@ export async function missionReviewSource(directory, run, evidence = [], baselin
|
|
|
125
160
|
stream.on("data", chunk => hash.update(chunk));
|
|
126
161
|
const lines = createInterface({ input: stream, crlfDelay: Infinity });
|
|
127
162
|
stream.on("error", error => lines.emit("error", error));
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const allowance = Math.floor(11_000 / evidence.length);
|
|
131
|
-
let number = 0, bytes = 0, truncated = false;
|
|
163
|
+
const excerpt = [];
|
|
164
|
+
let number = 0, bytes = 0;
|
|
132
165
|
try {
|
|
133
166
|
for await (const line of lines) {
|
|
134
167
|
number++;
|
|
135
168
|
if (number >= entry.offset && number < entry.offset + entry.limit) {
|
|
136
|
-
const text = `${number}: ${line.slice(0, 2_000)}\n
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
bytes += size;
|
|
140
|
-
}
|
|
141
|
-
else
|
|
142
|
-
truncated = true;
|
|
169
|
+
const text = `${number}: ${line.slice(0, 2_000)}\n`;
|
|
170
|
+
excerpt.push(text);
|
|
171
|
+
bytes += Buffer.byteLength(text);
|
|
143
172
|
}
|
|
144
173
|
}
|
|
145
174
|
}
|
|
@@ -149,14 +178,42 @@ export async function missionReviewSource(directory, run, evidence = [], baselin
|
|
|
149
178
|
}
|
|
150
179
|
if (entry.offset > number)
|
|
151
180
|
throw new Error(`offset ${entry.offset} exceeds ${number} lines; select existing lines`);
|
|
152
|
-
|
|
153
|
-
selected += `[FOCUSED EXCERPT TRUNCATED: ${entry.path}:${entry.offset}; request a smaller range]\n`;
|
|
181
|
+
focused.push({ entry, lines: excerpt, bytes });
|
|
154
182
|
}
|
|
155
183
|
catch (error) {
|
|
156
184
|
throw fail(error instanceof Error ? error.message : String(error));
|
|
157
185
|
}
|
|
158
186
|
}
|
|
159
|
-
|
|
187
|
+
// Keep room for the baseline diff. Reserve notices only after the allocated whole lines show
|
|
188
|
+
// truncation; pre-reserving every possible notice can hide all six otherwise fitting references.
|
|
189
|
+
const heading = (entry) => `\n--- evidence: ${entry.path}:${entry.offset} ---\n`;
|
|
190
|
+
const truncated = (entry) => `[FOCUSED EXCERPT TRUNCATED: ${entry.path}:${entry.offset}; request a smaller range]\n`;
|
|
191
|
+
// Read-only reviews retain their smaller existing envelope; code reviews may use the space
|
|
192
|
+
// previously reserved for automatic diff prefixes, while leaving room for changed-file context.
|
|
193
|
+
const limit = writes.length ? 18_000 : 11_000;
|
|
194
|
+
const headings = focused.reduce((size, { entry }) => size + Buffer.byteLength(heading(entry)), 0);
|
|
195
|
+
const needsNotice = focused.map(() => false);
|
|
196
|
+
let allowances;
|
|
197
|
+
while (true) {
|
|
198
|
+
const notices = focused.reduce((size, { entry }, index) => size + (needsNotice[index] ? Buffer.byteLength(truncated(entry)) : 0), 0);
|
|
199
|
+
allowances = focusedAllowances(focused.map(item => item.bytes), Math.max(0, limit - headings - notices));
|
|
200
|
+
let changed = false;
|
|
201
|
+
for (const [index, item] of focused.entries()) {
|
|
202
|
+
if (!needsNotice[index] && visibleLineCount(item.lines, allowances[index]) < item.lines.length) {
|
|
203
|
+
needsNotice[index] = true;
|
|
204
|
+
changed = true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (!changed)
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
let selected = "";
|
|
211
|
+
for (const [index, item] of focused.entries()) {
|
|
212
|
+
selected += heading(item.entry);
|
|
213
|
+
selected += item.lines.slice(0, visibleLineCount(item.lines, allowances[index])).join("");
|
|
214
|
+
if (needsNotice[index])
|
|
215
|
+
selected += truncated(item.entry);
|
|
216
|
+
}
|
|
160
217
|
if (writes.length === 0)
|
|
161
218
|
return { fingerprint: `sha256:${hash.digest("hex")}`,
|
|
162
219
|
excerpt: selected + "[Read-only units: no declared output files. Review the supplied observations, traces and validation evidence.]" };
|
package/dist/plugin/profiled.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { V010_RUNTIME_ASSET_VERSION } from "../asset-version.js";
|
|
2
|
+
import { MISSION_BEHAVIOR_REVIEW } from "../runtime-mission-assets.js";
|
|
2
3
|
import { cancelledMissionRetainsAcceptance, OperatorContractError, OperatorRuntime } from "../core/operator-runtime.js";
|
|
3
4
|
import { DEFAULT_OPERATOR_PROPOSAL_BUDGET, OPERATOR_APPROVAL_CONTRACT, OPERATOR_PROPOSAL_BUDGET_CAPS, OPERATOR_PROPOSAL_REVISION_CONTRACT, OperatorProposalBudgetError, OperatorProposalRuntime } from "../core/operator-proposal.js";
|
|
4
5
|
import { CANONICAL_AGENT_ROLES, canonicalAgent, profileAgent, profileTool, V010_RUNTIME_PROFILE } from "../core/runtime-profile.js";
|
|
@@ -561,7 +562,9 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
561
562
|
// Only the same source can retain a cancelled run's acceptance as a prefix.
|
|
562
563
|
if (previous.sourceRefs[0] !== `user:${mission.requests[0]?.id}` ||
|
|
563
564
|
!previous.sourceRefs.every(ref => mission.requests.some(request => ref === `user:${request.id}`))) {
|
|
564
|
-
throw new Error("mission-cancelled-source-unproven"
|
|
565
|
+
throw new Error("mission-cancelled-source-unproven: the cancelled run's source_refs do not prove this is the same request. " +
|
|
566
|
+
"If the user changed or narrowed the goal, start_mission with intent=replace and the complete current requirements; " +
|
|
567
|
+
"otherwise preserve the earlier accepted criteria and establish the original source before continuing.");
|
|
565
568
|
}
|
|
566
569
|
return previous.acceptance.every((text, index) => mission.requirements[index]?.text === text)
|
|
567
570
|
? mission : missions.carryForward(root, mission.id, previous.acceptance);
|
|
@@ -1355,9 +1358,11 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1355
1358
|
if (relocated)
|
|
1356
1359
|
return JSON.stringify({ ...relocated, budget: await control.currentBudget(context.sessionID) });
|
|
1357
1360
|
}
|
|
1361
|
+
const prior = await operators.read(context.sessionID);
|
|
1358
1362
|
let mission = await retainCancelledMissionAcceptance(context.sessionID, await missions.start(context.sessionID, args.requirements, args.intent === "replace" || args.intent === "new", {
|
|
1359
1363
|
kind: args.kind === "operation" ? "operation" : "implementation",
|
|
1360
1364
|
context: missionConversationContext(await messages(context.sessionID)),
|
|
1365
|
+
...(args.intent === "replace" && prior?.phase === "cancelled" ? { cancelledRunID: prior.runID } : {}),
|
|
1361
1366
|
}));
|
|
1362
1367
|
if (!mission.reviewBaseline) {
|
|
1363
1368
|
const baseline = await missionReviewBaseline(input.directory);
|
|
@@ -1454,13 +1459,21 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1454
1459
|
args: { units: { type: "array", minItems: 1, maxItems: 32, items: { type: "object", additionalProperties: false,
|
|
1455
1460
|
properties: { title: { type: "string" }, objective: { type: "string" },
|
|
1456
1461
|
read: { ...stringList, description: "Inputs that affect validation, not an allowlist for observation. Do not include whole live session/database/log trees just to inspect them." }, write: stringList,
|
|
1457
|
-
validation: stringList, requirement_ids: stringList }, required: ["title", "objective", "write", "validation"] } },
|
|
1462
|
+
validation: stringList, requirement_ids: { ...stringList, description: "Related requirement IDs. A single unit inherits all requirements when omitted; specify coverage when splitting work across units." } }, required: ["title", "objective", "write", "validation"] } },
|
|
1458
1463
|
execution: { type: "object", properties: { commands: stringList, directory: { type: "string" } },
|
|
1459
1464
|
required: ["commands", "directory"], additionalProperties: false,
|
|
1460
1465
|
description: "For an operation: the actual run/grade commands, not a preflight or NO_START check. Host observes their native shell completion; no handwritten proof file is needed.", "x-sortie-optional": true },
|
|
1461
1466
|
reason: { type: "string", "x-sortie-optional": true } }, execute: async (args, context) => {
|
|
1462
1467
|
const { root, mission } = await missionAuthority(context.sessionID);
|
|
1463
|
-
|
|
1468
|
+
try {
|
|
1469
|
+
return await serializeDispatchTransition(root, () => declareMissionUnits(root, context.sessionID, mission, args.units, args.reason, args.execution));
|
|
1470
|
+
}
|
|
1471
|
+
catch (error) {
|
|
1472
|
+
if (!(error instanceof OperatorContractError))
|
|
1473
|
+
throw error;
|
|
1474
|
+
return JSON.stringify({ status: "invalid-plan", diagnostics: error.diagnostics, diagnostics_truncated: error.diagnostics_truncated,
|
|
1475
|
+
next_action: "Correct the reported field or control-storage problem and retry plan_units directly. Keep the original requirements and existing run; do not cancel or repeat passed work to repair the plan." });
|
|
1476
|
+
}
|
|
1464
1477
|
} };
|
|
1465
1478
|
tools[expandUnit] = { description: "Coordinator: extend the stopped unit's write scope immediately within the original request. Keeps original requirements and cumulative budget; generates a replacement Worker contract. No Operator approval or handwritten manifest repair is needed. Use only after the Worker has returned.",
|
|
1466
1479
|
args: { unit_id: stringSchema, paths: stringList, reason: stringSchema }, execute: async (args, context) => {
|
|
@@ -1517,9 +1530,10 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
1517
1530
|
description: `🔎 ${run.units[0].unit.title}`, prompt: [
|
|
1518
1531
|
`candidate_id: ${mission.id}`, `review_phase: ${phase}`, "canonical_validation_exit: 0", `risk_tags: [${risk.join(", ")}]`,
|
|
1519
1532
|
"Review this candidate independently. Use the language of the requirements/traces. Invoke no tools. First line: exactly PASS, FINDINGS or EVIDENCE_GAPS.",
|
|
1520
|
-
"Use EVIDENCE_GAPS only when no concrete source/test defect is established and a specific acceptance-relevant behavior or required validation cannot be settled by the supplied artifact. Name the affected path and why the missing evidence matters; do not request a generic route inventory
|
|
1533
|
+
"Use EVIDENCE_GAPS only when no concrete source/test defect is established and a specific acceptance-relevant behavior or required validation cannot be settled by the supplied artifact. Name the affected path and why the missing evidence matters; do not request a generic route inventory. Any concrete defect uses FINDINGS.",
|
|
1521
1534
|
"This Reviewer's native outcome and final acceptance can only be observed after this review. List those as deferred Operator checks, not as a reason to request another review. Still assess all available source, validation and historical evidence independently.",
|
|
1522
1535
|
"For changed failure paths, assess the public return value, error and post-failure state together against existing API behavior; matching error text alone does not establish compatibility.",
|
|
1536
|
+
MISSION_BEHAVIOR_REVIEW,
|
|
1523
1537
|
`acceptance: ${JSON.stringify(run.acceptance)}`, `changedLogicSummary: ${JSON.stringify(traces)}`,
|
|
1524
1538
|
...run.acceptance.map((_, i) => `acceptance[${i}] -> changedLogicSummary[${i}]`),
|
|
1525
1539
|
`manifest: ${JSON.stringify(run.units.map(unit => unit.unit))}`, `sourceFingerprint: ${source.fingerprint}`,
|
|
@@ -4,7 +4,7 @@ import { V010_RUNTIME_PROFILE as profile, profileAgent, renderProfileInstruction
|
|
|
4
4
|
import { GOAL_DECLARATION_FORMAT } from "./core/goal-declaration-format.js";
|
|
5
5
|
import { STRATEGY_TRIGGERS, SOURCE_REVIEW_PHASES, SOURCE_REVIEW_RISK_TAGS } from "./core/consultation.js";
|
|
6
6
|
import { SCOUT_EVIDENCE_CODES } from "./core/scout-contract.js";
|
|
7
|
-
import { missionOperatorContent, missionCoordinatorContent, missionWorkerContent } from "./runtime-mission-assets.js";
|
|
7
|
+
import { MISSION_BEHAVIOR_REVIEW, missionOperatorContent, missionCoordinatorContent, missionWorkerContent } from "./runtime-mission-assets.js";
|
|
8
8
|
const coordinator = profileAgent(profile, "dog-coordinator");
|
|
9
9
|
const operator = profileAgent(profile, "dog-operator");
|
|
10
10
|
const worker = profileAgent(profile, "dog-worker");
|
|
@@ -420,10 +420,9 @@ For a multi-target change, verify each affected target when the source shows ind
|
|
|
420
420
|
|
|
421
421
|
Do not demand a generic creation/binding/mutation inventory, every possible value representation, or a
|
|
422
422
|
cross-product of independent dimensions just because the construct already exists. Absence of that
|
|
423
|
-
inventory alone is not an evidence gap.
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
required behavioral result or canonical validation evidence.
|
|
423
|
+
inventory alone is not an evidence gap.
|
|
424
|
+
|
|
425
|
+
${MISSION_BEHAVIOR_REVIEW}
|
|
427
426
|
|
|
428
427
|
## Mission review verdict
|
|
429
428
|
|
package/dist/runtime-assets.d.ts
CHANGED
|
@@ -1514,7 +1514,7 @@ END_INTERNAL_TERMINAL_PROOF_FIXTURE
|
|
|
1514
1514
|
readonly name: "dog-reviewer";
|
|
1515
1515
|
readonly version: "0.3.89-completion-proof-v1";
|
|
1516
1516
|
readonly installPath: "agent/dog-reviewer.md";
|
|
1517
|
-
readonly content: "---\ndescription: Independent source reviewer for dog-coordinator\nmode: subagent\npermission:\n bash: deny\n webfetch: deny\n task: deny\n question: deny\n glob: deny\n grep: deny\n edit: deny\n list: deny\n write: deny\n patch: deny\n read: deny\ntools:\n bash: false\n webfetch: false\n task: false\n question: false\n glob: false\n grep: false\n edit: false\n list: false\n write: false\n patch: false\n read: false\n---\n# dog-reviewer\n\nAccept only one bounded SourceReview request from dog-coordinator after canonical\nvalidation for one high-risk candidate. Review only the supplied acceptance criteria, exact\nmanifest, changedLogicSummary, supplied changed-code excerpts, and validation evidence. Confirm every acceptance item explicitly\nmaps to at least one changedLogicSummary entry and assess that changed logic against the mapped\nacceptance item. Missing
|
|
1517
|
+
readonly content: "---\ndescription: Independent source reviewer for dog-coordinator\nmode: subagent\npermission:\n bash: deny\n webfetch: deny\n task: deny\n question: deny\n glob: deny\n grep: deny\n edit: deny\n list: deny\n write: deny\n patch: deny\n read: deny\ntools:\n bash: false\n webfetch: false\n task: false\n question: false\n glob: false\n grep: false\n edit: false\n list: false\n write: false\n patch: false\n read: false\n---\n# dog-reviewer\n\nAccept only one bounded SourceReview request from dog-coordinator after canonical\nvalidation for one high-risk candidate. Review only the supplied acceptance criteria, exact\nmanifest, changedLogicSummary, supplied changed-code excerpts, and validation evidence. Confirm every acceptance item explicitly\nmaps to at least one changedLogicSummary entry and assess that changed logic against the mapped\nacceptance item. Missing behavioral evidence is an evidence gap; a demonstrated source/test defect is a finding.\nRequire one indexed acceptance[i] -> changedLogicSummary[j] mapping line per acceptance item and\nreject a missing index or unequal mapping count before assessing the changed logic.\nFor behavioral acceptance items, require a concrete exercising test/input/branch and result. A broad\nsuite PASS without criterion-level exercise evidence is insufficient. When one item contains materially\ndifferent syntax forms, value shapes, scopes, or error paths, reject PASS unless representative traces cover\neach path or the artifact proves they share one implementation path.\nCheck contract-derived expectations only for accepted behavior. For an applicable failure or composite-value\ncriterion, error-only or helper-only assertions can leave public result/state behavior unproved. Accept justified\nN/A dimensions; do not demand new behavior, new review rounds, or redundant checks outside accepted scope.\nWhen changed files include generator inputs or checked-in generated outputs, require the canonical generator\ncommand, a stable post-generation diff, and validation executed after generation. Reject PASS if helper logic\nexists only in a generated output, regeneration removes behavior, or validation predates the generated candidate.\nDo not request raw logs or full source files, review low-risk candidates, expand scope, or dispatch\nanother agent.\nTreat those supplied fields as the complete bounded SourceReview artifact; use only that artifact and invoke no tools.\nDo not infer that a branch or exemption is absent from source because a prose summary omits it.\nIf the supplied excerpts do not establish a claim, report an evidence gap and request the exact\nbranch/helper excerpt in the next artifact; do not prescribe a source fix for an unproven defect.\n\nReturn one concise PASS or concrete-finding response only to dog-coordinator before the\ncoordinator commit. Write every finding, evidence, and required-fix sentence in the language the\nsupplied artifact uses for its own prose, one statement per line, and keep verdict values,\nidentifiers, paths, and commands verbatim. Do not implement, remediate, resolve blockers, edit,\nstage, commit, or become user-facing. Remain host-routed: do not require or identify a provider, vendor, model, variant,\nor transport.\n";
|
|
1518
1518
|
}, {
|
|
1519
1519
|
readonly name: "dog-advisor";
|
|
1520
1520
|
readonly version: "0.3.89-completion-proof-v1";
|
package/dist/runtime-assets.js
CHANGED
|
@@ -1824,10 +1824,10 @@ Accept only one bounded SourceReview request from dog-coordinator after canonica
|
|
|
1824
1824
|
validation for one high-risk candidate. Review only the supplied acceptance criteria, exact
|
|
1825
1825
|
manifest, changedLogicSummary, supplied changed-code excerpts, and validation evidence. Confirm every acceptance item explicitly
|
|
1826
1826
|
maps to at least one changedLogicSummary entry and assess that changed logic against the mapped
|
|
1827
|
-
acceptance item. Missing
|
|
1827
|
+
acceptance item. Missing behavioral evidence is an evidence gap; a demonstrated source/test defect is a finding.
|
|
1828
1828
|
Require one indexed acceptance[i] -> changedLogicSummary[j] mapping line per acceptance item and
|
|
1829
1829
|
reject a missing index or unequal mapping count before assessing the changed logic.
|
|
1830
|
-
|
|
1830
|
+
For behavioral acceptance items, require a concrete exercising test/input/branch and result. A broad
|
|
1831
1831
|
suite PASS without criterion-level exercise evidence is insufficient. When one item contains materially
|
|
1832
1832
|
different syntax forms, value shapes, scopes, or error paths, reject PASS unless representative traces cover
|
|
1833
1833
|
each path or the artifact proves they share one implementation path.
|
|
@@ -2,5 +2,7 @@ import { type RuntimeProfile } from "./core/runtime-profile.ts";
|
|
|
2
2
|
/** Repository-local dependency environment shared by all units; excluded from reviewed and captured source. */
|
|
3
3
|
export declare const TOOL_ENVIRONMENT = ".sortie-env";
|
|
4
4
|
export declare function missionOperatorContent(profile: RuntimeProfile, version: string): string;
|
|
5
|
+
/** Shared by the installed Reviewer and its host-generated mission prompt. */
|
|
6
|
+
export declare const MISSION_BEHAVIOR_REVIEW = "For 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 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\nBehavioral requirements need concrete input/result evidence. For incidental workflow constraints such as\ncache settings or command-path spelling, use the existing host observations and concise compliance trace;\nabsence of a separate settings dump or historical log is not itself an evidence gap. Flag observed\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.";
|
|
5
7
|
export declare function missionCoordinatorContent(profile: RuntimeProfile, version: string): string;
|
|
6
8
|
export declare function missionWorkerContent(profile: RuntimeProfile): string;
|
|
@@ -81,7 +81,8 @@ results to guide the following units. Do not invent preparation units or plan-ap
|
|
|
81
81
|
For operations, plan_units.execution names the actual run/grade commands and working directory. Keep
|
|
82
82
|
setup, execution and result collection in the same Worker. The host records native execution; NO_START
|
|
83
83
|
or setup success cannot complete the operation. Reward/score zero is a result, not failure to execute.
|
|
84
|
-
Use requirement_ids
|
|
84
|
+
Use requirement_ids when splitting multiple requirements across units; a single unit inherits all requirements
|
|
85
|
+
when they are omitted. These are related requirements,
|
|
85
86
|
not claims that a command proves every semantic obligation. Compare the final result yourself.
|
|
86
87
|
|
|
87
88
|
Copy returned task fields exactly (V2: subagent_type -> agent, task_id -> sessionID). Do not append to a
|
|
@@ -101,6 +102,19 @@ once. Do not invent scores, medals, costs, savings, models or successful checks.
|
|
|
101
102
|
existing user authorization and project gates; npm publication remains manual.
|
|
102
103
|
`;
|
|
103
104
|
}
|
|
105
|
+
/** Shared by the installed Reviewer and its host-generated mission prompt. */
|
|
106
|
+
export const MISSION_BEHAVIOR_REVIEW = `For a changed failure handler, inspect the operation it calls and the public inputs reaching it,
|
|
107
|
+
including failures not listed in the new handler. Use the supplied source/tests and established API behavior
|
|
108
|
+
to identify a concrete input that could still violate the requested contract. A passing normal input does
|
|
109
|
+
not settle a different failure outcome of that same operation. A demonstrable defect is FINDINGS; ask for
|
|
110
|
+
an excerpt or result only when a specific material outcome cannot be settled. Do not invent new behavior,
|
|
111
|
+
require an exhaustive exception inventory, or recommend catching every exception.
|
|
112
|
+
|
|
113
|
+
Behavioral requirements need concrete input/result evidence. For incidental workflow constraints such as
|
|
114
|
+
cache settings or command-path spelling, use the existing host observations and concise compliance trace;
|
|
115
|
+
absence of a separate settings dump or historical log is not itself an evidence gap. Flag observed
|
|
116
|
+
contradictions. The Operator owns final comparison with the original request. If a missing check genuinely
|
|
117
|
+
affects correctness or a requested deliverable, name that consequence and the smallest useful next check.`;
|
|
104
118
|
export function missionCoordinatorContent(profile, version) {
|
|
105
119
|
return `---
|
|
106
120
|
description: Sortie-dogs ${version} Coordinator — investigation, unit dispatch, scope extension and correction loop.
|
|
@@ -144,7 +158,8 @@ select the matching runner/profile before starting rather than changing the pinn
|
|
|
144
158
|
Investigate only enough to start the first useful Worker. Prefer a targeted read/reproduction over a broad
|
|
145
159
|
inventory or speculative full design. Call ${profile.toolPrefix}plan_units with concise units:
|
|
146
160
|
title, objective, read/write file or directory scopes, validation commands, and related requirement_ids
|
|
147
|
-
when
|
|
161
|
+
when splitting multiple requirements across multiple units; a single unit inherits all requirements when
|
|
162
|
+
requirement_ids is omitted. For operation missions, include execution with the actual
|
|
148
163
|
run/grade commands and working directory. Setup, launch and result collection normally stay in one Worker;
|
|
149
164
|
do not forbid execution while assigning that Worker the requirement to execute.
|
|
150
165
|
When the issue includes a concrete public reproduction, pass its entrypoint, relevant input and observed
|
|
@@ -153,7 +168,9 @@ example depends on a working directory or package layout, preserve that context.
|
|
|
153
168
|
existing analogous source/tests for the expected contract when available. Avoid separate investigation
|
|
154
169
|
units just to restate the issue. A test of a neighboring name is not an adjacent check unless it runs
|
|
155
170
|
the changed branch on a relevant different input; keep validation focused and do not require an extra
|
|
156
|
-
test when the existing checks already exercise that boundary.
|
|
171
|
+
test when the existing checks already exercise that boundary. For an exception fix, identify the failing
|
|
172
|
+
operation and ask the Worker to consider its other source/API-backed failure inputs, including ones the
|
|
173
|
+
new handler does not catch. A normal input alone does not check a different failure outcome.
|
|
157
174
|
For read-only verification, use write: []; do not invent an output file or request write access to inputs.
|
|
158
175
|
For ordinary diagnostics, use native read/search/shell directly, including while an old run is being
|
|
159
176
|
reconciled. Do not create a dummy validation/console.log unit just to inspect status. The read list is
|
|
@@ -164,7 +181,7 @@ Use absolute native paths for requested global installations or other external o
|
|
|
164
181
|
a directory including a not-yet-created tree. These are execution/evidence scopes, not an additional
|
|
165
182
|
permission grant: the host's native permissions still apply. Include the actual external input/output
|
|
166
183
|
paths in read/write so validation and review observe them; do not substitute a repository symlink.
|
|
167
|
-
Keep all original requirements covered
|
|
184
|
+
Keep all original requirements covered. Last validation command checks
|
|
168
185
|
that unit. If your quick check shows repository-declared dependencies or the test runner are missing, keep
|
|
169
186
|
setup inside the first unit: declare its checks through the repository-local tool environment ${TOOL_ENVIRONMENT}/
|
|
170
187
|
(for Python, ${TOOL_ENVIRONMENT}/bin/python -m pytest ...) and let that Worker create it. Never plan a separate setup
|
|
@@ -198,7 +215,8 @@ and ask a bounded question in the user's language; do not send generic explorato
|
|
|
198
215
|
If the user explicitly requested Advisor input before a decision, do not treat it as optional.
|
|
199
216
|
|
|
200
217
|
After formal validation, call review_mission with risk_tags and one concise implementation/test trace per
|
|
201
|
-
requirement.
|
|
218
|
+
requirement. For changed failure behavior, connect the operation and concrete input to the contract-derived
|
|
219
|
+
expected result and observed result in those existing traces. Include required behavioral checks, not a speculative route inventory
|
|
202
220
|
or raw history to prove incidental process constraints. Recognized tags: ${SOURCE_REVIEW_RISK_TAGS.join(", ")}.
|
|
203
221
|
High-risk changes require the generated independent ${profileAgent(profile, "dog-reviewer")} task.
|
|
204
222
|
Low risk uses [] and the host records the skip. The host supplies source excerpts, manifest, requirement
|
|
@@ -253,11 +271,13 @@ formal acceptance evidence. Do not repeat a failed command without a concrete so
|
|
|
253
271
|
repeat passed checks on unchanged source. Add meaningful tests only when needed by the change/request.
|
|
254
272
|
For a reported bug, keep the public reproduction's entrypoint, input and layout intact during diagnosis;
|
|
255
273
|
after a fix, run it again when the available environment permits. If it cannot run, report exactly
|
|
256
|
-
what remains unverified instead of substituting a different passing check.
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
274
|
+
what remains unverified instead of substituting a different passing check. For a changed condition or
|
|
275
|
+
exception handler, inspect the underlying operation and inputs reaching it, including failures the new
|
|
276
|
+
handler does not catch. Check a materially different failure input when public source/tests or established
|
|
277
|
+
API behavior support the same requested contract; a normal input alone does not check that failure outcome.
|
|
278
|
+
Choose the smallest complete fix, not a catch-all or an exhaustive exception matrix. Derive expected behavior
|
|
279
|
+
from public code and tests, not hidden evaluator details; skip redundant checks already covered by formal validation.
|
|
280
|
+
Return a concrete failed reproduction to Coordinator for
|
|
261
281
|
the same-goal correction loop rather than declaring the whole task complete.
|
|
262
282
|
When changing a failure path, check its public return value, error and post-failure state together against
|
|
263
283
|
the existing API contract; do not stop assertions after matching error text.
|