@llblab/pi-actors 0.46.0 → 0.47.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.
Files changed (78) hide show
  1. package/AGENTS.md +7 -5
  2. package/CHANGELOG.md +20 -0
  3. package/README.md +2 -1
  4. package/dist/lib/async-runs.d.ts +1 -0
  5. package/dist/lib/async-runs.js +4 -1
  6. package/dist/lib/execution.d.ts +1 -0
  7. package/dist/lib/execution.js +1 -0
  8. package/dist/lib/extension-runtime.js +25 -9
  9. package/dist/lib/inspector.js +1 -0
  10. package/dist/lib/prompts.d.ts +6 -5
  11. package/dist/lib/prompts.js +22 -23
  12. package/dist/lib/recipes-context.d.ts +12 -3
  13. package/dist/lib/recipes-context.js +28 -4
  14. package/dist/lib/recipes-discovery.d.ts +22 -0
  15. package/dist/lib/recipes-discovery.js +108 -23
  16. package/dist/lib/recipes-references.d.ts +18 -0
  17. package/dist/lib/recipes-references.js +129 -38
  18. package/dist/lib/registry.d.ts +23 -6
  19. package/dist/lib/registry.js +294 -101
  20. package/dist/lib/runtime.d.ts +30 -3
  21. package/dist/lib/runtime.js +108 -9
  22. package/dist/lib/tools-inspect.d.ts +3 -0
  23. package/dist/lib/tools-inspect.js +190 -26
  24. package/dist/lib/tools-local.d.ts +2 -2
  25. package/dist/lib/tools-local.js +5 -2
  26. package/dist/lib/tools-register.js +2 -1
  27. package/dist/lib/tools-response.js +7 -1
  28. package/dist/lib/tools-spawn.d.ts +2 -2
  29. package/dist/lib/tools-spawn.js +1 -1
  30. package/dist/lib/tools.d.ts +4 -1
  31. package/dist/lib/tools.js +2 -0
  32. package/dist/scripts/conformance.mjs +1 -0
  33. package/dist/skills/actors/SKILL.md +76 -65
  34. package/dist/skills/actors/references/diagnostics.md +44 -0
  35. package/dist/skills/actors/references/persistent-tools.md +74 -0
  36. package/dist/skills/actors/references/recipes.md +51 -0
  37. package/dist/skills/actors/references/runs.md +39 -0
  38. package/dist/skills/artifacts/SKILL.md +24 -7
  39. package/dist/skills/media/SKILL.md +35 -7
  40. package/dist/skills/project-work/SKILL.md +28 -7
  41. package/dist/skills/recipe-memory/SKILL.md +27 -7
  42. package/dist/skills/swarm/SKILL.md +41 -445
  43. package/dist/skills/swarm/references/development-swarm.md +87 -539
  44. package/dist/skills/swarm/references/review-swarms.md +115 -0
  45. package/docs/README.md +5 -5
  46. package/docs/recipe-library.md +15 -10
  47. package/docs/template-recipes.md +3 -1
  48. package/docs/tool-registry.md +18 -6
  49. package/lib/async-runs.ts +5 -1
  50. package/lib/execution.ts +2 -0
  51. package/lib/extension-runtime.ts +33 -14
  52. package/lib/inspector.ts +1 -0
  53. package/lib/prompts.ts +24 -24
  54. package/lib/recipes-context.ts +49 -4
  55. package/lib/recipes-discovery.ts +186 -25
  56. package/lib/recipes-references.ts +176 -44
  57. package/lib/registry.ts +441 -113
  58. package/lib/runtime.ts +147 -12
  59. package/lib/tools-inspect.ts +254 -28
  60. package/lib/tools-local.ts +9 -3
  61. package/lib/tools-register.ts +4 -3
  62. package/lib/tools-response.ts +7 -1
  63. package/lib/tools-spawn.ts +3 -2
  64. package/lib/tools.ts +4 -1
  65. package/package.json +1 -1
  66. package/scripts/conformance.mjs +1 -0
  67. package/skills/actors/SKILL.md +76 -65
  68. package/skills/actors/references/diagnostics.md +44 -0
  69. package/skills/actors/references/persistent-tools.md +74 -0
  70. package/skills/actors/references/recipes.md +51 -0
  71. package/skills/actors/references/runs.md +39 -0
  72. package/skills/artifacts/SKILL.md +24 -7
  73. package/skills/media/SKILL.md +35 -7
  74. package/skills/project-work/SKILL.md +28 -7
  75. package/skills/recipe-memory/SKILL.md +27 -7
  76. package/skills/swarm/SKILL.md +41 -445
  77. package/skills/swarm/references/development-swarm.md +87 -539
  78. package/skills/swarm/references/review-swarms.md +115 -0
