@llblab/pi-actors 0.55.0 → 0.56.1
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/AGENTS.md +108 -20
- package/BACKLOG.md +198 -4
- package/CHANGELOG.md +17 -0
- package/README.md +31 -1
- package/dist/index.js +1 -1
- package/dist/lib/async-runs.d.ts +37 -0
- package/dist/lib/async-runs.js +131 -62
- package/dist/lib/automatic-review-runtime.d.ts +2 -0
- package/dist/lib/automatic-review-runtime.js +3 -2
- package/dist/lib/command-templates.d.ts +37 -0
- package/dist/lib/command-templates.js +263 -129
- package/dist/lib/execution-files.d.ts +32 -0
- package/dist/lib/execution-files.js +128 -0
- package/dist/lib/execution-output.js +5 -4
- package/dist/lib/execution-sessions.d.ts +19 -1
- package/dist/lib/execution-sessions.js +62 -26
- package/dist/lib/execution.d.ts +4 -1
- package/dist/lib/execution.js +6 -1
- package/dist/lib/extension-runtime.d.ts +9 -2
- package/dist/lib/extension-runtime.js +92 -14
- package/dist/lib/file-state.js +21 -2
- package/dist/lib/inspector-command.js +2 -2
- package/dist/lib/inspector-overlay.d.ts +25 -7
- package/dist/lib/inspector-overlay.js +562 -262
- package/dist/lib/inspector.d.ts +20 -10
- package/dist/lib/inspector.js +80 -91
- package/dist/lib/limits.d.ts +1 -0
- package/dist/lib/limits.js +1 -0
- package/dist/lib/observability.d.ts +15 -1
- package/dist/lib/observability.js +216 -99
- package/dist/lib/pi.d.ts +5 -4
- package/dist/lib/pi.js +64 -10
- package/dist/lib/recipe-projection.d.ts +18 -0
- package/dist/lib/recipe-projection.js +220 -0
- package/dist/lib/recipes-context.d.ts +2 -0
- package/dist/lib/recipes-context.js +30 -6
- package/dist/lib/registry.js +280 -36
- package/dist/lib/run-delivery.d.ts +213 -5
- package/dist/lib/run-delivery.js +1909 -40
- package/dist/lib/run-supervision.d.ts +107 -0
- package/dist/lib/run-supervision.js +412 -0
- package/dist/lib/run-ui-runtime.d.ts +9 -2
- package/dist/lib/run-ui-runtime.js +283 -60
- package/dist/lib/runs-artifacts.d.ts +26 -1
- package/dist/lib/runs-artifacts.js +68 -2
- package/dist/lib/runs-context-exports.d.ts +451 -0
- package/dist/lib/runs-context-exports.js +2315 -0
- package/dist/lib/runs-context-index.d.ts +97 -0
- package/dist/lib/runs-context-index.js +368 -0
- package/dist/lib/runs-control-delivery.js +46 -7
- package/dist/lib/runs-control.d.ts +78 -2
- package/dist/lib/runs-control.js +334 -2
- package/dist/lib/runs-controls.js +4 -1
- package/dist/lib/runs-descendant-launches.d.ts +80 -0
- package/dist/lib/runs-descendant-launches.js +287 -0
- package/dist/lib/runs-execution-evidence.d.ts +110 -0
- package/dist/lib/runs-execution-evidence.js +282 -0
- package/dist/lib/runs-index.d.ts +66 -1
- package/dist/lib/runs-index.js +349 -13
- package/dist/lib/runs-native-launches.d.ts +73 -0
- package/dist/lib/runs-native-launches.js +227 -0
- package/dist/lib/runs-outcomes.d.ts +141 -0
- package/dist/lib/runs-outcomes.js +292 -0
- package/dist/lib/runs-ownership.d.ts +10 -1
- package/dist/lib/runs-ownership.js +36 -4
- package/dist/lib/runs-process-windows-mi.d.ts +46 -0
- package/dist/lib/runs-process-windows-mi.js +114 -0
- package/dist/lib/runs-process.d.ts +34 -1
- package/dist/lib/runs-process.js +158 -26
- package/dist/lib/runs-results.d.ts +116 -0
- package/dist/lib/runs-results.js +518 -0
- package/dist/lib/runs-retention.d.ts +15 -2
- package/dist/lib/runs-retention.js +148 -9
- package/dist/lib/runs-session-exports.d.ts +95 -0
- package/dist/lib/runs-session-exports.js +470 -0
- package/dist/lib/runs-snapshot.d.ts +58 -0
- package/dist/lib/runs-snapshot.js +92 -0
- package/dist/lib/runs-start.d.ts +2 -0
- package/dist/lib/runs-start.js +44 -3
- package/dist/lib/runs-status.d.ts +15 -1
- package/dist/lib/runs-status.js +337 -13
- package/dist/lib/runs-supervision.d.ts +105 -0
- package/dist/lib/runs-supervision.js +501 -0
- package/dist/lib/runs-trace.d.ts +1 -0
- package/dist/lib/runs-trace.js +14 -3
- package/dist/lib/runtime.js +22 -3
- package/dist/lib/session-evidence.d.ts +37 -0
- package/dist/lib/session-evidence.js +59 -3
- package/dist/lib/state-readers.d.ts +4 -1
- package/dist/lib/state-readers.js +14 -8
- package/dist/lib/temp.d.ts +2 -4
- package/dist/lib/temp.js +4 -56
- package/dist/lib/tools-access.d.ts +3 -0
- package/dist/lib/tools-access.js +13 -0
- package/dist/lib/tools-inspect.d.ts +1 -0
- package/dist/lib/tools-inspect.js +110 -43
- package/dist/lib/tools-local.d.ts +3 -0
- package/dist/lib/tools-local.js +18 -6
- package/dist/lib/tools-message.d.ts +4 -1
- package/dist/lib/tools-message.js +126 -31
- package/dist/lib/tools-response.d.ts +31 -3
- package/dist/lib/tools-response.js +311 -47
- package/dist/lib/tools-spawn.d.ts +3 -0
- package/dist/lib/tools-spawn.js +29 -7
- package/dist/lib/trace-projection.d.ts +20 -0
- package/dist/lib/trace-projection.js +192 -43
- package/dist/scripts/async-runner.mjs +272 -194
- package/dist/scripts/conformance.mjs +14 -2
- package/dist/skills/actors/SKILL.md +46 -2
- package/dist/skills/actors/references/diagnostics.md +40 -0
- package/dist/skills/actors/references/runs.md +55 -1
- package/docs/README.md +9 -1
- package/docs/actor-inspector.md +84 -15
- package/docs/agent-experience.md +216 -0
- package/docs/async-runs.md +18 -2
- package/docs/composition-transport.md +103 -0
- package/docs/coordinator-delivery.md +204 -4
- package/docs/inspection.md +38 -2
- package/docs/output-projection-map.md +130 -0
- package/docs/releasing.md +19 -2
- package/docs/run-supervision.md +1622 -0
- package/docs/template-recipes.md +4 -0
- package/docs/windows-process-observation.md +248 -0
- package/index.ts +1 -1
- package/lib/async-runs.ts +164 -73
- package/lib/automatic-review-runtime.ts +4 -2
- package/lib/command-templates.ts +287 -138
- package/lib/execution-files.ts +118 -0
- package/lib/execution-output.ts +4 -4
- package/lib/execution-sessions.ts +57 -27
- package/lib/execution.ts +8 -0
- package/lib/extension-runtime.ts +102 -12
- package/lib/file-state.ts +16 -2
- package/lib/inspector-command.ts +2 -2
- package/lib/inspector-overlay.ts +524 -261
- package/lib/inspector.ts +101 -130
- package/lib/limits.ts +1 -0
- package/lib/observability.ts +235 -116
- package/lib/pi.ts +59 -11
- package/lib/recipe-projection.ts +232 -0
- package/lib/recipes-context.ts +27 -6
- package/lib/registry.ts +275 -36
- package/lib/run-delivery.ts +1737 -49
- package/lib/run-supervision.ts +411 -0
- package/lib/run-ui-runtime.ts +237 -73
- package/lib/runs-artifacts.ts +73 -1
- package/lib/runs-context-exports.ts +1871 -0
- package/lib/runs-context-index.ts +372 -0
- package/lib/runs-control-delivery.ts +36 -18
- package/lib/runs-control.ts +297 -1
- package/lib/runs-controls.ts +3 -1
- package/lib/runs-descendant-launches.ts +338 -0
- package/lib/runs-execution-evidence.ts +302 -0
- package/lib/runs-index.ts +345 -17
- package/lib/runs-native-launches.ts +270 -0
- package/lib/runs-outcomes.ts +377 -0
- package/lib/runs-ownership.ts +37 -4
- package/lib/runs-process-windows-mi.ts +113 -0
- package/lib/runs-process.ts +210 -34
- package/lib/runs-results.ts +601 -0
- package/lib/runs-retention.ts +134 -10
- package/lib/runs-session-exports.ts +406 -0
- package/lib/runs-snapshot.ts +143 -0
- package/lib/runs-start.ts +44 -2
- package/lib/runs-status.ts +252 -10
- package/lib/runs-supervision.ts +394 -0
- package/lib/runs-trace.ts +14 -3
- package/lib/runtime.ts +22 -3
- package/lib/session-evidence.ts +76 -4
- package/lib/state-readers.ts +16 -7
- package/lib/temp.ts +3 -56
- package/lib/tools-access.ts +13 -0
- package/lib/tools-inspect.ts +110 -51
- package/lib/tools-local.ts +37 -24
- package/lib/tools-message.ts +120 -37
- package/lib/tools-response.ts +273 -50
- package/lib/tools-spawn.ts +31 -10
- package/lib/trace-projection.ts +165 -42
- package/package.json +10 -6
- package/scripts/async-runner.mjs +272 -194
- package/scripts/conformance.mjs +14 -2
- package/skills/actors/SKILL.md +46 -2
- package/skills/actors/references/diagnostics.md +40 -0
- package/skills/actors/references/runs.md +55 -1
- package/banner.jpg +0 -0
- package/dist/lib/inspector-actions.d.ts +0 -16
- package/dist/lib/inspector-actions.js +0 -57
- package/lib/inspector-actions.ts +0 -79
package/lib/trace-projection.ts
CHANGED
|
@@ -4,17 +4,21 @@
|
|
|
4
4
|
* Owns public Trace items; source journals and session parsing remain in their domains.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
7
8
|
import { existsSync, statSync } from "node:fs";
|
|
8
9
|
import { join, relative } from "node:path";
|
|
9
10
|
|
|
10
11
|
import * as ControlProjection from "./control-projection.ts";
|
|
11
12
|
import * as ExecutionSessions from "./execution-sessions.ts";
|
|
12
13
|
import * as Limits from "./limits.ts";
|
|
14
|
+
import { createRunRecipeEvidenceRedactor } from "./recipe-projection.ts";
|
|
13
15
|
import {
|
|
14
|
-
|
|
16
|
+
describeRunArtifactReferences,
|
|
17
|
+
observeRunArtifactReference,
|
|
15
18
|
type RunArtifactDeclaration,
|
|
16
19
|
} from "./runs-artifacts.ts";
|
|
17
20
|
import * as RunsControls from "./runs-controls.ts";
|
|
21
|
+
import { isRunStopResultCapture } from "./runs-outcomes.ts";
|
|
18
22
|
import type { RunControlRecord } from "./runs-controls.ts";
|
|
19
23
|
import { tailFile } from "./runs-status.ts";
|
|
20
24
|
import * as RunsTrace from "./runs-trace.ts";
|
|
@@ -35,11 +39,17 @@ export type TraceSource =
|
|
|
35
39
|
export type TraceSourceFilter = TraceSource | "all";
|
|
36
40
|
|
|
37
41
|
export const TRACE_ITEM_SEQUENCE = Symbol("trace-item-sequence");
|
|
42
|
+
export const TRACE_ITEM_CHRONOLOGY = Symbol("trace-item-chronology");
|
|
43
|
+
export type TraceChronologyReason = "history_incomplete" | "control_history_unproven" | "metadata_unavailable" | "metadata_private" | "metadata_too_large" | "metadata_ambiguous" | "timestamp_unavailable";
|
|
44
|
+
export type TraceChronology = Readonly<{ basis: "recorded_observations" } & (
|
|
45
|
+
{ state: "available"; ordinal: number; total: number } | { state: "unavailable"; reason: TraceChronologyReason }
|
|
46
|
+
)>;
|
|
38
47
|
|
|
39
48
|
export interface TraceItem {
|
|
40
49
|
id: string;
|
|
41
50
|
ts: string;
|
|
42
51
|
[TRACE_ITEM_SEQUENCE]?: number;
|
|
52
|
+
[TRACE_ITEM_CHRONOLOGY]?: TraceChronology;
|
|
43
53
|
source: TraceSource;
|
|
44
54
|
kind: string;
|
|
45
55
|
summary: string;
|
|
@@ -47,11 +57,12 @@ export interface TraceItem {
|
|
|
47
57
|
detail: unknown;
|
|
48
58
|
}
|
|
49
59
|
|
|
50
|
-
interface
|
|
51
|
-
item: TraceItem
|
|
60
|
+
interface OrderedTraceKey {
|
|
61
|
+
item: Pick<TraceItem, "id" | "ts" | "source">;
|
|
52
62
|
ordinal: number;
|
|
53
63
|
sourceKey: string;
|
|
54
64
|
}
|
|
65
|
+
interface OrderedTraceItem extends OrderedTraceKey { item: TraceItem }
|
|
55
66
|
|
|
56
67
|
const LIFECYCLE_PREFIXES = ["run.", "command."];
|
|
57
68
|
const SOURCE_LIMIT = 100;
|
|
@@ -84,7 +95,7 @@ function ordered(
|
|
|
84
95
|
return { item, ordinal, sourceKey };
|
|
85
96
|
}
|
|
86
97
|
|
|
87
|
-
function compareTraceItems(left:
|
|
98
|
+
function compareTraceItems(left: OrderedTraceKey, right: OrderedTraceKey): number {
|
|
88
99
|
const timestamp = right.item.ts.localeCompare(left.item.ts);
|
|
89
100
|
if (timestamp) return timestamp;
|
|
90
101
|
if (left.sourceKey === right.sourceKey) {
|
|
@@ -95,6 +106,52 @@ function compareTraceItems(left: OrderedTraceItem, right: OrderedTraceItem): num
|
|
|
95
106
|
right.item.id.localeCompare(left.item.id);
|
|
96
107
|
}
|
|
97
108
|
|
|
109
|
+
// Read-local metadata only; availability is not an original-history, issuer or work capability.
|
|
110
|
+
class TraceChronologyBuilder {
|
|
111
|
+
private entries: OrderedTraceKey[] = [];
|
|
112
|
+
private bytes = 2;
|
|
113
|
+
private reason?: TraceChronologyReason;
|
|
114
|
+
unavailable(reason: TraceChronologyReason): void { this.reason ??= reason; this.entries.length = 0; }
|
|
115
|
+
add(item: Pick<TraceItem, "id" | "ts" | "source">, sourceKey: string, ordinal: number): void {
|
|
116
|
+
if (this.reason) return;
|
|
117
|
+
if (typeof item.id !== "string" || !item.id) { this.unavailable("metadata_unavailable"); return; }
|
|
118
|
+
const projected = redact([item.id, item.ts]) as unknown[];
|
|
119
|
+
if (projected[0] !== item.id || projected[1] !== item.ts) { this.unavailable("metadata_private"); return; }
|
|
120
|
+
if (typeof item.ts !== "string" || item.ts.length !== 24 || !Number.isFinite(Date.parse(item.ts)) || new Date(item.ts).toISOString() !== item.ts) {
|
|
121
|
+
this.unavailable("timestamp_unavailable"); return;
|
|
122
|
+
}
|
|
123
|
+
const entry = { item: { id: item.id, ts: item.ts, source: item.source }, sourceKey, ordinal };
|
|
124
|
+
this.bytes += Buffer.byteLength(JSON.stringify(entry)) + Number(this.entries.length > 0);
|
|
125
|
+
if (this.bytes > Limits.TRACE_JOURNAL_MAX_BYTES) { this.unavailable("metadata_too_large"); return; }
|
|
126
|
+
this.entries.push(entry);
|
|
127
|
+
}
|
|
128
|
+
finish(items: OrderedTraceItem[]): void {
|
|
129
|
+
const ranks = new Map<string, { key: OrderedTraceKey; ordinal: number }>();
|
|
130
|
+
if (!this.reason) {
|
|
131
|
+
this.entries.sort(compareTraceItems);
|
|
132
|
+
for (const [index, key] of this.entries.entries()) {
|
|
133
|
+
if (ranks.has(key.item.id)) { this.unavailable("metadata_ambiguous"); break; }
|
|
134
|
+
ranks.set(key.item.id, { key, ordinal: this.entries.length - index });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (!this.reason && items.some(({ item, sourceKey }) => {
|
|
138
|
+
const entry = ranks.get(item.id);
|
|
139
|
+
return !entry || entry.key.sourceKey !== sourceKey || entry.key.item.ts !== item.ts || entry.key.item.source !== item.source;
|
|
140
|
+
})) this.unavailable("metadata_unavailable");
|
|
141
|
+
// The legacy same-source ordinal/cross-source rank tie rule is not always a total order.
|
|
142
|
+
if (!this.reason) for (const source of ["all", ...Object.keys(SOURCE_RANK)]) {
|
|
143
|
+
let previous = Infinity;
|
|
144
|
+
const view = items.filter(({ item }) => source === "all" || item.source === source).sort(compareTraceItems);
|
|
145
|
+
if (view.some(({ item }) => { const rank = ranks.get(item.id)!.ordinal; const mismatch = rank >= previous; previous = rank; return mismatch; })) {
|
|
146
|
+
this.unavailable("metadata_ambiguous"); break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (const { item } of items) Object.defineProperty(item, TRACE_ITEM_CHRONOLOGY, { value: Object.freeze(this.reason
|
|
150
|
+
? { state: "unavailable", basis: "recorded_observations", reason: this.reason }
|
|
151
|
+
: { state: "available", basis: "recorded_observations", ordinal: ranks.get(item.id)!.ordinal, total: ranks.size }) });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
98
155
|
function latestControlTimestamp(control: RunControlRecord): string {
|
|
99
156
|
return (
|
|
100
157
|
control.failed_at ??
|
|
@@ -136,9 +193,15 @@ function controlDiagnosticItems(
|
|
|
136
193
|
}));
|
|
137
194
|
}
|
|
138
195
|
|
|
139
|
-
function traceEventItems(
|
|
140
|
-
|
|
196
|
+
function traceEventItems(read: RunsTrace.RunTraceJournalRead, recipe?: Record<string, unknown>,
|
|
197
|
+
projectEvidence: (value: unknown) => unknown = recipe ? createRunRecipeEvidenceRedactor(recipe) : redact,
|
|
198
|
+
chronology?: TraceChronologyBuilder): OrderedTraceItem[] {
|
|
141
199
|
const summary = RunsTrace.summarizeRunTraceJournal(read);
|
|
200
|
+
if (!summary.history_complete) chronology?.unavailable("history_incomplete");
|
|
201
|
+
if (chronology) for (const { event, ordinal } of read.events) {
|
|
202
|
+
if (redact(event.kind) !== event.kind) chronology.unavailable("metadata_private");
|
|
203
|
+
chronology.add({ id: event.id, ts: event.ts, source: sourceForEvent(event) }, "trace", ordinal);
|
|
204
|
+
}
|
|
142
205
|
const sequenceOffset = summary.dropped_events + Math.max(0, summary.compactions_total - 1);
|
|
143
206
|
const retained = read.events.slice(-SOURCE_LIMIT);
|
|
144
207
|
const projected = retained.map(({ event, ordinal }) => ordered({
|
|
@@ -146,9 +209,9 @@ function traceEventItems(stateDir: string): OrderedTraceItem[] {
|
|
|
146
209
|
ts: event.ts,
|
|
147
210
|
source: sourceForEvent(event),
|
|
148
211
|
kind: event.kind,
|
|
149
|
-
summary: event.summary ?? event.kind,
|
|
212
|
+
summary: projectEvidence(event.summary ?? event.kind) as string,
|
|
150
213
|
...(event.level ? { level: event.level } : {}),
|
|
151
|
-
detail:
|
|
214
|
+
detail: projectEvidence({
|
|
152
215
|
...(event.attention ? { attention: event.attention } : {}),
|
|
153
216
|
...(event.data !== undefined ? { data: event.data } : {}),
|
|
154
217
|
}),
|
|
@@ -177,8 +240,24 @@ function traceEventItems(stateDir: string): OrderedTraceItem[] {
|
|
|
177
240
|
return [...projected, ...diagnostics];
|
|
178
241
|
}
|
|
179
242
|
|
|
180
|
-
function controlItems(stateDir: string): OrderedTraceItem[] {
|
|
243
|
+
function controlItems(stateDir: string, chronology?: TraceChronologyBuilder): OrderedTraceItem[] {
|
|
181
244
|
const read = RunsControls.readRunControlJournalFromStateDir(stateDir);
|
|
245
|
+
if (read.diagnostics.length) chronology?.unavailable("metadata_unavailable");
|
|
246
|
+
let terminal = 0;
|
|
247
|
+
if (chronology) for (const [index, raw] of read.records.entries()) {
|
|
248
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) { chronology.unavailable("metadata_unavailable"); continue; }
|
|
249
|
+
const record = raw as RunControlRecord;
|
|
250
|
+
if (![record.id, record.action, record.run_instance_id, record.queued_at].every(value => typeof value === "string") || !record.id || !record.run_instance_id ||
|
|
251
|
+
!["queued", "delivered", "claimed", "handled", "failed"].includes(record.status)) { chronology.unavailable("metadata_unavailable"); continue; }
|
|
252
|
+
if (record.status === "handled" || record.status === "failed") terminal++;
|
|
253
|
+
const metadata = { id: record.id, action: record.action, run_instance_id: record.run_instance_id, queued_at: record.queued_at, status: record.status,
|
|
254
|
+
...Object.fromEntries(["failed_at", "handled_at", "claimed_at", "delivered_at"].flatMap(field =>
|
|
255
|
+
typeof (raw as Record<string, unknown>)[field] === "string" ? [[field, (raw as Record<string, unknown>)[field]]] : [])) };
|
|
256
|
+
const value = ControlProjection.projectRunControl(metadata);
|
|
257
|
+
if (value.id !== record.id || latestControlTimestamp(value) !== latestControlTimestamp(record)) chronology.unavailable("metadata_unavailable");
|
|
258
|
+
chronology.add({ id: `control:${value.id}`, ts: latestControlTimestamp(value), source: "control" }, "control", index + 1);
|
|
259
|
+
}
|
|
260
|
+
if (terminal >= Limits.RUN_CONTROL_TERMINAL_LIMIT) chronology?.unavailable("control_history_unproven");
|
|
182
261
|
const start = Math.max(0, read.records.length - SOURCE_LIMIT);
|
|
183
262
|
const projected = read.records.slice(start).map((control, index) => {
|
|
184
263
|
const value = ControlProjection.projectRunControl(control as RunControlRecord);
|
|
@@ -200,14 +279,39 @@ function controlItems(stateDir: string): OrderedTraceItem[] {
|
|
|
200
279
|
];
|
|
201
280
|
}
|
|
202
281
|
|
|
203
|
-
function
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
282
|
+
function agentIdentity(commandId: string, sessionFile: string, index: number,
|
|
283
|
+
admitted: SessionEvidence.SessionEvidenceTurn[typeof SessionEvidence.SESSION_TURN_IDENTITY]): string {
|
|
284
|
+
const namespace = redact([commandId, sessionFile]) as unknown[];
|
|
285
|
+
const identity = namespace[0] === commandId && namespace[1] === sessionFile ? admitted : undefined;
|
|
286
|
+
const basis = identity?.basis ?? "legacy";
|
|
287
|
+
const key = createHash("sha256").update(JSON.stringify([
|
|
288
|
+
"agent-turn-v1", ...namespace, identity ?? { basis, ordinal: index },
|
|
289
|
+
])).digest("hex");
|
|
290
|
+
return `agent:${basis}:${key}`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function agentItems(stateDir: string, chronology?: TraceChronologyBuilder): OrderedTraceItem[] {
|
|
294
|
+
const turns = ExecutionSessions.readExecutionTurns(stateDir);
|
|
295
|
+
const metadata = turns[ExecutionSessions.EXECUTION_CHRONOLOGY];
|
|
296
|
+
if (!metadata || metadata.state !== "available") chronology?.unavailable("metadata_unavailable");
|
|
297
|
+
else for (const entry of metadata.entries) chronology?.add({
|
|
298
|
+
id: agentIdentity(entry.commandId, entry.sessionFile, entry.ordinal, entry.identity), ts: entry.timestamp, source: "agent",
|
|
299
|
+
}, "agent", entry.ordinal);
|
|
300
|
+
return turns.slice(-SOURCE_LIMIT).map((turn) => {
|
|
207
301
|
const text = turn.assistantText ?? turn.userText ?? "Agent turn";
|
|
208
|
-
const
|
|
302
|
+
const compact = text.replaceAll(/\s+/g, " ").trim();
|
|
303
|
+
let summary = compact;
|
|
304
|
+
if (Buffer.from(compact).toString("utf8") !== compact) {
|
|
305
|
+
summary = "Agent turn [omitted: unknown] (malformed retained text)";
|
|
306
|
+
} else if (compact.length > 160) {
|
|
307
|
+
const last = compact.charCodeAt(159), next = compact.charCodeAt(160);
|
|
308
|
+
const end = last >= 0xd800 && last <= 0xdbff && next >= 0xdc00 && next <= 0xdfff ? 159 : 160;
|
|
309
|
+
// Only this normalized retained suffix supplies a count; upstream source loss stays unknown.
|
|
310
|
+
const omitted = Array.from(compact.slice(end)).length;
|
|
311
|
+
summary = `${compact.slice(0, end)}… [omitted: ${omitted} chars] from normalized retained turn; upstream [omitted: unknown]`;
|
|
312
|
+
}
|
|
209
313
|
return ordered({
|
|
210
|
-
id:
|
|
314
|
+
id: agentIdentity(turn.commandId, turn.sessionFile, turn.index, turn[SessionEvidence.SESSION_TURN_IDENTITY]),
|
|
211
315
|
ts: turn.timestamp ?? new Date(0).toISOString(),
|
|
212
316
|
source: "agent",
|
|
213
317
|
kind: "agent.turn",
|
|
@@ -247,14 +351,15 @@ function resultItems(stateDir: string): OrderedTraceItem[] {
|
|
|
247
351
|
}
|
|
248
352
|
const stat = statSync(path);
|
|
249
353
|
const failed = Number(read.value.code ?? 0) !== 0;
|
|
354
|
+
const captured = isRunStopResultCapture(read.value);
|
|
250
355
|
return [ordered({
|
|
251
356
|
id: "process:result",
|
|
252
357
|
ts: typeof read.value.completedAt === "string"
|
|
253
358
|
? read.value.completedAt
|
|
254
359
|
: stat.mtime.toISOString(),
|
|
255
360
|
source: "process",
|
|
256
|
-
kind: failed ? "process.failed" : "process.result",
|
|
257
|
-
summary: failed ? "Run process failed" : "Run process completed",
|
|
361
|
+
kind: captured ? "process.result_captured" : failed ? "process.failed" : "process.result",
|
|
362
|
+
summary: captured ? "Workload result captured while stopping" : failed ? "Run process failed" : "Run process completed",
|
|
258
363
|
...(failed ? { level: "error" as const } : {}),
|
|
259
364
|
detail: redact(read.value),
|
|
260
365
|
}, "process:result", 1, 2), ...diagnosticItems(read.diagnostics).map(
|
|
@@ -265,27 +370,41 @@ function resultItems(stateDir: string): OrderedTraceItem[] {
|
|
|
265
370
|
function artifactItems(
|
|
266
371
|
stateDir: string,
|
|
267
372
|
declarations: Record<string, RunArtifactDeclaration> | undefined,
|
|
373
|
+
chronology?: TraceChronologyBuilder,
|
|
268
374
|
): OrderedTraceItem[] {
|
|
269
|
-
const
|
|
270
|
-
if (
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
375
|
+
const described = describeRunArtifactReferences(declarations, process.cwd());
|
|
376
|
+
if (described.state !== "available") { if (declarations) chronology?.unavailable("metadata_unavailable"); return []; }
|
|
377
|
+
if (described.references.length > SOURCE_LIMIT) chronology?.unavailable("metadata_unavailable");
|
|
378
|
+
return described.references.slice(0, SOURCE_LIMIT).map((reference, index) => {
|
|
379
|
+
const artifact = observeRunArtifactReference(reference);
|
|
380
|
+
const exists = artifact.availability === "available";
|
|
381
|
+
if (!artifact.modified_at) chronology?.unavailable("timestamp_unavailable");
|
|
382
|
+
return ordered({
|
|
383
|
+
id: `artifact:${artifact.name}`,
|
|
384
|
+
ts: artifact.modified_at ?? new Date(0).toISOString(),
|
|
277
385
|
source: "artifact",
|
|
278
|
-
kind:
|
|
279
|
-
summary: `${name}: ${
|
|
280
|
-
...(artifact.required && !
|
|
386
|
+
kind: exists ? "artifact.ready" : artifact.availability === "missing" ? "artifact.missing" : "artifact.unavailable",
|
|
387
|
+
summary: redact(`${artifact.name}: ${exists ? "ready" : artifact.availability}`) as string,
|
|
388
|
+
...(artifact.required && !exists ? { level: "warning" as const } : {}),
|
|
281
389
|
detail: redact({
|
|
282
|
-
exists:
|
|
390
|
+
...(artifact.availability !== "unavailable" ? { exists } : {}),
|
|
391
|
+
availability: artifact.availability,
|
|
283
392
|
path: relative(stateDir, artifact.path).replaceAll("\\", "/"),
|
|
284
393
|
required: artifact.required,
|
|
285
|
-
...(artifact.
|
|
394
|
+
...(artifact.bytes_total !== undefined ? { size: artifact.bytes_total } : {}),
|
|
395
|
+
...(artifact.reason ? { reason: artifact.reason } : {}),
|
|
286
396
|
}),
|
|
287
|
-
}, "artifact", index + 1, index)
|
|
288
|
-
);
|
|
397
|
+
}, "artifact", index + 1, index);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** Data-only canonical-journal projection; captured Recipe context supplies privacy, never lifecycle/work authority. */
|
|
402
|
+
export function projectRunTraceJournal(
|
|
403
|
+
read: RunsTrace.RunTraceJournalRead,
|
|
404
|
+
options: { limit?: number; recipe?: Record<string, unknown>; redactEvidence?: (value: unknown) => unknown } = {},
|
|
405
|
+
): TraceItem[] {
|
|
406
|
+
return traceEventItems(read, options.recipe, options.redactEvidence).sort(compareTraceItems)
|
|
407
|
+
.slice(0, Math.max(1, Math.min(options.limit ?? 100, 200))).map(({ item }) => item);
|
|
289
408
|
}
|
|
290
409
|
|
|
291
410
|
export function projectRunTrace(
|
|
@@ -297,16 +416,20 @@ export function projectRunTrace(
|
|
|
297
416
|
} = {},
|
|
298
417
|
): TraceItem[] {
|
|
299
418
|
const source = options.source ?? "all";
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
...
|
|
303
|
-
...
|
|
304
|
-
...
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
.
|
|
309
|
-
.
|
|
419
|
+
const chronology = new TraceChronologyBuilder();
|
|
420
|
+
const entries = [
|
|
421
|
+
...traceEventItems(RunsTrace.readRunTraceJournal(stateDir), undefined, undefined, chronology),
|
|
422
|
+
...controlItems(stateDir, chronology),
|
|
423
|
+
...agentItems(stateDir, chronology),
|
|
424
|
+
];
|
|
425
|
+
const snapshots = [...processItems(stateDir), ...resultItems(stateDir), ...artifactItems(stateDir, options.artifacts, chronology)];
|
|
426
|
+
for (const entry of snapshots) {
|
|
427
|
+
if (entry.item.kind === "state.read_error") chronology.unavailable("metadata_unavailable");
|
|
428
|
+
chronology.add(entry.item, entry.sourceKey, entry.ordinal);
|
|
429
|
+
}
|
|
430
|
+
const all = [...entries, ...snapshots];
|
|
431
|
+
chronology.finish(all);
|
|
432
|
+
const items = all.filter(({ item }) => source === "all" || item.source === source).sort(compareTraceItems);
|
|
310
433
|
return items
|
|
311
434
|
.slice(0, Math.max(1, Math.min(options.limit ?? 100, 200)))
|
|
312
435
|
.map(({ item }) => item);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-actors",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.56.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Local Actor Kernel for Pi",
|
|
6
6
|
"keywords": [
|
|
@@ -27,11 +27,13 @@
|
|
|
27
27
|
"scripts": {
|
|
28
28
|
"check": "node --experimental-strip-types -e \"await import('./index.ts'); console.log('pi-actors: extension import ok')\"",
|
|
29
29
|
"conformance": "node scripts/conformance.mjs",
|
|
30
|
-
"test": "node --experimental-strip-types --test --test-concurrency=1 tests/*.test.ts",
|
|
31
|
-
"test:
|
|
30
|
+
"test": "node --import ./tests/test-environment.mjs --experimental-strip-types --test --test-concurrency=1 tests/*.test.ts",
|
|
31
|
+
"test:shard": "node .github/scripts/test-shards.mjs",
|
|
32
|
+
"test:preservation": "node --import ./tests/test-environment.mjs --experimental-strip-types --test --test-concurrency=1 tests/async-runs.test.ts tests/runs-retention.test.ts tests/observability.test.ts tests/session-evidence.test.ts tests/inspector.test.ts tests/inspector-overlay.test.ts tests/review-control.test.ts",
|
|
32
33
|
"pack:dry": "npm pack --dry-run",
|
|
33
34
|
"recipes:qa": "node skills/actors/scripts/validate-recipe.mjs skills --skills --qa --summary",
|
|
34
|
-
"validate": "npx tsc --noEmit && npm run recipes:qa && npm run build:check && npm run check
|
|
35
|
+
"validate:preflight": "npx tsc --noEmit && npm run recipes:qa && npm run build:check && npm run check",
|
|
36
|
+
"validate": "npm run validate:preflight && npm test && npm run pack:dry",
|
|
35
37
|
"audit:dependencies": "npm audit --audit-level=high --omit=peer",
|
|
36
38
|
"build": "node scripts/build-dist.mjs",
|
|
37
39
|
"build:check": "node scripts/build-dist.mjs --check",
|
|
@@ -49,8 +51,7 @@
|
|
|
49
51
|
"BACKLOG.md",
|
|
50
52
|
"CHANGELOG.md",
|
|
51
53
|
"docs",
|
|
52
|
-
"fixtures"
|
|
53
|
-
"banner.jpg"
|
|
54
|
+
"fixtures"
|
|
54
55
|
],
|
|
55
56
|
"pi": {
|
|
56
57
|
"extensions": [
|
|
@@ -68,5 +69,8 @@
|
|
|
68
69
|
"devDependencies": {
|
|
69
70
|
"@types/node": "latest",
|
|
70
71
|
"typescript": "latest"
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"yaml": "2.9.0"
|
|
71
75
|
}
|
|
72
76
|
}
|