@llblab/pi-actors 0.53.1 → 0.54.0

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 CHANGED
@@ -26,6 +26,8 @@ Public Run verbs remain `spawn`, `message`, and `inspect`.
26
26
 
27
27
  ## Core Structure
28
28
 
29
+ Require Pi ≥1.0.0 for all declared Pi peers. Keep source and packed lifecycle tests aligned with that baseline; do not restore an older host floor independently of those checks. Validation fixtures must use temporary agent directories, never write into the operator's live Recipe registry.
30
+
29
31
  ```text
30
32
  Pi host
31
33
  -> index.ts composition root
@@ -86,7 +88,7 @@ Canonical event:
86
88
  {"id":"…","ts":"…","kind":"…","summary":"…","data":{},"level":"info","attention":"notify"}
87
89
  ```
88
90
 
89
- Trace is a bounded retained suffix, not an audit archive. Every first-party writer must call `appendRunTraceEvent`; under the canonical token-owned lock it appends within both fixed bounds or atomically retains the newest suffix plus one cumulative warning-only `runtime.trace_compacted` marker. The marker means older history was discarded; terminal/result/execution/artifact files remain authoritative independently. Reads are newline-safe and order equal timestamps by same-source ordinal, fixed source rank, then stable id without exposing ordering metadata. Never write `trace.jsonl` directly. Generic command lifecycle is Trace-only: `command.done` preserves complete bounded execution evidence but never requests or projects any attention value, and Recipe grammar has no command-completion delivery switch. Semantic attention is explicit: `notify` is visible status, `followup` is an ordinary checkpoint hint, and actor-authored `steer` is durable urgent delivery at Pi's next safe boundary. Never infer attention from status or exit code. Admit steer by exact event and Run generation before `deliverAs: "steer"`; acknowledge only its exact model-bound context envelope, and preserve the later root-terminal completion batch. Sequence, parallel, repeat, and import branches remain internal, while each separately launched Run owns a separate generation.
91
+ Trace is a bounded retained suffix, not an audit archive. Every first-party writer must call `appendRunTraceEvent`; under the canonical token-owned lock it appends within both fixed bounds or atomically retains the newest suffix plus one cumulative warning-only `runtime.trace_compacted` marker. The marker means older history was discarded; terminal/result/execution/artifact files remain authoritative independently. Reads are newline-safe and order equal timestamps by same-source ordinal, fixed source rank, then stable id without exposing ordering metadata. Actor Inspector derives stable source-local row sequences before applying its visible-tail bound, including cumulative compaction offsets for canonical Trace, so appends never renumber retained rows. Never write `trace.jsonl` directly. Generic command lifecycle is Trace-only: `command.done` preserves complete bounded execution evidence but never requests or projects any attention value, and Recipe grammar has no command-completion delivery switch. Semantic attention is explicit: `notify` is visible status, `followup` is an ordinary checkpoint hint, and actor-authored `steer` is durable urgent delivery at Pi's next safe boundary. Never infer attention from status or exit code. Admit steer by exact event and Run generation before `deliverAs: "steer"`; acknowledge only its exact model-bound context envelope, and preserve the later root-terminal completion batch. Sequence, parallel, repeat, and import branches remain internal, while each separately launched Run owns a separate generation.
90
92
 
91
93
  ### Control
92
94
 
package/CHANGELOG.md CHANGED
@@ -2,7 +2,14 @@
2
2
 
3
3
  > Each release keeps at most 8 outcome records of at most 512 characters.
4
4
 
5
- ## Unreleased
5
+ ## 0.54.0: Pi 1.0 Baseline and Package Licensing
6
+
7
+ - `Licensing`: Includes the MIT LICENSE in source checkouts and npm packages, preserving existing author attribution.
8
+ - `Pi Baseline`: Requires Pi 1.0.0 or newer for both coding-agent and TUI peers. Source and installed-package lifecycle checks use the same baseline; runtime ownership, Recipe/Run semantics and persistent registries are unchanged. Stored-tool normalization tests now use a temporary agent registry rather than writing fixtures into the operator's home.
9
+
10
+ ## 0.53.2: Stable Inspector Trace Sequences
11
+
12
+ - `Stable Inspector Trace Sequences`: Actor Inspector now numbers Trace rows from stable source-local chronology before applying the 100-row projection bound. Canonical Trace rows include cumulative compaction offsets and owned Pi turns retain their native sequence, so adding `#100` no longer renumbers the previous `#99`; newest-first ordering, source filters, public Trace JSON, and focus-by-id remain unchanged.
6
13
 