@@ -0,0 +1,115 @@
1
+ # Review Swarms
2
+
3
+ Use this reference for independent review, delegated audit, research synthesis, quorum judgement, and post-merge review. Generic actor execution remains owned by `actors`.
4
+
5
+ ## Select breadth or confidence
6
+
7
+ ```text
8
+ Different lenses on one target → breadth → lens swarm
9
+ Same exact claim, independent judges → confidence → quorum
10
+ Important lenses each need repeated judges → breadth + confidence → lens swarms of quorums
11
+ ```
12
+
13
+ Use the smallest shape that covers the decision risk. A lens swarm of quorums is reserved for high-impact security, financial, governance, migration, or release decisions.
14
+
15
+ Primary Recipes:
16
+
17
+ - `swarm/lens-review` for parallel risk lenses plus verification, merge, judge, and normalized result;
18
+ - `swarm/quorum-review` for one prompt judged independently by explicitly selected models;
19
+ - `swarm/research-synthesis` for plan, evidence map, contradictions, verification, and risk-first synthesis;
20
+ - `swarm/architect` for competing directions and one validated smallest next slice;
21
+ - `swarm/review-readiness` for a multi-lens ship/readiness verdict.
22
+
23
+ ## Lens selection
24
+
25
+ Choose lenses from plausible failure modes, not from a fixed catalog. Common software lenses include correctness, architecture, security, tests, concurrency, data integrity, performance, operator UX, accessibility, maintainability, documentation, and release risk.
26
+
27
+ A good lens assignment states:
28
+
29
+ ```markdown
30
+ Target:
31
+ Question or claim:
32
+ Lens:
33
+ Evidence required:
34
+ Out of scope:
35
+ Severity rule:
36
+ Output shape:
37
+ Stop condition:
38
+ ```
39
+
40
+ Do not ask every reviewer to cover everything. Keep reviewers independent until synthesis so one early narrative does not contaminate all findings.
41
+
42
+ ## Quorum design
43
+
44
+ A quorum keeps the target, claim, evidence standard, and output shape constant while varying independent judges. Before fanout:
45
+
46
+ 1. define the exact decision claim;
47
+ 2. define what counts as supporting and contradicting evidence;
48
+ 3. select the minimum successful threshold;
49
+ 4. choose concurrency and timeout bounds;
50
+ 5. preflight model and tool availability;
51
+ 6. define how partial results affect status.
52
+
53
+ Provider or model failure reduces available evidence; it is not a vote. When evidence falls below threshold, mark the result degraded or insufficient data.
54
+
55
+ ## Research evidence
56
+
57
+ Research participants separate source discovery, verification, contradiction mapping, and synthesis when stakes justify it.
58
+
59
+ - Every material claim traces to a source note, inspected artifact, or explicit uncertainty.
60
+ - Source quality and confidence remain visible.
61
+ - Contradictory evidence is first-class output.
62
+ - Missing source classes block overconfident synthesis.
63
+ - Unsafe or unverifiable evidence is excluded with a reason.
64
+
65
+ Do not turn a research swarm into an automatic publication pipeline. Stop at the caller's evidence and decision boundary.
66
+
67
+ ## Merge protocol
68
+
69
+ A merger is a synthesis participant, not a formatter. It may deduplicate, rank, connect evidence, and add a grounded `merger finding`, but it may not fabricate support.
70
+
71
+ For serious quorum work, use a clean-context merger. The merger receives all retained participant outputs and must produce:
72
+
73
+ - status: complete, degraded, or insufficient data;
74
+ - consensus findings and vote shape where applicable;
75
+ - minority high-impact findings;
76
+ - contradictions and unresolved evidence gaps;
77
+ - merger findings, clearly labeled;
78
+ - confidence and limitations;
79
+ - ordered next actions.
80
+
81
+ Keep raw participant outputs until the merged result is accepted. Preserve attribution for major findings. Never promote repeated low-value observations merely because they are numerous, and never discard a severe evidence-backed minority finding merely because it is unique.
82
+
83
+ ## Conflict and disagreement
84
+
85
+ Disagreement can mean different assumptions, different evidence, ambiguous criteria, or real uncertainty. The merger records:
86
+
87
+ ```markdown
88
+ Finding:
89
+ Supporting participants and evidence:
90
+ Contradicting participants and evidence:
91
+ Assumption difference:
92
+ Impact if minority view is correct:
93
+ Resolution status:
94
+ Next evidence needed:
95
+ ```
96
+
97
+ Resolve only when evidence supports resolution. Otherwise preserve the disagreement and lower confidence.
98
+
99
+ ## Post-merge review
100
+
101
+ Use a fresh reviewer when the merged result will drive consequential implementation or decisions. The post-merge reviewer checks the report, not the original target by default:
102
+
103
+ - evidence traceability;
104
+ - honest severity;
105
+ - correct quorum accounting;
106
+ - preserved minority findings;
107
+ - unsupported merger narrative;
108
+ - actionable next steps;
109
+ - retained uncertainty and contradictions.
110
+
111
+ Possible decisions are accept, accept with notes, revise merge, rerun bounded quorum, or escalate. Rerun only when the raw evidence or scope is genuinely insufficient, not because the verdict is inconvenient.
112
+
113
+ ## Completion and stop rules
114
+
115
+ A review swarm is complete only when requested evidence is retained, threshold status is explicit, synthesis preserves dissent, and the coordinator can state the safe decision or next evidence slice. Stop when the claim is ambiguous, target changes during review, preflight fails, evidence is not inspectable, threshold cannot be met, or merger independence required by the stakes is unavailable.
package/docs/README.md CHANGED
@@ -12,9 +12,9 @@ Living index of all documentation in the `/docs` directory.
12
12
  - [recipe-library.md](./recipe-library.md) — Packaged standard recipe library such as async subagents, coordinator pipelines, utilities, and music playback
