@llblab/pi-actors 0.16.0 → 0.16.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.16.2: Recipe Registry Diagnostics Hotfix
4
+
5
+ - `[Schema]` Derived recipe tool arguments without expanding runtime-dependent repeat nodes. Impact: valid recipes using repeat expressions such as `{lenses.length}` can be exposed as tools instead of being skipped during startup schema generation.
6
+ - `[Runtime]` Replaced the dense semicolon warning with grouped recipe registry diagnostics and explicit spacing. Impact: startup diagnostics are easier to scan and do not visually run into adjacent text.
7
+ - `[Recipes]` Added a packaged `lens-swarm` recipe that composes the review coordinator without concrete model-version defaults. Impact: the standard library includes the general multi-lens review launcher instead of relying only on operator-local copies.
8
+ - `[Package]` Bumped package and packaged skill metadata to `0.16.2` for the hotfix release.
9
+
10
+ ## 0.16.1: Recipe Registry Hotfix
11
+
12
+ - `[Runtime]` Prevented invalid user recipe files from aborting extension startup when tool-schema generation fails, surfacing a warning and skipping the offending tool instead. Impact: one bad recipe in `~/.pi/agent/recipes` no longer takes down the pi-actors extension.
13
+ - `[Recipe Discovery]` Excluded the legacy migration report file from recipe discovery. Impact: `actors-tools-migration-report.json` no longer appears as a broken recipe/tool candidate after migration.
14
+ - `[Package]` Bumped package and packaged skill metadata to `0.16.1` for the hotfix release.
15
+
3
16
  ## 0.16.0: File-Discovered Recipe Registry Migration
4
17
 
5
18
  - `[Version]` Began the `0.16.0` breaking-change cycle and captured the file-discovered recipe registry migration plan in `BACKLOG.md`. Impact: the next release target is now explicit: replace `actors-tools.json` as live registry with validated recipe files, filename identity, `tool` exposure, override/disable semantics, migration reporting, registry inspection, and usage-informed cleanup.
@@ -41,10 +41,41 @@ export interface RecipeDiscoverySource {
41
41
  mutableUsage?: boolean;
42
42
  }
43
43
 
44
+ function assertToolSafeRepeatConfig(
45
+ config: unknown,
46
+ argTypes: Record<string, { kind: string }>,
47
+ defaults: Record<string, unknown>,
48
+ ): void {
49
+ if (typeof config === "string" || config === undefined || config === null) return;
50
+ if (Array.isArray(config)) {
51
+ for (const step of config) assertToolSafeRepeatConfig(step, argTypes, defaults);
52
+ return;
53
+ }
54
+ if (typeof config !== "object") return;
55
+ const node = config as { repeat?: unknown; template?: unknown; recover?: unknown };
56
+ if (typeof node.repeat === "string") {
57
+ const trimmed = node.repeat.trim();
58
+ if (!/^\d+$/.test(trimmed)) {
59
+ const match = trimmed.match(/^\{?([A-Za-z_][A-Za-z0-9_-]*)\.length\}?$/);
60
+ if (!match || (argTypes[match[1]]?.kind !== "array" && !Array.isArray(defaults[match[1]])))
61
+ throw new Error(
62
+ "Command template repeat must be a positive integer or {array.length} with an array argument/default.",
63
+ );
64
+ }
65
+ }
66
+ assertToolSafeRepeatConfig(node.template, argTypes, defaults);
67
+ assertToolSafeRepeatConfig(node.recover, argTypes, defaults);
68
+ }
69
+
44
70
  function listRecipeFiles(root: string): string[] {
45
71
  if (!existsSync(root)) return [];
46
72
  return readdirSync(root, { withFileTypes: true })
47
- .filter((entry) => entry.isFile() && entry.name.endsWith(".json"))
73
+ .filter(
74
+ (entry) =>
75
+ entry.isFile() &&
76
+ entry.name.endsWith(".json") &&
77
+ entry.name !== "actors-tools-migration-report.json",
78
+ )
48
79
  .map((entry) => join(root, entry.name))
49
80
  .sort();
50
81
  }
@@ -202,6 +233,13 @@ export function toRegisteredTool(entry: DiscoveredRecipe): RegisteredTool | unde
202
233
  defaults: { ...(argTemplate.defaults ?? {}), ...(cfg.defaults ?? {}) },
203
234
  }
204
235
  : { args: cfg.args, defaults: cfg.defaults ?? {}, template: argTemplate };
236
+ const explicitArgTypes = Object.fromEntries(
237
+ (cfg.args ?? []).map((arg) => {
238
+ const parsed = Schema.parseToolArgToken(String(arg));
239
+ return [parsed.arg, parsed.type];
240
+ }),
241
+ );
242
+ assertToolSafeRepeatConfig(argTemplateConfig, explicitArgTypes, cfg.defaults ?? {});
205
243
  const argTypes = Schema.getTemplateArgTypes(argTemplateConfig);
