sortie-dogs 0.12.13 → 0.12.14
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/operator-mission.js +2 -0
- package/dist/core/operator-runtime.d.ts +2 -0
- package/dist/core/operator-runtime.js +20 -0
- package/dist/plugin/mission-progress.d.ts +2 -1
- package/dist/plugin/mission-progress.js +28 -0
- package/dist/plugin/profiled.js +11 -0
- package/dist/plugin/v2.js +41 -9
- package/dist/runtime-mission-assets.js +5 -0
- 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.14-worker-context-progress-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.14-worker-context-progress-v1";
|
|
@@ -358,6 +358,8 @@ export function missionPacket(mission, run) {
|
|
|
358
358
|
...(run ? { run_id: run.runID, status: run.phase, decision: run.decision,
|
|
359
359
|
units: run.units.map(unit => ({ id: unit.unit.id, title: unit.unit.title, status: unit.status,
|
|
360
360
|
child_session_id: unit.childSessionID, result_class: unit.resultClass, evidence: unit.evidence,
|
|
361
|
+
handoff_path: unit.handoffPath, operation_manifest_path: unit.manifestPath,
|
|
362
|
+
scope_read: unit.unit.read, scope_write: unit.unit.write, validation: unit.unit.validation,
|
|
361
363
|
...(unit.dispatchDenial ? { dispatch_denial: unit.dispatchDenial } : {}) })) } : {}),
|
|
362
364
|
next_action: mission.phase === "completed" ? "Mission completed. Report the accepted result and retained review gaps; no further dispatch or completion call is needed."
|
|
363
365
|
: mission.phase === "submitted" && mission.submission?.status === "ready"
|
|
@@ -340,6 +340,8 @@ export declare class OperatorRuntime {
|
|
|
340
340
|
completionGoalFingerprint(state: OperatorState): Promise<string>;
|
|
341
341
|
verifyContinuityControls(state: OperatorState): Promise<void>;
|
|
342
342
|
packet(state: OperatorState): unknown;
|
|
343
|
+
/** Reconstruct the admitted child's instructions without trusting a lossy conversation summary. */
|
|
344
|
+
workerContext(root: string, child: string): Promise<string | undefined>;
|
|
343
345
|
continuationCheckpoint(root: string): Promise<string | undefined>;
|
|
344
346
|
private verifyControls;
|
|
345
347
|
/** Follow only the host's authorized parent-link repair; keep the durable control pin in sync. */
|
|
@@ -1919,6 +1919,26 @@ export class OperatorRuntime {
|
|
|
1919
1919
|
throw new Error("operator-packet-too-large-no-evidence-truncated");
|
|
1920
1920
|
return packet;
|
|
1921
1921
|
}
|
|
1922
|
+
/** Reconstruct the admitted child's instructions without trusting a lossy conversation summary. */
|
|
1923
|
+
async workerContext(root, child) {
|
|
1924
|
+
const state = await this.read(root);
|
|
1925
|
+
if (!state || state.phase !== "running")
|
|
1926
|
+
return undefined;
|
|
1927
|
+
const unit = state.units.find(item => item.childSessionID === child && item.status === "running");
|
|
1928
|
+
if (!unit)
|
|
1929
|
+
return undefined;
|
|
1930
|
+
// Keep this prefix stable across reads/edits: changing counters belong in status/tool results.
|
|
1931
|
+
return `SORTIE_WORKER_CONTEXT\n${JSON.stringify({ root_session_id: root, run_id: state.runID,
|
|
1932
|
+
unit_id: unit.unit.id, task_id: /^task_id: (.+)$/m.exec(unit.task.prompt)?.[1],
|
|
1933
|
+
project_root: this.projectRoot, handoff_path: unit.handoffPath, operation_manifest: unit.manifestPath,
|
|
1934
|
+
objective: unit.unit.objective, read: unit.unit.read, write: unit.unit.write,
|
|
1935
|
+
validation: unit.unit.validation, acceptance: state.acceptance,
|
|
1936
|
+
...(unit.repairValidation === null ? {} : { validation_only: true }),
|
|
1937
|
+
})}\nThis is the durable assignment for this same Worker, including after compaction or reload. ` +
|
|
1938
|
+
"A missing path in a summary does not mean the handoff is missing. Read the retained handoff/manifest and inspect the actual diff and outputs before claiming no edits or replaying work. " +
|
|
1939
|
+
`Use ${this.profile.toolPrefix}operator_status for observed validation and remaining work; do not repeat successful checks for an unchanged candidate. ` +
|
|
1940
|
+
"This context is an assignment, not proof of execution or acceptance.";
|
|
1941
|
+
}
|
|
1922
1942
|
async continuationCheckpoint(root) {
|
|
1923
1943
|
const state = await this.read(root);
|
|
1924
1944
|
const cancelledRemediation = state?.phase === "cancelled" &&
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
/** Display-only native Task progress. Never prompts a model or changes execution ownership. */
|
|
2
1
|
type Sink = (value: Record<string, unknown>) => Promise<void>;
|
|
3
2
|
export declare function bindMissionProgress(root: string, sink: Sink): () => void;
|
|
4
3
|
export declare function publishMissionProgress(root: string, value: Record<string, unknown>): Promise<void>;
|
|
4
|
+
/** Read durable transitions even when settlement ran in a different/reloaded plugin instance. */
|
|
5
|
+
export declare function missionProgressReader(directory: string, root: string, callID: string): () => Promise<Record<string, unknown> | undefined>;
|
|
5
6
|
export {};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/** Display-only native Task progress. Never prompts a model or changes execution ownership. */
|
|
2
|
+
import { OperatorMissionRuntime } from "../core/operator-mission.js";
|
|
3
|
+
import { OperatorRuntime } from "../core/operator-runtime.js";
|
|
4
|
+
import { V010_RUNTIME_PROFILE } from "../core/runtime-profile.js";
|
|
1
5
|
const sinks = new Map();
|
|
2
6
|
export function bindMissionProgress(root, sink) {
|
|
3
7
|
sinks.set(root, sink);
|
|
@@ -7,3 +11,27 @@ export function bindMissionProgress(root, sink) {
|
|
|
7
11
|
export async function publishMissionProgress(root, value) {
|
|
8
12
|
await sinks.get(root)?.(value).catch(() => undefined);
|
|
9
13
|
}
|
|
14
|
+
/** Read durable transitions even when settlement ran in a different/reloaded plugin instance. */
|
|
15
|
+
export function missionProgressReader(directory, root, callID) {
|
|
16
|
+
const missions = new OperatorMissionRuntime(directory, V010_RUNTIME_PROFILE);
|
|
17
|
+
return async () => {
|
|
18
|
+
const mission = await missions.read(root);
|
|
19
|
+
if (!mission || mission.callID !== callID)
|
|
20
|
+
return undefined;
|
|
21
|
+
// OperatorRuntime caches its own writes; a display observer must read a fresh disk snapshot.
|
|
22
|
+
const run = await new OperatorRuntime(directory, V010_RUNTIME_PROFILE).read(root);
|
|
23
|
+
const units = run?.runID === mission.runID ? run.units : [];
|
|
24
|
+
const running = units.find(unit => unit.status === "running");
|
|
25
|
+
const last = mission.progress.at(-1);
|
|
26
|
+
const status = running ? "running" : last?.status ?? mission.phase;
|
|
27
|
+
const title = running?.unit.title ?? last?.title ?? mission.requirements[0]?.text ?? "Coordinator";
|
|
28
|
+
return { description: `🐾 ${status}: ${title}`, sortie_progress: {
|
|
29
|
+
mission_id: mission.id, phase: mission.phase, unit: running ? `${run.runID}/${running.unit.id}` : last?.unit ?? null,
|
|
30
|
+
title, status, child_session_id: running?.childSessionID ?? null,
|
|
31
|
+
completed_units: units.filter(unit => unit.status === "succeeded").length,
|
|
32
|
+
failed_units: units.filter(unit => unit.status === "failed").length,
|
|
33
|
+
historical_failed_attempts: mission.progress.filter(unit => unit.status === "failed").length,
|
|
34
|
+
accepted: mission.phase === "completed",
|
|
35
|
+
} };
|
|
36
|
+
};
|
|
37
|
+
}
|
package/dist/plugin/profiled.js
CHANGED
|
@@ -2112,6 +2112,11 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2112
2112
|
(output.system ??= []).push(`SORTIE_RUNTIME_PROFILE ${profile.id}; marker ${assetVersion}. ` +
|
|
2113
2113
|
`Shared MkII protocol role names are logical: ${protocolMap}. Use only ${profile.toolPrefix} tools for this profile. ` +
|
|
2114
2114
|
"Never rewrite user acceptance or evidence to rename protocol roles. Final acceptance belongs only to the root coordinator.");
|
|
2115
|
+
if ((await identity(request.sessionID)).role === "dog-worker") {
|
|
2116
|
+
const context = await operators.workerContext(root, request.sessionID);
|
|
2117
|
+
if (context)
|
|
2118
|
+
(output.system ??= []).push(context);
|
|
2119
|
+
}
|
|
2115
2120
|
const proposal = await proposals.read(root);
|
|
2116
2121
|
if (proposal?.phase !== "approved" && proposal?.proposal_session_id === request.sessionID) {
|
|
2117
2122
|
// Only immutable identity and the frozen budget caps belong here. Consumed counters move with
|
|
@@ -2166,6 +2171,12 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
2166
2171
|
const root = await rootFor(request.sessionID);
|
|
2167
2172
|
if (!root)
|
|
2168
2173
|
return;
|
|
2174
|
+
if ((await identity(request.sessionID)).role === "dog-worker") {
|
|
2175
|
+
const context = await operators.workerContext(root, request.sessionID);
|
|
2176
|
+
if (context)
|
|
2177
|
+
(output.context ??= []).push(context +
|
|
2178
|
+
" Preserve the actual edits, tool outcomes and next action in the summary; do not replace them with an empty-work claim.");
|
|
2179
|
+
}
|
|
2169
2180
|
if ((await identity(request.sessionID)).role === "dog-operator") {
|
|
2170
2181
|
const mission = await missions.read(root);
|
|
2171
2182
|
if (mission?.coordinator === request.sessionID) {
|
package/dist/plugin/v2.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SortieDogsV010Plugin } from "./profiled.js";
|
|
2
|
-
import { bindMissionProgress } from "./mission-progress.js";
|
|
2
|
+
import { bindMissionProgress, missionProgressReader } from "./mission-progress.js";
|
|
3
3
|
import { owningServiceSessionList } from "./v2-session-history.js";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
@@ -332,18 +332,50 @@ async function registerV2Hooks(context, hooks) {
|
|
|
332
332
|
return execute(value, execution);
|
|
333
333
|
const report = execution.progress;
|
|
334
334
|
let metadata = {};
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
335
|
+
let pending = Promise.resolve();
|
|
336
|
+
const update = (update) => {
|
|
337
|
+
metadata = { ...metadata, ...update };
|
|
338
|
+
const snapshot = { ...metadata };
|
|
339
|
+
pending = pending.catch(() => undefined).then(() => report(snapshot));
|
|
340
|
+
return pending;
|
|
341
|
+
};
|
|
342
|
+
const unbind = bindMissionProgress(String(execution.sessionID), update);
|
|
343
|
+
const readProgress = missionProgressReader(context.location.directory, String(execution.sessionID), String(execution.id));
|
|
344
|
+
let previous = "", reading;
|
|
345
|
+
const refresh = () => {
|
|
346
|
+
if (reading)
|
|
347
|
+
return reading;
|
|
348
|
+
reading = (async () => {
|
|
349
|
+
try {
|
|
350
|
+
const progress = await readProgress(), key = JSON.stringify(progress);
|
|
351
|
+
if (progress && key !== previous) {
|
|
352
|
+
await update(progress);
|
|
353
|
+
previous = key;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
console.warn("[sortie-dogs-v010] mission progress unavailable", error instanceof Error ? error.message : "unknown");
|
|
358
|
+
}
|
|
359
|
+
})().finally(() => { reading = undefined; });
|
|
360
|
+
return reading;
|
|
361
|
+
};
|
|
362
|
+
// The native executor is a stable snapshot. Poll only local durable state, not models or
|
|
363
|
+
// session status APIs; this also recovers progress after another plugin instance settles work.
|
|
364
|
+
const timer = setInterval(() => { void refresh(); }, 1000);
|
|
365
|
+
timer.unref();
|
|
339
366
|
try {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
367
|
+
await refresh();
|
|
368
|
+
const result = await execute(value, { ...execution, progress: update });
|
|
369
|
+
await refresh();
|
|
370
|
+
await pending.catch(() => undefined);
|
|
371
|
+
// Native completion replaces metadata, so retain our display fields alongside its own.
|
|
372
|
+
return { ...result, metadata: { ...metadata, ...(record(result.metadata) ? result.metadata : {}) } };
|
|
344
373
|
}
|
|
345
374
|
finally {
|
|
375
|
+
clearInterval(timer);
|
|
346
376
|
unbind();
|
|
377
|
+
await reading;
|
|
378
|
+
await pending.catch(() => undefined);
|
|
347
379
|
}
|
|
348
380
|
};
|
|
349
381
|
});
|
|
@@ -117,6 +117,11 @@ You are Coordinator. Own most of the practical work and dispatch within the save
|
|
|
117
117
|
Read/search and confirmation shell commands are available; source edits belong to Worker. Do not edit
|
|
118
118
|
through shell. There is no proposal/approval/contract-repair round trip in this route.
|
|
119
119
|
|
|
120
|
+
For release/benchmark work, resolve the package from its release receipt and hash, not a matching version
|
|
121
|
+
or filename. Record the runner's own revision separately. Before repairing infrastructure on an old branch,
|
|
122
|
+
check current main for an existing fix; preserve local edits and use a current-main worktree when needed.
|
|
123
|
+
Report setup/route failures as such, with observed inference count, instead of calling runner exits a score.
|
|
124
|
+
|
|
120
125
|
Investigate only enough to start the first useful Worker. Prefer a targeted read/reproduction over a broad
|
|
121
126
|
inventory or speculative full design. Call ${profile.toolPrefix}plan_units with concise units:
|
|
122
127
|
title, objective, read/write file or directory scopes, validation commands, optionally requirement_ids.
|