13
13
  - [releasing.md](./releasing.md) — Guarded tag validation, npm Trusted Publisher setup, registry verification, and GitHub Release convergence
14
14
 
15
- ## Root Context
15
+ ## Project Surfaces
16
16
 
17
- - [Project Context](../AGENTS.md)
18
- - [Open Backlog](../BACKLOG.md)
19
- - [Changelog](../CHANGELOG.md)
20
- - [Root README](../README.md)
17
+ - [Human product entrypoint](../README.md)
18
+ - [Implementation protocol](../AGENTS.md)
19
+ - [Future work](../BACKLOG.md)
20
+ - [Completed delivery history](../CHANGELOG.md)
@@ -6,34 +6,39 @@ Active Skills provide maintained execution graphs and service definitions. Skill
6
6
 
7
7
  ### Repository and delivery
8
8
 
9
- - `project-work/repo-health` — repository inspection and bounded health artifact.
10
- - `project-work/docs-maintenance` — documentation analysis and artifact preparation.
11
- - `project-work/release-readiness` — release checks and readiness artifact.
12
- - `project-work/release-summary` — release-summary artifact.
13
- - `swarm/development-tasking` — task-card and implementation planning pipeline.
9
+ - `project-work/repo-health` — repository status, recent history, docs surface, trusted validation, and bounded report content.
10
+ - `project-work/docs-maintenance` — documentation consistency evidence and a maintenance plan; it does not edit documentation.
11
+ - `project-work/release-readiness` — multi-lens readiness verdict and blockers; it does not publish.
12
+ - `project-work/release-summary` — evidence-only release summary and PR-body draft with no external release side effect.
13
+ - `project-work/run-ops` — read-only report over existing Run state; it does not send Control.
14
+ - `swarm/development-tasking` — bounded task-card and scope-critique pipeline.
14
15
 
15
16
  ### Review and synthesis
16
17
 
17
18
  - `swarm/quorum-review` — parallel reviewers with quorum-oriented synthesis.
18
19
  - `swarm/review-readiness` — review plus readiness stages.
19
- - `swarm/research-synthesis` — evidence-oriented research synthesis.
20
- - `swarm/lens-review` — configurable repeated review lenses.
20
+ - `swarm/research-synthesis` — evidence map, contradiction analysis, and risk-first research synthesis.
21
+ - `swarm/lens-review` — different independent risk lenses for breadth.
22
+ - `swarm/architect` — competing architecture directions and one validated smallest next slice.
21
23
  - `swarm/subagent-review-coordinator` — lower-level review/verify/merge/judge composition.
22
24
 
23
25
  Callers should own model, thinking, concurrency, quorum, and mission policy. Review pipelines preflight provider/model availability before expensive fanout.
24
26
 
25
27
  ### Artifacts
26
28
 
27
- - `artifacts/report` — prepare one artifact body.
28
- - `artifacts/write` — prepare and deterministically write an artifact.
29
+ - `artifacts/report` — prepare normalized report content without committing a filesystem write.
30
+ - `artifacts/write` — prepare and deterministically write one artifact with explicit create/overwrite/append policy.
29
31
  - `artifacts/bundle` — optional validation, artifact write, manifest generation, and manifest write.
30
32
  - `artifacts/file-write` — deterministic create/overwrite/append helper.
31
33
  - `artifacts/manifest` — artifact manifest generation.
32
34
 
33
35
  Artifact pipelines terminate in files/manifests and result evidence; they do not fabricate communication events.
34
36
 
35
- ### Controlled services
37
+ ### Media and controlled services
36
38
 
39
+ - `media/playlist-scan` — shallow unfiltered path inventory.
40
+ - `media/playlist-build` — extension-filtered `paths`, `m3u`, or `inline` playlist output; it does not create a playlist file.
41
+ - `media/library` — filtered playlist plus bounded library-report content; `artifact_path` alone is not durable-write proof.
37
42
  - `media/player` — playback service with declared playback actions, `controls.jsonl`, generation-fenced endpoint readiness, state artifact, and playback Trace. Player selection is `player:enum(auto,mpv,afplay,ffplay,cvlc,play,wmp)=auto`.
38
43
  - `actors/resource-locker` — optional queue/lease-lock service with explicit owner/resource input, lock Trace, and a 512-record/1 MiB atomically retained journal.
39
44
 
@@ -147,7 +147,9 @@ Resolution fails before launch when required current policy is unavailable. The
147
147
 
148
148
  ## Resolution Context
149
149
 
150
- User Recipes under `~/.pi/agent/recipes` remain intentionally registered tools, not an ambient import namespace. Each session receives an immutable active-Skill resolution context from Pi's loaded Skill metadata; pi-actors does not scan ambient Skill roots independently or keep a process-global mutable namespace. A launch captures its resolved graph, so later Skill changes affect only future launches. An invalid or missing exact target fails without fallback. Disabled Recipes cannot launch. Registry watchers converge after atomic changes without executing partial definitions.
150
+ User Recipes under `~/.pi/agent/recipes` remain intentionally registered tools, not an ambient import namespace. Each session receives one immutable resolution context from Pi's loaded Skill metadata; spawn, user-Recipe admission, registration, schema derivation, live inspection, and watcher reconciliation consume that same context rather than scanning ambient Skill roots or keeping a process-global mutable namespace. A launch captures its resolved graph, so later Skill changes affect only future launches. An invalid or missing exact target fails without fallback. Disabled Recipes cannot launch. Registry watchers converge after atomic changes without executing partial definitions.
151
+
152
+ Active-Skill catalog inventory is fail-soft diagnostic state, not exact-resolution authority. Invalid components are reported individually and make the catalog partial while unrelated valid `<skill>/<recipe>` references remain exactly resolvable.
151
153
 