7
14
  ## 0.53.1: Filterable Skills and drift-safe Git installs
8
15
 
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 llblab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -19,7 +19,7 @@ This topology does not require every task to become a subagent. Short work with
19
19
 
20
20
  ## Install
21
21
 
22
- Requires Node.js 22.19.0 or newer and Pi 0.84.4 or newer.
22
+ Requires Node.js 22.19.0 or newer and Pi 1.0.0 or newer.
23
23
 
24
24
  ```bash
25
25
  pi install npm:@llblab/pi-actors
@@ -583,7 +583,8 @@ export class ActorInspectorOverlay {
583
583
  const prefix = this.focus === "list" && index === this.rowIndex
584
584
  ? this.theme.fg("accent", " ▶ ")
585
585
  : " ";
586
- const row = `${prefix}${this.theme.fg("text", `#${items.length - index - 1}`)} ${marker} ${this.theme.fg("muted", item.source)}/${this.theme.fg(item.level === "error" ? "error" : "accent", item.kind)} ${this.theme.fg("text", item.summary)}`;
586
+ const sequence = item[TraceProjection.TRACE_ITEM_SEQUENCE] ?? items.length - index - 1;
587
+ const row = `${prefix}${this.theme.fg("text", `#${sequence}`)} ${marker} ${this.theme.fg("muted", item.source)}/${this.theme.fg(item.level === "error" ? "error" : "accent", item.kind)} ${this.theme.fg("text", item.summary)}`;
587
588
  return this.focus === "list" && index === this.rowIndex
588
589
  ? this.theme.fg("accent", row)
589
590
  : row;
@@ -6,9 +6,11 @@
6
6
  import { type RunArtifactDeclaration } from "./runs-artifacts.ts";
7
7
  export type TraceSource = "lifecycle" | "control" | "process" | "agent" | "artifact" | "runtime";
8
8
  export type TraceSourceFilter = TraceSource | "all";
9
+ export declare const TRACE_ITEM_SEQUENCE: unique symbol;
9
10
  export interface TraceItem {
10
11
  id: string;
11
12
  ts: string;
13
+ [TRACE_ITEM_SEQUENCE]?: number;
12
14
  source: TraceSource;
13
15
  kind: string;
14
16
  summary: string;
@@ -14,6 +14,7 @@ import { tailFile } from "./runs-status.js";
14
14
  import * as RunsTrace from "./runs-trace.js";
15
15
  import * as SessionEvidence from "./session-evidence.js";
16
16
  import { readJsonFileResilient, } from "./state-readers.js";
17
+ export const TRACE_ITEM_SEQUENCE = Symbol("trace-item-sequence");
17
18
  const LIFECYCLE_PREFIXES = ["run.", "command."];
18
19
  const SOURCE_LIMIT = 100;
19
20
  const SOURCE_RANK = {
@@ -32,7 +33,8 @@ function sourceForEvent(event) {
32
33
  ? "lifecycle"
33
34
  : "runtime";
34
35
  }
35
- function ordered(item, sourceKey, ordinal) {
36
+ function ordered(item, sourceKey, ordinal, sequence = ordinal) {
37
+ Object.defineProperty(item, TRACE_ITEM_SEQUENCE, { value: sequence });
36
38
  return { item, ordinal, sourceKey };
37
39
  }
38
40
  function compareTraceItems(left, right) {
@@ -83,6 +85,8 @@ function controlDiagnosticItems(diagnostics) {
83
85
  }
84
86
  function traceEventItems(stateDir) {
85
87
  const read = RunsTrace.readRunTraceJournal(stateDir);
88
+ const summary = RunsTrace.summarizeRunTraceJournal(read);
89
+ const sequenceOffset = summary.dropped_events + Math.max(0, summary.compactions_total - 1);
86
90
  const retained = read.events.slice(-SOURCE_LIMIT);
87
91
  const projected = retained.map(({ event, ordinal }) => ordered({
88
92
  id: event.id,
@@ -95,7 +99,7 @@ function traceEventItems(stateDir) {
95
99
  ...(event.attention ? { attention: event.attention } : {}),
96
100
  ...(event.data !== undefined ? { data: event.data } : {}),
97
101
  }),
98
- }, "trace", ordinal));
102
+ }, "trace", ordinal, sequenceOffset + Math.max(0, ordinal - 1)));
99
103
  const diagnostics = diagnosticItems(read.diagnostics).map((item, index) => ordered(item, "trace", read.events.length + index + 1));
100
104
  const hasMarker = read.events.some(({ event }) => event.kind === "runtime.trace_compacted");
101
105
  if (read.omittedPrefixBytes > 0 && !hasMarker) {
@@ -128,7 +132,7 @@ function controlItems(stateDir) {
128
132
  summary: `${value.action} ${value.status}`,
129
133
  ...(value.status === "failed" ? { level: "error" } : {}),
130
134
  detail: value,
131
- }, "control", start + index + 1);
135
+ }, "control", start + index + 1, start + index);
132
136
  });
133
137
  return [
134
138
  ...projected,
@@ -153,7 +157,7 @@ function agentItems(stateDir) {
153
157
  });
154
158
  }
155
159
  function processItems(stateDir) {
156
- return ["stdout", "stderr"].flatMap((stream) => {
160
+ return ["stdout", "stderr"].flatMap((stream, index) => {
157
161
  const path = join(stateDir, `${stream}.log`);
158
162
  if (!existsSync(path))
159
163
  return [];
@@ -169,7 +173,7 @@ function processItems(stateDir) {
169
173
  summary: `${stream} (${stat.size} bytes)`,
170
174
  ...(stream === "stderr" ? { level: "warning" } : {}),
171
175
  detail: redact({ bytes: stat.size, path, tail }),
172
- }, `process:${stream}`, 1)];
176
+ }, `process:${stream}`, 1, index)];
173
177
  });
174
178
  }
175
179
  function resultItems(stateDir) {
@@ -190,7 +194,7 @@ function resultItems(stateDir) {
190
194
  summary: failed ? "Run process failed" : "Run process completed",
191
195
  ...(failed ? { level: "error" } : {}),
192
196
  detail: redact(read.value),
193
- }, "process:result", 1), ...diagnosticItems(read.diagnostics).map((item, index) => ordered(item, "process:result", index + 2))];
197
+ }, "process:result", 1, 2), ...diagnosticItems(read.diagnostics).map((item, index) => ordered(item, "process:result", index + 2))];
194
198
  }
195
199
  function artifactItems(stateDir, declarations) {
196
200
  const manifest = resolveArtifactManifest(declarations);
@@ -211,7 +215,7 @@ function artifactItems(stateDir, declarations) {
211
215
  required: artifact.required,
212
216
  ...(artifact.size !== undefined ? { size: artifact.size } : {}),
213
217
  }),
214
- }, "artifact", index + 1));
218
+ }, "artifact", index + 1, index));
215
219
  }
216
220
  export function projectRunTrace(stateDir, options = {}) {
217
221
  const source = options.source ?? "all";
@@ -25,7 +25,7 @@ Captured Recipe evidence belongs to the Run generation and does not change when
25
25
 
26
26
  Shows the unified bounded Trace projection. Sources include lifecycle/runtime observations, Controls, owned Pi turns, command-log tails, results, artifacts, and diagnostics. The source selector displays only `all` plus sources present in the current projection from `lifecycle`, `control`, `process`, `agent`, `artifact`, and `runtime`. Select a row to open structured detail.
27
27
 
28
- Trace ordering stays deterministic and newest-first: timestamp descending, same-source physical ordinal descending, fixed internal source rank, then stable id. Internal ordinals are never displayed or interpreted as cross-source causality. Row numbers are zero-based chronological identities even though display is newest-first: the oldest visible event is `#0` and the newest carries the highest number. The summary states whether retained history is complete; `runtime.trace_compacted` means older history was discarded and shows bounded cumulative drop evidence. Terminal/result/execution/artifact evidence keeps its own authority. The projection applies path containment and redaction before rendering.
28
+ Trace ordering stays deterministic and newest-first: timestamp descending, same-source physical ordinal descending, fixed internal source rank, then stable id. Row numbers use stable zero-based source sequences rather than positions inside the visible 100-row tail: when `#100` arrives, the existing `#99` remains `#99`. Canonical journal rows reconstruct their absolute sequence from retained ordinals plus cumulative compaction evidence; owned Pi turns keep their native turn sequence. Sequences are source-local and never imply cross-source causality. The summary states whether retained history is complete; `runtime.trace_compacted` means older history was discarded and shows bounded cumulative drop evidence. Terminal/result/execution/artifact evidence keeps its own authority. The projection applies path containment and redaction before rendering.
29
29
 