206
244
  return {
207
245
  name: entry.id,
package/lib/runtime.ts CHANGED
@@ -98,6 +98,27 @@ export function createAutoToolsRuntime(
98
98
  runtimeTools.add(cfg.name);
99
99
  runtimeToolFingerprints.set(cfg.name, fingerprint);
100
100
  }
101
+ function formatRecipeToolWarnings(warnings: string[]): string {
102
+ const shadowed = warnings.filter((warning) => warning.includes(" shadows "));
103
+ const skipped = warnings.filter((warning) => warning.includes(" could not be exposed as a tool:"));
104
+ const other = warnings.filter(
105
+ (warning) => !shadowed.includes(warning) && !skipped.includes(warning),
106
+ );
107
+ const lines = ["pi-actors recipe registry warning"];
108
+ if (shadowed.length > 0) {
109
+ lines.push("User recipes override packaged recipes:");
110
+ lines.push(...shadowed.map((warning) => `• ${warning}`));
111
+ }
112
+ if (skipped.length > 0) {
113
+ lines.push("Recipes skipped from tool exposure:");
114
+ lines.push(...skipped.map((warning) => `• ${warning}`));
115
+ }
116
+ if (other.length > 0) {
117
+ lines.push("Other registry diagnostics:");
118
+ lines.push(...other.map((warning) => `• ${warning}`));
119
+ }
120
+ return `${lines.join("\n")}\n`;
121
+ }
101
122
  function loadTools(ctx: RuntimeContext) {
102
123
  const warnings: string[] = [];
103
124
  const recipeRoot = deps.recipeRoot ?? Paths.getRecipeRoot();
@@ -119,8 +140,14 @@ export function createAutoToolsRuntime(
119
140
  warnings.push(...discovered.diagnostics);
120
141
  tools.clear();
121
142
  for (const entry of discovered.active.values()) {
122
- const cfg = RecipeDiscovery.toRegisteredTool(entry);
123
- if (cfg) tools.set(cfg.name, cfg);
143
+ try {
144
+ const cfg = RecipeDiscovery.toRegisteredTool(entry);
145
+ if (cfg) tools.set(cfg.name, cfg);
146
+ } catch (error) {
147
+ warnings.push(
148
+ `Recipe ${entry.id} could not be exposed as a tool: ${error instanceof Error ? error.message : String(error)}`,
149
+ );
150
+ }
124
151
  }
125
152
  deactivateMissingRuntimeTools(new Set(tools.keys()));
126
153
  for (const cfg of tools.values()) {
@@ -132,7 +159,7 @@ export function createAutoToolsRuntime(
132
159
  registerRuntimeTool(cfg);
133
160
  }
134
161
  if (warnings.length > 0) {
135
- notify(ctx, `Recipe tools: ${warnings.join("; ")}`, "warning");
162
+ notify(ctx, formatRecipeToolWarnings(warnings), "warning");
136
163
  }
137
164
  }
138
165
  return {
package/lib/schema.ts CHANGED
@@ -261,19 +261,35 @@ function collectWhenDeclarations(
261
261
  declarations.push(parseToolArgToken(`${bareCondition[1]}:bool=false`));
262
262
  }
263
263
 
264
+ function collectCommandTemplateConfigDeclarations(
265
+ config: CommandTemplates.CommandTemplateConfig | CommandTemplates.CommandTemplateValue,
266
+ declarations: ParsedToolArgToken[],
267
+ ): void {
268
+ if (typeof config === "string") {
269
+ collectTemplatePlaceholderDeclarations(config, declarations);
270
+ return;
271
+ }
272
+ if (Array.isArray(config)) {
273
+ for (const step of config)
274
+ collectCommandTemplateConfigDeclarations(step, declarations);
275
+ return;
276
+ }
277
+ if (config.template !== undefined)
278
+ collectCommandTemplateConfigDeclarations(config.template, declarations);
279
+ if (config.recover !== undefined)
280
+ collectCommandTemplateConfigDeclarations(config.recover, declarations);
281
+ for (const field of [config.timeout, config.delay, config.retry, config.repeat]) {
282
+ if (typeof field === "string")
283
+ collectTemplatePlaceholderDeclarations(field, declarations);
284
+ }
285
+ if (typeof config.when === "string") collectWhenDeclarations(config.when, declarations);
286
+ }
287
+
264
288
  function getTemplatePlaceholderDeclarations(
265
289
  config: CommandTemplates.CommandTemplateConfig,
266
290
  ): ParsedToolArgToken[] {
267
291
  const declarations: ParsedToolArgToken[] = [];
268
- for (const step of CommandTemplates.expandCommandTemplateConfigs(config)) {
269
- collectTemplatePlaceholderDeclarations(step.template, declarations);
270
- for (const field of [step.timeout, step.delay, step.retry]) {
271
- if (typeof field === "string")
272
- collectTemplatePlaceholderDeclarations(field, declarations);
273
- }
274
- if (typeof step.when === "string")
275
- collectWhenDeclarations(step.when, declarations);
276
- }
292
+ collectCommandTemplateConfigDeclarations(config, declarations);
277
293
  return declarations;
278
294
  }
279
295
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-actors",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
4
4
  "private": false,
5
5
  "description": "Actor runtime and orchestrator for agent-managed local processes",
6
6
  "keywords": [
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "lens-swarm",
3
+ "description": "General-purpose multi-lens review swarm. Launches independent reviewers by lens, then verifies, merges, judges, and normalizes the result.",
4
+ "tool": true,
5
+ "async": true,
6
+ "imports": {
7
+ "coordinator": "subagent-review-coordinator.json"
8
+ },
9
+ "args": [
10
+ "scope:string",
11
+ "lenses:array",
12
+ "model:string",
13
+ "thinking:string",
14
+ "tools:string",
15
+ "claim:string",
16
+ "evidence_policy:string",
17
+ "risk_policy:string",
18
+ "output_format:string"
19
+ ],
20
+ "defaults": {
21
+ "lenses": [
22
+ "correctness",
23
+ "architecture",
24
+ "operator UX"
25
+ ],
26
+ "thinking": "off",
27
+ "tools": "",
28
+ "claim": "The reviewed scope has clear, evidence-based findings, risks, and recommended next actions.",
29
+ "evidence_policy": "Cite inspected files, command outputs, or explicit uncertainty for every material claim.",
30
+ "risk_policy": "Preserve minority high-impact risks and ideas; separate confirmed issues from hypotheses.",
31
+ "output_format": "Markdown sections: Summary, Consensus Findings, Minority Findings, Verification, Judge Notes, Risks, Next Actions."
32
+ },
33
+ "mailbox": {
34
+ "accepts": [
35
+ "control.stop",
36
+ "control.cancel",
37
+ "control.kill"
38
+ ],
39
+ "emits": [
40
+ "review.completed",
41
+ "verification.completed",
42
+ "merge.completed",
43
+ "judge.completed",
44
+ "command.done",
45
+ "run.done",
46
+ "run.failed"
47
+ ]
48
+ },
49
+ "template": [
50
+ {
51
+ "name": "coordinator",
52
+ "values": {
53
+ "scope": "{scope}",
54
+ "lenses": "{lenses}",
55
+ "claim": "{claim}",
56
+ "reviewer_model": "{model}",
57
+ "verifier_model": "{model}",
58
+ "merger_model": "{model}",
59
+ "judge_model": "{model}",
60
+ "thinking": "{thinking}",
61
+ "tools": "{tools}",
62
+ "evidence_policy": "{evidence_policy}",
63
+ "risk_policy": "{risk_policy}",
64
+ "output_format": "{output_format}"
65
+ }
66
+ }
67
+ ]
68
+ }
@@ -2,7 +2,7 @@
2
2
  name: actors
3
3
  description: Highest-density practical guide for pi-actors. Read this skill whenever prompt and tools are not enough for spawn, message, inspect, actor runs, tools, recipes, command templates, async lifecycle, mailboxes, artifacts, and local orchestration mechanics.
4
4
  metadata:
5
- version: 0.16.0
5
+ version: 0.16.2
6
6
  ---
7
7
 
8
8
  # Actors (pi-actors)
@@ -216,7 +216,7 @@ Use packaged recipes by name with `spawn file=<name>` for async actors, or regis
216
216
  - Review chain: [`subagent-review`](../../recipes/subagent-review.json), [`subagent-verify`](../../recipes/subagent-verify.json), [`subagent-merge`](../../recipes/subagent-merge.json), [`subagent-judge`](../../recipes/subagent-judge.json), [`subagent-normalize`](../../recipes/subagent-normalize.json).
217
217
  - Planning/evidence: [`subagent-plan`](../../recipes/subagent-plan.json), [`subagent-task-card`](../../recipes/subagent-task-card.json), [`subagent-evidence-map`](../../recipes/subagent-evidence-map.json), [`subagent-contradiction-map`](../../recipes/subagent-contradiction-map.json), [`subagent-critic`](../../recipes/subagent-critic.json).
218
218
  - Handoffs: [`subagent-checkpoint`](../../recipes/subagent-checkpoint.json), [`subagent-followup`](../../recipes/subagent-followup.json), [`subagent-message`](../../recipes/subagent-message.json), [`subagent-artifact`](../../recipes/subagent-artifact.json), [`subagent-conflict-report`](../../recipes/subagent-conflict-report.json).
219
- - Composition: [`subagent-quorum`](../../recipes/subagent-quorum.json), [`subagent-review-coordinator`](../../recipes/subagent-review-coordinator.json).
219
+ - Composition: [`subagent-quorum`](../../recipes/subagent-quorum.json), [`subagent-review-coordinator`](../../recipes/subagent-review-coordinator.json), [`lens-swarm`](../../recipes/lens-swarm.json).
220
220
 
221
221
  ### Pipelines
222
222
 
@@ -2,7 +2,7 @@
2
2
  name: swarm
3
3
  description: Subagent orchestration with scoped locks and quorum consensus. Use for multi-model review, parallel scoped work, delegated audit, and coordinated subagent execution.
4
4
  metadata:
5
- version: 0.16.0
5
+ version: 0.16.2
6
6
  ---
7
7
 
8
8
  # Swarm