152
154
  ## Validation
153
155
 
@@ -6,7 +6,7 @@
6
6
  ~/.pi/agent/recipes/*.json
7
7
  ```
8
8
 
9
- Each active valid Recipe becomes an agent-callable tool. `register_tool` creates, updates, promotes, or deletes these files through fenced mutation paths.
9
+ Each valid Recipe admitted against the current session context can become an agent-callable tool. `register_tool` creates, updates, promotes, or deletes these files through fenced mutation paths and reports the resulting activation state.
10
10
 
11
11
  ## Registration
12
12
 
@@ -16,13 +16,23 @@ Register a command template:
16
16
  register_tool name=repo_check template="make check" description="Run repository checks"
17
17
  ```
18
18
 
19
- Register a typed/defaulted template or Recipe-backed definition when reuse justifies it. String templates execute directly without shell semantics; use arrays or an explicit trusted script for sequencing.
19
+ Specialize a maintained Recipe without copying its contract:
20
+
21
+ ```text
22
+ register_tool name=music_player from=media/player defaults={"source":"~/Music/1MIX"}
23
+ ```
24
+
25
+ `from`, `template`, and `draft` are distinct source modes. `from` accepts exact `<skill>/<recipe>` identity or an explicit `.json` / `.md` path and inherits async behavior, args/types, source defaults, artifacts, Control, and runtime-owned origins. `defaults` may set only effective caller-owned args and must satisfy their types. `template` is only for trusted command definitions; public `values` authoring has been removed in favor of caller defaults or an authored Recipe file.
20
26
 
21
27
  Promote an immutable captured draft only with its draft path and explicit target name. Name collisions require `update=true`. Invalid content fails before active mutation.
22
28
 
29
+ Registration resolves the effective delegated contract before persistence, then reports logical `source`, effective `required_args` / `optional_args`, and distinct `persisted`, `registry_active`, `host_registered`, `active_tool`, and `callable_now` states. A callable result points to the actual generated tool as the next action. An uncallable result names its `activation_boundary` and status/doctor action without suggesting spawn as a substitute. Diagnose one maintained source with `inspect target=recipes view=doctor identity=<skill>/<recipe>`; diagnose final activation, source, schema summary, and separate spawn/tool usage with `inspect target=tool:<name> view=status`. Treat the tool as callable in the current session only when `callable_now` is true; persistence alone is not activation proof. Registration results omit raw persisted paths and executable template/config payloads.
30
+
23
31
  ## Resolution
24
32
 
25
- User Recipes are the only file-discovered tool source. Invalid or disabled user entries fail closed. Active Skill Recipes remain exact components outside tool discovery. Runtime reload watches the user Recipe root and converges after atomic changes; stale watcher generations cannot replace current registration state.
33
+ User Recipes are the only file-discovered tool source. Invalid or disabled user entries fail closed. Active Skill Recipes remain exact components outside tool discovery. Spawn, registration, registry admission, schema derivation, and live inspection resolve against one immutable session context containing the current working directory and active Skills. Runtime reload watches the user Recipe root using that current context and converges after atomic changes; stale watcher generations cannot replace current registration state.
34
+
35
+ Skill component inventory is diagnostic and fail-soft: valid components remain listed and exactly resolvable when an unrelated component is rejected. Recipe inspection reports rejected components and marks the catalog partial instead of treating one bad component as an empty catalog.
26
36
 
27
37
  Inspect registry state with:
28
38
 
@@ -31,7 +41,9 @@ inspect target=recipes view=status
31
41
  inspect target=tool:<name> view=status
32
42
  ```
33
43
 
34
- Recipe inspection reports active, shadowed, invalid, disabled, diagnostic, risk, usage, and review evidence. Tool inspection reports the current capability definition/schema; a registered tool is not a running actor.
44
+ Recipe inspection reports generation, scan/watch state, active, shadowed, invalid, disabled, component rejection, diagnostic, risk, usage, and review evidence. Tool status reports current activation plus separate `tool_calls` and `spawn_calls`; tool schema reports the caller-owned capability contract. A registered tool is not a running actor.
45
+
46
+ `spawn recipe=<name>` executes a Recipe and reports `launch_kind: "spawn"`; it does not prove that a registered tool was exposed or invoked. Registered-tool execution reports `launch_kind: "tool"`.
35
47
 
36
48
  ## Automatic Review
37
49
 
@@ -59,9 +71,9 @@ Set `PI_ACTORS_AUTOMATIC_REVIEW=off` to disable scheduling and safe-boundary act
59
71
 
60
72
  Usage and lineage live in locked metadata ledgers rather than authored Recipe files. Launch accounting briefly shares the portfolio transaction fence so quarantine cannot invalidate an already-authorized launch. Revision snapshots, rollback, demotion, rename, and identical-source deduplication retain CAS/hash evidence.
61
73
 
62
- ## Wrapping Existing Recipes
74
+ ## Specializing Existing Recipes
63
75
 
64
- Prefer a small user-root wrapper that imports a maintained Recipe by exact `<skill>/<recipe>` identity and delegates by alias. Skill Recipes remain components and are never exposed merely because their Skill is active. Do not duplicate executable templates, defaults, Control declarations, artifacts, or runtime-owned `{recipe_dir}`/`{skill_dir}`. Install only specific capabilities; internal automatic-review Recipes must not become user-callable tools.
76
+ Use `register_tool from=<skill>/<recipe> defaults={...}` for one maintained capability under a persistent name or narrower defaults. The stored user Recipe remains compact direct delegation; it does not copy async, args/types, Control, artifacts, helpers, or runtime-owned `{recipe_dir}`/`{skill_dir}`. Named imports remain for multi-node Recipe composition, not one-source specialization. Skill Recipes remain components and are never exposed merely because their Skill is active. Install only specific capabilities; internal automatic-review Recipes must not become user-callable tools.
65
77
 
66
78
  ## Safety
67
79
 
package/lib/async-runs.ts CHANGED
@@ -161,6 +161,7 @@ export interface AsyncRunMeta {
161
161
  argv: string[];
162
162
  createdAt: string;
163
163
  cwd: string;
164
+ launch_kind?: AsyncRunLaunchSource;
164
165
  launch_source?: AsyncRunLaunchSource;
165
166
  launch_correlation?: {
166
167
  correlation_id?: string;
@@ -600,7 +601,10 @@ export function startRun(
600
601
  createdAt: new Date().toISOString(),
601
602
  cwd,
602
603
  ...(startParams.launch_source
603
- ? { launch_source: startParams.launch_source }
604
+ ? {
605
+ launch_kind: startParams.launch_source,
606
+ launch_source: startParams.launch_source,
607
+ }
604
608
  : {}),
605
609
  ...(startParams.launch_correlation
606
610
  ? { launch_correlation: startParams.launch_correlation } : {}),
package/lib/execution.ts CHANGED
@@ -83,6 +83,7 @@ export interface RegisteredToolExecutionResult {
83
83
  command: string;
84
84
  fullOutputPath?: string;
85
85
  killed: boolean;
86
+ launch_kind: "tool";
86
87
  stderrBytes?: number;
87
88
  stderrCapturedBytes?: number;
88
89
  stderrFile?: string;
@@ -1136,6 +1137,7 @@ export async function executeRegisteredTool(
1136
1137
  command,
1137
1138
  fullOutputPath: result.stdoutFile ?? formatted.fullOutputPath,
1138
1139
  killed: result.killed,
1140
+ launch_kind: "tool",
1139
1141
  ...getCaptureDetails(result),
1140
1142
  ...(executed.branches.length > 0 ? { branches: executed.branches } : {}),
1141
1143
  ...(executed.failures.length > 0
@@ -9,6 +9,7 @@ import * as CommandTemplates from "./command-templates.ts";
9
9
  import * as Paths from "./paths.ts";
10
10
  import * as Pi from "./pi.ts";
11
11
  import * as Prompts from "./prompts.ts";
12
+ import * as RecipeResolution from "./recipes-context.ts";
12
13
  import * as RecipesReferences from "./recipes-references.ts";
13
14
  import * as RunUiRuntime from "./run-ui-runtime.ts";
14
15
  import * as Runtime from "./runtime.ts";
@@ -34,14 +35,21 @@ export function createActorExtensionRuntime(
34
35
  pi: Pi.ExtensionAPI,
35
36
  ): ActorExtensionRuntime {
36
37
  let activeRunContext: Pi.ExtensionContext | undefined;
37
- const skillContextsBySession = new Map<
38
+ const recipeResolutionContextsBySession = new Map<
38
39
  string,
39
- RecipesReferences.ActiveSkillRecipeContext
40
+ RecipeResolution.RecipeResolutionContext
40
41
  >();
41
42
  const getRunOwnerId = Pi.getSessionId;
42
- const getSkillContext = (ctx: Pi.ExtensionContext) =>
43
- skillContextsBySession.get(getRunOwnerId(ctx)) ??
44
- RecipesReferences.EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT;
43
+ const getRecipeResolutionContext = (ctx: Pi.ExtensionContext) => {
44
+ const sessionId = getRunOwnerId(ctx);
45
+ const resolutionContext = recipeResolutionContextsBySession.get(sessionId);
46
+ if (!resolutionContext) {
47
+ throw new Error(
48
+ `Recipe resolution context is unavailable for session ${sessionId}.`,
49
+ );
50
+ }
51
+ return resolutionContext;
52
+ };
45
53
  const automaticReview = AutomaticReviewRuntime.createAutomaticReviewRuntime({
46
54
  getActiveContext: () => activeRunContext,
47
55
  getRunOwnerId,
@@ -67,7 +75,7 @@ export function createActorExtensionRuntime(
67
75
  if (ctx && typeof ctx === "object") {
68
76
  nextArgs[4] = {
69
77
  ...(ctx as Record<string, unknown>),
70
- activeSkillRecipeContext: getSkillContext(
78
+ recipeResolutionContext: getRecipeResolutionContext(
71
79
  ctx as Pi.ExtensionContext,
72
80
  ),
73
81
  getThinkingLevel: () => pi.getThinkingLevel(),
@@ -85,6 +93,7 @@ export function createActorExtensionRuntime(
85
93
  configPath: Paths.EXTENSION_RUNTIME_PATHS.configPath,
86
94
  exec: CommandTemplates.execCommandTemplate,
87
95
  getActiveTools: () => pi.getActiveTools(),
96
+ getAllTools: () => pi.getAllTools(),
88
97
  registerTool: (definition) => {
89
98
  const wrapped = withCurrentThinkingContext(definition);
90
99
  actorToolDefinitions.set(wrapped.name, wrapped);
@@ -93,13 +102,22 @@ export function createActorExtensionRuntime(
93
102
  reservedToolNames: Tools.RESERVED_TOOL_NAMES,
94
103
  setActiveTools: (toolNames) => pi.setActiveTools(toolNames),
95
104
  });
96
- const recipeReload = Runtime.createRecipeToolReloadWatcher(runtime);
105
+ const recipeReload = Runtime.createRecipeToolReloadWatcher(runtime, {
106
+ getResolutionContext: () =>
107
+ activeRunContext
108
+ ? getRecipeResolutionContext(activeRunContext)
109
+ : undefined,
110
+ });
97
111
  return {
98
112
  beforeAgentStart(systemPrompt, skills, ctx) {
99
- skillContextsBySession.set(
100
- getRunOwnerId(ctx),
113
+ const sessionId = getRunOwnerId(ctx);
114
+ const resolutionContext = RecipeResolution.createRecipeResolutionContext(
115
+ sessionId,
116
+ ctx.cwd,
101
117
  RecipesReferences.createActiveSkillRecipeContext(skills),
102
118
  );
119
+ recipeResolutionContextsBySession.set(sessionId, resolutionContext);
120
+ runtime.loadTools(ctx, resolutionContext);
103
121
  return {
104
122
  systemPrompt: `${systemPrompt}\n\n${Prompts.ONBOARDING_SYSTEM_PROMPT}`,
105
123
  };
@@ -113,16 +131,17 @@ export function createActorExtensionRuntime(
113
131
  if (activeRunContext === ctx) automaticReview.schedule();
114
132
  },
115
133
  onSessionShutdown(reason, ctx) {
116
- skillContextsBySession.delete(getRunOwnerId(ctx));
134
+ recipeResolutionContextsBySession.delete(getRunOwnerId(ctx));
117
135
  activeRunContext = undefined;
118
136
  automaticReview.close();
119
137
  recipeReload.close();
120
138
  runUiRuntime.shutdown(reason, ctx);
121
139
  },
122
140
  async onSessionStart(ctx) {
123
- skillContextsBySession.set(
124
- getRunOwnerId(ctx),
125
- RecipesReferences.EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT,
141
+ const sessionId = getRunOwnerId(ctx);
142
+ recipeResolutionContextsBySession.set(
143
+ sessionId,
144
+ RecipeResolution.createEmptyRecipeResolutionContext(sessionId, ctx.cwd),
126
145
  );
127
146
  ctx.ui.setWidget("zz-pi-actors-comms", undefined);
128
147
  activeRunContext = ctx;
@@ -132,7 +151,6 @@ export function createActorExtensionRuntime(
132
151
  await Temp.prepareExtensionTempDir(Paths.EXTENSION_RUNTIME_PATHS.tempDir);
133
152
  if (activeRunContext !== ctx) return;
134
153
  automaticReview.start(ctx);
135
- runtime.loadTools(ctx);
136
154
  runUiRuntime.start(ctx);
137
155
  recipeReload.watch(ctx);
138
156
  },
@@ -148,6 +166,7 @@ export function createActorExtensionRuntime(
148
166
  runtime.getTools(),
149
167
  (activeName) => actorToolDefinitions.get(activeName),
150
168
  ),
169
+ getRuntimeToolStatus: runtime.getToolStatus,
151
170
  handleRuntimeControl: automaticReview.handleControl,
152
171
  registryRuntime: runtime,
153
172
  setActiveTools: (toolNames) => pi.setActiveTools(toolNames),
package/lib/inspector.ts CHANGED
@@ -183,6 +183,7 @@ export function readActorInspectorRecipe(
183
183
  logical_reference: primaryLogicalReference,
184
184
  ...(typeof primary?.skill === "string" ? { skill: primary.skill } : {}),
185
185
  source_kind: primarySourceKind,
186
+ launch_kind: meta.launch_kind ?? meta.launch_source,
186
187
  launch_source: meta.launch_source,
187
188
  }),
188
189
  launch: redactedRecord({
package/lib/prompts.ts CHANGED
@@ -5,52 +5,52 @@
5
5
  */