30
30
  ## Control
31
31
 
@@ -191,7 +191,7 @@ Implementation is complete only when source and packed-extension tests prove:
191
191
  10. Explicit steer reaches the next safe Pi boundary once and root terminal still batches later.
192
192
  11. Overflow, corruption, journal backpressure, archive/prune races, and stale contexts fail safely.
193
193
  12. Completion flushing precedes automatic Recipe review.
194
- 13. Pi 0.84.4 remains the exact minimum source and packed lifecycle baseline.
194
+ 13. Pi 1.0.0 is the minimum source and packed lifecycle baseline; coding-agent and TUI peers share that floor.
195
195
 
196
196
  Focused observability and delivery tests precede TypeScript/build/import checks. The acceptance checkpoint then runs full product validation, dependency audit, package dry-run, and ABCd context validation.
197
197
 
@@ -653,7 +653,8 @@ export class ActorInspectorOverlay {
653
653
  const prefix = this.focus === "list" && index === this.rowIndex
654
654
  ? this.theme.fg("accent", " ▶ ")
655
655
  : " ";
656
- const row = `${prefix}${this.theme.fg("text", `#${items.length - index - 1}`)} ${marker} ${this.theme.fg("muted", item.source)}/${this.theme.fg(item.level === "error" ? "error" : "accent", item.kind)} ${this.theme.fg("text", item.summary)}`;
656
+ const sequence = item[TraceProjection.TRACE_ITEM_SEQUENCE] ?? items.length - index - 1;
657
+ const row = `${prefix}${this.theme.fg("text", `#${sequence}`)} ${marker} ${this.theme.fg("muted", item.source)}/${this.theme.fg(item.level === "error" ? "error" : "accent", item.kind)} ${this.theme.fg("text", item.summary)}`;
657
658
  return this.focus === "list" && index === this.rowIndex
658
659
  ? this.theme.fg("accent", row)
659
660
  : row;
@@ -34,9 +34,12 @@ export type TraceSource =
34
34
 
35
35
  export type TraceSourceFilter = TraceSource | "all";
36
36
 
37
+ export const TRACE_ITEM_SEQUENCE = Symbol("trace-item-sequence");
38
+
37
39
  export interface TraceItem {
38
40
  id: string;
39
41
  ts: string;
42
+ [TRACE_ITEM_SEQUENCE]?: number;
40
43
  source: TraceSource;
41
44
  kind: string;
42
45
  summary: string;
@@ -75,7 +78,9 @@ function ordered(
75
78
  item: TraceItem,
76
79
  sourceKey: string,
77
80
  ordinal: number,
81
+ sequence = ordinal,
78
82
  ): OrderedTraceItem {
83
+ Object.defineProperty(item, TRACE_ITEM_SEQUENCE, { value: sequence });
79
84
  return { item, ordinal, sourceKey };
80
85
  }
81
86
 
@@ -133,6 +138,8 @@ function controlDiagnosticItems(
133
138
 
134
139
  function traceEventItems(stateDir: string): OrderedTraceItem[] {
135
140
  const read = RunsTrace.readRunTraceJournal(stateDir);
141
+ const summary = RunsTrace.summarizeRunTraceJournal(read);
142
+ const sequenceOffset = summary.dropped_events + Math.max(0, summary.compactions_total - 1);
136
143
  const retained = read.events.slice(-SOURCE_LIMIT);
137
144
  const projected = retained.map(({ event, ordinal }) => ordered({
138
145
  id: event.id,
@@ -145,7 +152,7 @@ function traceEventItems(stateDir: string): OrderedTraceItem[] {
145
152
  ...(event.attention ? { attention: event.attention } : {}),
146
153
  ...(event.data !== undefined ? { data: event.data } : {}),
147
154
  }),
148
- }, "trace", ordinal));
155
+ }, "trace", ordinal, sequenceOffset + Math.max(0, ordinal - 1)));
149
156
  const diagnostics = diagnosticItems(read.diagnostics).map((item, index) =>
150
157
  ordered(item, "trace", read.events.length + index + 1)
151
158
  );