6
6
 
7
7
  export const REGISTER_TOOL_DESCRIPTION =
8
- "Register a persistent custom tool from a command template, template recipe path, or co-located template recipe. " +
9
- "Definitions are stored as recipe files under ~/.pi/agent/recipes across reloads. " +
10
- "Use update=true to overwrite an existing tool, template=null/empty to delete.";
8
+ "Register a persistent custom tool from one maintained Recipe, command template, or captured draft. " +
9
+ "Use from for Recipe specialization, template for trusted commands, or draft for promotion. " +
10
+ "Definitions persist under ~/.pi/agent/recipes; activation is reported separately.";
11
11
 
12
12
  export const REGISTER_TOOL_PROMPT_SNIPPET =
13
- "Register persistent command templates as agent-callable tools";
13
+ "Register persistent Recipes or command templates as agent-callable tools";
14
14
 
15
15
  export const REGISTER_TOOL_GUIDELINES = [
16
- "Use register_tool to wrap trusted local commands, scripts, programs, libraries, or template recipes as persistent pi tools.",
17
- "After register_tool succeeds, the new tool is immediately callable and remains available after reload.",
16
+ "Use register_tool from=<skill>/<recipe> with defaults={...} to specialize a maintained Recipe without copying its contract.",
17
+ "Use register_tool template only for trusted command templates, and use register_tool draft only for captured draft promotion.",
18
+ "After register_tool succeeds, trust its callable_now and activation result; persistence alone is not callability.",
18
19
  'Set template=null or template="" in register_tool to delete a persisted tool.',
19
20
  "Set update=true in register_tool to overwrite an existing tool registration.",
20
21
  ];
21
22
 
22
- export const ONBOARDING_SYSTEM_PROMPT = `pi-actors quick model:
23
- - Local-first actor memory: persist trusted local capabilities instead of rebuilding shell recipes.
24
- - Layers: task -> command template -> recipe/tool -> spawn -> run:<id>; tool:<name> wraps registered capabilities.
25
- - Command templates stay sync and shell-free: string leaves split into executable + argv, infer .js/.mjs through node→bun→deno run and .sh through bash, and treat operators such as && as literal arguments; use template arrays for sequencing or an explicit trusted shell/script when shell semantics are required. Flags include args/defaults, parallel, concurrency, min_successful, when, timeout, delay, retry, failure, recover, repeat, accept_output, output.
26
- - Placeholders support typed/default args plus {value??fallback} and {flag?yes:no}.
27
- - ~/.pi/agent/recipes/*.json is actor muscle memory: every recipe there is auto-registered as an agent tool across sessions; register_tool writes there.
28
- - Recipes own template directly and may declare metadata/defaults/imports/control/artifacts; files >1 MiB or import depth >32 fail closed.
29
- - Recipe imports are local variables; imported recipes are definitions, not nested async runs; parent async:true creates one run.
30
- - Actor-mode trigger: if work may outlive this turn, need steering/follow-up/artifacts, run as a service, fan out, or be resumed/inspected later, use spawn -> message -> inspect instead of ad hoc shell backgrounding.
31
- - Use spawn/message/inspect for actor-level start/send/observe; short foreground checks can stay ordinary tools/templates; avoid internal transport vocabulary in public guidance.
32
- - Run state lives under ~/.pi/agent/tmp/pi-actors/runs. Inspect intentionally and avoid busy-polling. Terminal and coordinator-bound notifications queue as Pi follow-ups so concurrently completed actors can reach the coordinator after current work instead of steering between tool calls. Terminal follow-up content stays minimal: run, status, one base path, and relative artifact names only; semantic output stays in non-LLM details and run state. When a deferred actor result gates the next step, wait for its terminal follow-up; do not schedule continuation loops, repeatedly inspect, or mutate its reviewed scope while it runs. Inspect early only for an operator request, a meaningful actor event, or diagnosis of an overdue/stuck run.
33
- - Maintain ~/.pi/agent/recipes like MEMORY.md for capabilities: keep useful tools, curate stale ones, and fix/remove/disable invalid recipes flagged by registry warnings; active-Skill and explicit file Recipes remain components outside user tool discovery; offer to save successful recurring patterns only after confirmation.
34
- - Prefer maintained active-Skill Recipes with spawn recipe=<skill>/<recipe> before ad hoc scripts/wrappers; explicit file Recipes use exact .json/.md paths; review swarms inherit current model/thinking, preflight before fanout, and expose quorum/concurrency/TTL knobs unless explicit args are passed.
35
- - For any non-trivial actor use or pi-actors change, read the bundled actors skill first. Before launching multiple actors/subagents for parallel implementation, independent artifact generation, delegated audit, or review, also read the bundled swarm skill; the coordinator owns decomposition, disjoint scopes, launch correctness, integration, and final validation. For deeper guidance, inspect installed extension sources/docs/recipes because README/docs are not automatically in context.`;
23
+ export const ONBOARDING_SYSTEM_PROMPT = `pi-actors Skill routing:
24
+ - Treat active bundled Skills as the operating authority.
25
+ - For non-trivial pi-actors operation, diagnosis, or development, load and read the actors Skill before acting.
26
+ - For work requiring multiple actors or subagents, additionally load and read the swarm Skill.
27
+ - For capability-specific selection or constraints, load the owning capability Skill; actors owns generic mechanics and swarm owns multi-actor methodology.
28
+ - Keep a Skill Recipe distinct from a registered tool and a Recipe spawn distinct from registered-tool invocation; actors owns the proof rules.
29
+ - Treat persistence or registration as distinct from current callability; actors owns activation proof.
30
+ - On failure or disagreement, preserve the logical Recipe identity, stop, and follow actors diagnosis; never bypass the owning Skills with copied contracts, helper paths, shell evaluation, or background-process workarounds.
31
+ - If a capability Skill conflicts with actors about generic mechanics, follow actors and report the stale capability guidance.
32
+ - README and docs are human-facing references, not the normal agent operating path.
33
+ - AGENTS, source, and tests are implementation protocol and evidence; use them when changing or debugging the extension, not as substitutes for operating Skills.`;
36
34
 