@@ -183,7 +190,7 @@ function controlItems(stateDir: string): OrderedTraceItem[] {
183
190
  summary: `${value.action} ${value.status}`,
184
191
  ...(value.status === "failed" ? { level: "error" as const } : {}),
185
192
  detail: value,
186
- }, "control", start + index + 1);
193
+ }, "control", start + index + 1, start + index);
187
194
  });
188
195
  return [
189
196
  ...projected,
@@ -212,7 +219,7 @@ function agentItems(stateDir: string): OrderedTraceItem[] {
212
219
  }
213
220
 
214
221
  function processItems(stateDir: string): OrderedTraceItem[] {
215
- return ["stdout", "stderr"].flatMap((stream) => {
222
+ return ["stdout", "stderr"].flatMap((stream, index) => {
216
223
  const path = join(stateDir, `${stream}.log`);
217
224
  if (!existsSync(path)) return [];
218
225
  const stat = statSync(path);
@@ -226,7 +233,7 @@ function processItems(stateDir: string): OrderedTraceItem[] {
226
233
  summary: `${stream} (${stat.size} bytes)`,
227
234
  ...(stream === "stderr" ? { level: "warning" as const } : {}),
228
235
  detail: redact({ bytes: stat.size, path, tail }),
229
- }, `process:${stream}`, 1)];
236
+ }, `process:${stream}`, 1, index)];
230
237
  });
231
238
  }
232
239
 
@@ -250,7 +257,7 @@ function resultItems(stateDir: string): OrderedTraceItem[] {
250
257
  summary: failed ? "Run process failed" : "Run process completed",
251
258
  ...(failed ? { level: "error" as const } : {}),
252
259
  detail: redact(read.value),
253
- }, "process:result", 1), ...diagnosticItems(read.diagnostics).map(
260
+ }, "process:result", 1, 2), ...diagnosticItems(read.diagnostics).map(
254
261
  (item, index) => ordered(item, "process:result", index + 2),
255
262
  )];
256
263
  }
@@ -277,7 +284,7 @@ function artifactItems(
277
284
  required: artifact.required,
278
285
  ...(artifact.size !== undefined ? { size: artifact.size } : {}),
279
286
  }),
280
- }, "artifact", index + 1),
287
+ }, "artifact", index + 1, index),
281
288
  );
282
289
  }
283
290
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-actors",
3
- "version": "0.53.1",
3
+ "version": "0.54.0",
4
4
  "private": false,
5
5
  "description": "Local Actor Kernel for Pi",
6
6
  "keywords": [
@@ -38,6 +38,7 @@
38
38
  "prepack": "npm run build"
39
39
  },
40
40
  "files": [
41
+ "LICENSE",
41
42
  "index.ts",
42
43
  "dist",
43
44
  "lib",
@@ -61,8 +62,8 @@
61
62
  "image": "https://raw.githubusercontent.com/llblab/pi-actors/main/banner.jpg"
62
63
  },
63
64
  "peerDependencies": {
64
- "@earendil-works/pi-coding-agent": ">=0.84.4",
65
- "@earendil-works/pi-tui": ">=0.84.4"
65
+ "@earendil-works/pi-coding-agent": ">=1.0.0",
66
+ "@earendil-works/pi-tui": ">=1.0.0"
66
67
  },
67
68
  "devDependencies": {
68
69
  "@types/node": "latest",