37
35
  export const REGISTER_TOOL_PARAM_DESCRIPTIONS = {
38
36
  name: "Tool name in snake_case (e.g., 'transcribe')",
39
37
  description:
40
38
  "Describe what the tool does for the LLM. Required unless deleting; omitted updates keep the old description.",
39
+ from:
40
+ "Recipe to specialize by canonical <skill>/<recipe> identity or explicit .json/.md path. Inherits async, args/types, source defaults, artifacts, Control, and runtime origins.",
41
+ defaults:
42
+ "Optional caller-owned defaults. Keys and values must satisfy the effective source or command-template argument contract.",
41
43
  draft:
42
- "Promote a draft recipe path from ~/.pi/agent/recipes/drafts into an active named recipe under ~/.pi/agent/recipes. Requires name; use update=true to overwrite.",
44
+ "Promote a captured draft Recipe path from ~/.pi/agent/recipes/drafts. This is a source mode; do not combine it with from or template.",
43
45
  async:
44
46
  "Set true for a co-located async template recipe. Omit for ordinary command templates or file-backed recipe references.",
45
47
  template:
46
- "Command template with {arg} or {arg=default} placeholders, or a template recipe JSON path/name. With async, this is the co-located recipe body. Bare recipe names resolve under ~/.pi/agent/recipes. Omitted updates keep the old template. Empty string deletes the tool.",
48
+ "Trusted command template with {arg} or {arg=default} placeholders. To specialize a Recipe, use from instead. Omitted updates keep the old template; empty string deletes the tool.",
47
49
  templateArray:
48
50
  "Sequential command-template composition array. Leaves may be strings or objects with template/defaults/timeout/retry/failure/recover.",
49
51
  templateNull: "Delete the tool when template is null.",
50
52
  args: "Optional comma-separated placeholder declarations. Usually omit because args are derived from template placeholders. Interactive shorthand defaults are accepted and normalized. Example: file,lang,mode=fast",
51
53
  update: "Set to true to overwrite an existing tool registration.",
52
- values:
53
- "Optional default runtime placeholder values for a co-located template recipe.",
54
54
  } as const;
55
55
 
56
56
  export function formatRegisteredToolPromptSnippet(template: unknown): string {
@@ -1,15 +1,60 @@
1
1
  /**
2
- * Recipe context prompt assembly.
3
- * Zones: async runner prompt context, recipe provenance, LLM child launches
4
- * Owns compact actor recipe context records appended to child-agent prompts.
2
+ * Recipe context contracts and prompt assembly.
3
+ * Zones: live session resolution, async runner prompt context, recipe provenance, LLM child launches
4
+ * Owns the immutable live Recipe environment and compact actor context appended to child-agent prompts.
5
5
  */
6
6
 
7
+ import { createHash } from "node:crypto";
7
8
  import { writeFileSync } from "node:fs";
8
- import { basename } from "node:path";
9
+ import { basename, resolve } from "node:path";
9
10
 
10
11
  import type { CommandTemplateActorRecipeContext } from "./command-templates.ts";
12
+ import * as RecipesReferences from "./recipes-references.ts";
11
13
  import type { TemplateRecipeContextRecord } from "./recipes-references.ts";
12
14
 
15
+ export interface RecipeResolutionContext {
16
+ readonly activeSkills: RecipesReferences.ActiveSkillRecipeContext;
17
+ readonly cwd: string;
18
+ readonly generation: string;
19
+ readonly sessionId: string;
20
+ }
21
+
22
+ export function createRecipeResolutionContext(
23
+ sessionId: string,
24
+ cwd: string,
25
+ activeSkills: RecipesReferences.ActiveSkillRecipeContext,
26
+ ): RecipeResolutionContext {
27
+ const normalizedSessionId = sessionId.trim();
28
+ if (!normalizedSessionId) throw new Error("Recipe resolution session id is required.");
29
+ const normalizedCwd = resolve(cwd);
30
+ const generation = createHash("sha256")
31
+ .update(
32
+ JSON.stringify({
33
+ activeSkills: RecipesReferences.getActiveSkillRecipeNamespaces(activeSkills),
34
+ cwd: normalizedCwd,
35
+ sessionId: normalizedSessionId,
36
+ }),
37
+ )
38
+ .digest("hex");
39
+ return Object.freeze({
40
+ activeSkills,
41
+ cwd: normalizedCwd,
42
+ generation,
43
+ sessionId: normalizedSessionId,
44
+ });
45
+ }
46
+
47
+ export function createEmptyRecipeResolutionContext(
48
+ sessionId: string,
49
+ cwd: string,
50
+ ): RecipeResolutionContext {
51
+ return createRecipeResolutionContext(
52
+ sessionId,
53
+ cwd,
54
+ RecipesReferences.EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT,
55
+ );
56
+ }
57
+
13
58
  export interface MarkedRecipeContextRecord extends TemplateRecipeContextRecord {
14
59
  you_are_here?: true;
15
60
  you_are_here_path?: string;