@llblab/pi-actors 0.45.1 → 0.46.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.
Files changed (228) hide show
  1. package/AGENTS.md +9 -7
  2. package/BACKLOG.md +582 -0
  3. package/CHANGELOG.md +17 -1
  4. package/README.md +27 -13
  5. package/dist/fixtures/protocol/recipe-summary.json +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/lib/async-runs.d.ts +5 -1
  8. package/dist/lib/async-runs.js +26 -24
  9. package/dist/lib/automatic-review-runtime.d.ts +2 -0
  10. package/dist/lib/automatic-review-runtime.js +12 -5
  11. package/dist/lib/draft-sleep.js +0 -1
  12. package/dist/lib/execution.d.ts +1 -0
  13. package/dist/lib/execution.js +1 -0
  14. package/dist/lib/extension-runtime.d.ts +1 -1
  15. package/dist/lib/extension-runtime.js +26 -4
  16. package/dist/lib/inspector.js +46 -7
  17. package/dist/lib/paths.d.ts +0 -1
  18. package/dist/lib/paths.js +0 -7
  19. package/dist/lib/prompts.d.ts +1 -1
  20. package/dist/lib/prompts.js +4 -4
  21. package/dist/lib/recipes-context.d.ts +12 -3
  22. package/dist/lib/recipes-context.js +30 -6
  23. package/dist/lib/recipes-discovery.d.ts +18 -0
  24. package/dist/lib/recipes-discovery.js +95 -22
  25. package/dist/lib/recipes-references.d.ts +42 -9
  26. package/dist/lib/recipes-references.js +248 -135
  27. package/dist/lib/registry.d.ts +14 -1
  28. package/dist/lib/registry.js +110 -87
  29. package/dist/lib/runtime.d.ts +30 -4
  30. package/dist/lib/runtime.js +74 -12
  31. package/dist/lib/tools-inspect.d.ts +3 -1
  32. package/dist/lib/tools-inspect.js +56 -9
  33. package/dist/lib/tools-local.d.ts +2 -0
  34. package/dist/lib/tools-local.js +5 -2
  35. package/dist/lib/tools-response.js +2 -0
  36. package/dist/lib/tools-spawn.d.ts +2 -0
  37. package/dist/lib/tools-spawn.js +24 -52
  38. package/dist/lib/tools.d.ts +4 -1
  39. package/dist/lib/tools.js +2 -0
  40. package/dist/scripts/build-dist.mjs +13 -4
  41. package/dist/skills/actors/SKILL.md +8 -8
  42. package/dist/skills/actors/recipes/recipe-validate.json +11 -0
  43. package/{recipes/utility-coordinator-lock-snapshot.json → dist/skills/actors/recipes/resource-locker-snapshot.json} +1 -3
  44. package/dist/{recipes → skills/actors/recipes}/resource-locker.json +1 -3
  45. package/dist/{recipes/utility-run-ops-snapshot.json → skills/actors/recipes/run-ops-snapshot.json} +1 -3
  46. package/dist/skills/actors/recipes/run-summary.json +9 -0
  47. package/dist/{scripts/locker.mjs → skills/actors/scripts/resource-locker.mjs} +2 -2
  48. package/dist/skills/actors/scripts/run-utils.mjs +164 -0
  49. package/{scripts → dist/skills/actors/scripts}/validate-recipe.mjs +134 -17
  50. package/dist/skills/artifacts/SKILL.md +16 -0
  51. package/{recipes/pipeline-artifact-bundle.json → dist/skills/artifacts/recipes/bundle.json} +4 -4
  52. package/dist/{recipes/utility-artifact-write.json → skills/artifacts/recipes/file-write.json} +1 -3
  53. package/dist/{recipes/utility-artifact-manifest.json → skills/artifacts/recipes/manifest.json} +1 -3
  54. package/{recipes/pipeline-artifact-report.json → dist/skills/artifacts/recipes/report.json} +2 -2
  55. package/dist/{recipes/pipeline-artifact-write.json → skills/artifacts/recipes/write.json} +3 -3
  56. package/dist/skills/artifacts/scripts/artifact-utils.mjs +63 -0
  57. package/dist/skills/media/SKILL.md +16 -0
  58. package/dist/{recipes/pipeline-media-library.json → skills/media/recipes/library.json} +2 -2
  59. package/{recipes/music-player.json → dist/skills/media/recipes/player.json} +1 -3
  60. package/dist/{recipes/utility-playlist-build.json → skills/media/recipes/playlist-build.json} +1 -3
  61. package/dist/skills/media/scripts/media-utils.mjs +47 -0
  62. package/dist/{scripts → skills/media/scripts}/music-player.mjs +9 -3
  63. package/dist/skills/project-work/SKILL.md +16 -0
  64. package/dist/skills/project-work/recipes/changelog-section.json +11 -0
  65. package/{recipes/pipeline-docs-maintenance.json → dist/skills/project-work/recipes/docs-maintenance.json} +4 -4
  66. package/dist/skills/project-work/recipes/package-summary.json +9 -0
  67. package/{recipes/pipeline-release-readiness.json → dist/skills/project-work/recipes/release-readiness.json} +6 -6
  68. package/dist/{recipes/pipeline-release-summary.json → skills/project-work/recipes/release-summary.json} +5 -5
  69. package/{recipes/pipeline-repo-health.json → dist/skills/project-work/recipes/repo-health.json} +6 -6
  70. package/{recipes/pipeline-async-run-ops.json → dist/skills/project-work/recipes/run-ops.json} +3 -3
  71. package/dist/skills/project-work/recipes/skill-summary.json +11 -0
  72. package/dist/skills/project-work/scripts/project-utils.mjs +89 -0
  73. package/dist/skills/recipe-memory/SKILL.md +16 -0
  74. package/dist/skills/swarm/SKILL.md +4 -4
  75. package/{recipes/pipeline-architect-coordinator.json → dist/skills/swarm/recipes/architect.json} +5 -5
  76. package/{recipes/pipeline-checkpoint-continuation.json → dist/skills/swarm/recipes/checkpoint-continuation.json} +3 -3
  77. package/dist/{recipes/pipeline-development-tasking.json → skills/swarm/recipes/development-tasking.json} +4 -4
  78. package/dist/{recipes/lens-swarm.json → skills/swarm/recipes/lens-review.json} +1 -1
  79. package/dist/{recipes/pipeline-quorum-review.json → skills/swarm/recipes/quorum-review.json} +4 -4
  80. package/{recipes/pipeline-research-synthesis.json → dist/skills/swarm/recipes/research-synthesis.json} +6 -6
  81. package/{recipes/pipeline-review-readiness.json → dist/skills/swarm/recipes/review-readiness.json} +1 -1
  82. package/{recipes/subagents-prompts.json → dist/skills/swarm/recipes/subagent-prompts.json} +1 -1
  83. package/{recipes → dist/skills/swarm/recipes}/subagent-quorum.json +1 -1
  84. package/dist/{recipes → skills/swarm/recipes}/subagent-review-coordinator.json +6 -6
  85. package/docs/actor-inspector.md +4 -3
  86. package/docs/async-runs.md +2 -2
  87. package/docs/recipe-library.md +23 -23
  88. package/docs/releasing.md +2 -2
  89. package/docs/template-recipes.md +32 -14
  90. package/docs/tool-registry.md +10 -4
  91. package/fixtures/protocol/recipe-summary.json +1 -1
  92. package/index.ts +2 -1
  93. package/lib/async-runs.ts +52 -25
  94. package/lib/automatic-review-runtime.ts +16 -3
  95. package/lib/draft-sleep.ts +0 -1
  96. package/lib/execution.ts +2 -0
  97. package/lib/extension-runtime.ts +42 -4
  98. package/lib/inspector.ts +57 -11
  99. package/lib/paths.ts +0 -7
  100. package/lib/prompts.ts +4 -4
  101. package/lib/recipes-context.ts +51 -6
  102. package/lib/recipes-discovery.ts +164 -24
  103. package/lib/recipes-references.ts +359 -146
  104. package/lib/registry.ts +185 -94
  105. package/lib/runtime.ts +109 -17
  106. package/lib/tools-inspect.ts +77 -10
  107. package/lib/tools-local.ts +9 -1
  108. package/lib/tools-response.ts +2 -0
  109. package/lib/tools-spawn.ts +38 -74
  110. package/lib/tools.ts +4 -1
  111. package/package.json +2 -4
  112. package/scripts/build-dist.mjs +13 -4
  113. package/skills/actors/SKILL.md +8 -8
  114. package/skills/actors/recipes/recipe-validate.json +11 -0
  115. package/{dist/recipes/utility-coordinator-lock-snapshot.json → skills/actors/recipes/resource-locker-snapshot.json} +1 -3
  116. package/{recipes → skills/actors/recipes}/resource-locker.json +1 -3
  117. package/{recipes/utility-run-ops-snapshot.json → skills/actors/recipes/run-ops-snapshot.json} +1 -3
  118. package/skills/actors/recipes/run-summary.json +9 -0
  119. package/{scripts/locker.mjs → skills/actors/scripts/resource-locker.mjs} +2 -2
  120. package/skills/actors/scripts/run-utils.mjs +164 -0
  121. package/{dist → skills/actors}/scripts/validate-recipe.mjs +134 -17
  122. package/skills/artifacts/SKILL.md +16 -0
  123. package/{dist/recipes/pipeline-artifact-bundle.json → skills/artifacts/recipes/bundle.json} +4 -4
  124. package/{recipes/utility-artifact-write.json → skills/artifacts/recipes/file-write.json} +1 -3
  125. package/{recipes/utility-artifact-manifest.json → skills/artifacts/recipes/manifest.json} +1 -3
  126. package/{dist/recipes/pipeline-artifact-report.json → skills/artifacts/recipes/report.json} +2 -2
  127. package/{recipes/pipeline-artifact-write.json → skills/artifacts/recipes/write.json} +3 -3
  128. package/skills/artifacts/scripts/artifact-utils.mjs +63 -0
  129. package/skills/media/SKILL.md +16 -0
  130. package/{recipes/pipeline-media-library.json → skills/media/recipes/library.json} +2 -2
  131. package/{dist/recipes/music-player.json → skills/media/recipes/player.json} +1 -3
  132. package/{recipes/utility-playlist-build.json → skills/media/recipes/playlist-build.json} +1 -3
  133. package/skills/media/scripts/media-utils.mjs +47 -0
  134. package/{scripts → skills/media/scripts}/music-player.mjs +9 -3
  135. package/skills/project-work/SKILL.md +16 -0
  136. package/skills/project-work/recipes/changelog-section.json +11 -0
  137. package/{dist/recipes/pipeline-docs-maintenance.json → skills/project-work/recipes/docs-maintenance.json} +4 -4
  138. package/skills/project-work/recipes/package-summary.json +9 -0
  139. package/{dist/recipes/pipeline-release-readiness.json → skills/project-work/recipes/release-readiness.json} +6 -6
  140. package/{recipes/pipeline-release-summary.json → skills/project-work/recipes/release-summary.json} +5 -5
  141. package/{dist/recipes/pipeline-repo-health.json → skills/project-work/recipes/repo-health.json} +6 -6
  142. package/{dist/recipes/pipeline-async-run-ops.json → skills/project-work/recipes/run-ops.json} +3 -3
  143. package/skills/project-work/recipes/skill-summary.json +11 -0
  144. package/skills/project-work/scripts/project-utils.mjs +89 -0
  145. package/skills/recipe-memory/SKILL.md +16 -0
  146. package/skills/swarm/SKILL.md +4 -4
  147. package/{dist/recipes/pipeline-architect-coordinator.json → skills/swarm/recipes/architect.json} +5 -5
  148. package/{dist/recipes/pipeline-checkpoint-continuation.json → skills/swarm/recipes/checkpoint-continuation.json} +3 -3
  149. package/{recipes/pipeline-development-tasking.json → skills/swarm/recipes/development-tasking.json} +4 -4
  150. package/{recipes/lens-swarm.json → skills/swarm/recipes/lens-review.json} +1 -1
  151. package/{recipes/pipeline-quorum-review.json → skills/swarm/recipes/quorum-review.json} +4 -4
  152. package/{dist/recipes/pipeline-research-synthesis.json → skills/swarm/recipes/research-synthesis.json} +6 -6
  153. package/{dist/recipes/pipeline-review-readiness.json → skills/swarm/recipes/review-readiness.json} +1 -1
  154. package/{dist/recipes/subagents-prompts.json → skills/swarm/recipes/subagent-prompts.json} +1 -1
  155. package/{dist → skills/swarm}/recipes/subagent-quorum.json +1 -1
  156. package/{recipes → skills/swarm/recipes}/subagent-review-coordinator.json +6 -6
  157. package/dist/recipes/utility-changelog-section.json +0 -13
  158. package/dist/recipes/utility-package-summary.json +0 -11
  159. package/dist/recipes/utility-run-summary.json +0 -11
  160. package/dist/recipes/utility-skill-summary.json +0 -13
  161. package/dist/recipes/utility-validate-recipe.json +0 -13
  162. package/dist/scripts/executable-block-style.d.mts +0 -1
  163. package/dist/scripts/executable-block-style.mjs +0 -73
  164. package/dist/scripts/recipe-utils.mjs +0 -404
  165. package/dist/scripts/release-gates.mjs +0 -281
  166. package/recipes/utility-changelog-section.json +0 -13
  167. package/recipes/utility-package-summary.json +0 -11
  168. package/recipes/utility-run-summary.json +0 -11
  169. package/recipes/utility-skill-summary.json +0 -13
  170. package/recipes/utility-validate-recipe.json +0 -13
  171. package/scripts/executable-block-style.d.mts +0 -1
  172. package/scripts/executable-block-style.mjs +0 -73
  173. package/scripts/recipe-utils.mjs +0 -404
  174. package/scripts/release-gates.mjs +0 -281
  175. /package/dist/{recipes/utility-validation-wrapper.json → skills/actors/recipes/command-validate.json} +0 -0
  176. /package/dist/{recipes/utility-jsonl-tail.json → skills/actors/recipes/jsonl-tail.json} +0 -0
  177. /package/dist/{recipes/utility-run-state-files.json → skills/actors/recipes/run-state-files.json} +0 -0
  178. /package/dist/{recipes/utility-playlist-scan.json → skills/media/recipes/playlist-scan.json} +0 -0
  179. /package/dist/{recipes/utility-changelog-head.json → skills/project-work/recipes/changelog-head.json} +0 -0
  180. /package/dist/{recipes/utility-git-log.json → skills/project-work/recipes/git-log.json} +0 -0
  181. /package/dist/{recipes/utility-git-status.json → skills/project-work/recipes/git-status.json} +0 -0
  182. /package/dist/{recipes/utility-markdown-index.json → skills/project-work/recipes/markdown-index.json} +0 -0
  183. /package/dist/{recipes → skills/recipe-memory/recipes}/draft-review.json +0 -0
  184. /package/dist/{recipes → skills/recipe-memory/recipes}/tool-review.json +0 -0
  185. /package/dist/{recipes → skills/swarm/recipes}/subagent-artifact.json +0 -0
  186. /package/dist/{recipes → skills/swarm/recipes}/subagent-checkpoint.json +0 -0
  187. /package/dist/{recipes → skills/swarm/recipes}/subagent-conflict-report.json +0 -0
  188. /package/dist/{recipes → skills/swarm/recipes}/subagent-contradiction-map.json +0 -0
  189. /package/dist/{recipes → skills/swarm/recipes}/subagent-critic.json +0 -0
  190. /package/dist/{recipes → skills/swarm/recipes}/subagent-evidence-map.json +0 -0
  191. /package/dist/{recipes → skills/swarm/recipes}/subagent-followup.json +0 -0
  192. /package/dist/{recipes → skills/swarm/recipes}/subagent-judge.json +0 -0
  193. /package/dist/{recipes → skills/swarm/recipes}/subagent-merge.json +0 -0
  194. /package/dist/{recipes → skills/swarm/recipes}/subagent-normalize.json +0 -0
  195. /package/dist/{recipes → skills/swarm/recipes}/subagent-plan.json +0 -0
  196. /package/dist/{recipes → skills/swarm/recipes}/subagent-preflight.json +0 -0
  197. /package/dist/{recipes → skills/swarm/recipes}/subagent-prompt.json +0 -0
  198. /package/dist/{recipes → skills/swarm/recipes}/subagent-review.json +0 -0
  199. /package/dist/{recipes → skills/swarm/recipes}/subagent-task-card.json +0 -0
  200. /package/dist/{recipes → skills/swarm/recipes}/subagent-tools.json +0 -0
  201. /package/dist/{recipes → skills/swarm/recipes}/subagent-verify.json +0 -0
  202. /package/{recipes/utility-validation-wrapper.json → skills/actors/recipes/command-validate.json} +0 -0
  203. /package/{recipes/utility-jsonl-tail.json → skills/actors/recipes/jsonl-tail.json} +0 -0
  204. /package/{recipes/utility-run-state-files.json → skills/actors/recipes/run-state-files.json} +0 -0
  205. /package/{recipes/utility-playlist-scan.json → skills/media/recipes/playlist-scan.json} +0 -0
  206. /package/{recipes/utility-changelog-head.json → skills/project-work/recipes/changelog-head.json} +0 -0
  207. /package/{recipes/utility-git-log.json → skills/project-work/recipes/git-log.json} +0 -0
  208. /package/{recipes/utility-git-status.json → skills/project-work/recipes/git-status.json} +0 -0
  209. /package/{recipes/utility-markdown-index.json → skills/project-work/recipes/markdown-index.json} +0 -0
  210. /package/{recipes → skills/recipe-memory/recipes}/draft-review.json +0 -0
  211. /package/{recipes → skills/recipe-memory/recipes}/tool-review.json +0 -0
  212. /package/{recipes → skills/swarm/recipes}/subagent-artifact.json +0 -0
  213. /package/{recipes → skills/swarm/recipes}/subagent-checkpoint.json +0 -0
  214. /package/{recipes → skills/swarm/recipes}/subagent-conflict-report.json +0 -0
  215. /package/{recipes → skills/swarm/recipes}/subagent-contradiction-map.json +0 -0
  216. /package/{recipes → skills/swarm/recipes}/subagent-critic.json +0 -0
  217. /package/{recipes → skills/swarm/recipes}/subagent-evidence-map.json +0 -0
  218. /package/{recipes → skills/swarm/recipes}/subagent-followup.json +0 -0
  219. /package/{recipes → skills/swarm/recipes}/subagent-judge.json +0 -0
  220. /package/{recipes → skills/swarm/recipes}/subagent-merge.json +0 -0
  221. /package/{recipes → skills/swarm/recipes}/subagent-normalize.json +0 -0
  222. /package/{recipes → skills/swarm/recipes}/subagent-plan.json +0 -0
  223. /package/{recipes → skills/swarm/recipes}/subagent-preflight.json +0 -0
  224. /package/{recipes → skills/swarm/recipes}/subagent-prompt.json +0 -0
  225. /package/{recipes → skills/swarm/recipes}/subagent-review.json +0 -0
  226. /package/{recipes → skills/swarm/recipes}/subagent-task-card.json +0 -0
  227. /package/{recipes → skills/swarm/recipes}/subagent-tools.json +0 -0
  228. /package/{recipes → skills/swarm/recipes}/subagent-verify.json +0 -0
@@ -1,10 +1,34 @@
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
+ import { createHash } from "node:crypto";
6
7
  import { writeFileSync } from "node:fs";
7
- import { basename } from "node:path";
8
+ import { basename, resolve } from "node:path";
9
+ import * as RecipesReferences from "./recipes-references.js";
10
+ export function createRecipeResolutionContext(sessionId, cwd, activeSkills) {
11
+ const normalizedSessionId = sessionId.trim();
12
+ if (!normalizedSessionId)
13
+ throw new Error("Recipe resolution session id is required.");
14
+ const normalizedCwd = resolve(cwd);
15
+ const generation = createHash("sha256")
16
+ .update(JSON.stringify({
17
+ activeSkills: RecipesReferences.getActiveSkillRecipeNamespaces(activeSkills),
18
+ cwd: normalizedCwd,
19
+ sessionId: normalizedSessionId,
20
+ }))
21
+ .digest("hex");
22
+ return Object.freeze({
23
+ activeSkills,
24
+ cwd: normalizedCwd,
25
+ generation,
26
+ sessionId: normalizedSessionId,
27
+ });
28
+ }
29
+ export function createEmptyRecipeResolutionContext(sessionId, cwd) {
30
+ return createRecipeResolutionContext(sessionId, cwd, RecipesReferences.EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT);
31
+ }
8
32
  function commandName(command) {
9
33
  return basename(command).toLowerCase();
10
34
  }
@@ -78,7 +102,7 @@ export function findPiPrintPromptIndex(args) {
78
102
  function matchesActorContext(record, context) {
79
103
  if (!context)
80
104
  return record.role === "entry";
81
- if (context.file && context.file === record.file)
105
+ if (context.file && context.file === record.source_file)
82
106
  return true;
83
107
  if (context.name && context.name === record.name)
84
108
  return true;
@@ -105,7 +129,7 @@ export function markRecipeContextRecords(records, context) {
105
129
  }
106
130
  export function formatRecipeContextJsonl(records, context) {
107
131
  return markRecipeContextRecords(records, context)
108
- .map((record) => JSON.stringify(record))
132
+ .map(({ source_file: _sourceFile, ...record }) => JSON.stringify(record))
109
133
  .join("\n");
110
134
  }
111
135
  export function buildRecipeContextPromptBlock(records, context) {
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import * as CommandTemplates from "./command-templates.ts";
7
7
  import type { RegisteredTool } from "./config.ts";
8
+ import type { RecipeResolutionContext } from "./recipes-context.ts";
8
9
  import type { TemplateRecipeConfig } from "./recipes-references.ts";
9
10
  export interface DiscoveredRecipe {
10
11
  id: string;
@@ -18,6 +19,7 @@ export interface DiscoveredRecipe {
18
19
  disabled: boolean;
19
20
  tool: boolean;
20
21
  mutableUsage: boolean;
22
+ resolutionContext?: RecipeResolutionContext;
21
23
  diagnostics: string[];
22
24
  riskLabels: CommandTemplates.CommandTemplateRiskLabel[];
23
25
  shadows: string[];
@@ -44,6 +46,21 @@ export interface RecipesDiscoverySource {
44
46
  file?: string;
45
47
  defaultTool?: boolean;
46
48
  mutableUsage?: boolean;
49
+ resolutionContext?: RecipeResolutionContext;
50
+ }
51
+ export interface UserRecipeAdmission {
52
+ args?: string[];
53
+ argTypes?: RegisteredTool["argTypes"];
54
+ artifacts?: Record<string, string>;
55
+ async?: boolean;
56
+ control?: string[];
57
+ defaults?: Record<string, unknown>;
58
+ diagnostics: string[];
59
+ effectiveRecipe?: TemplateRecipeConfig;
60
+ identity: string;
61
+ sourcePath: string;
62
+ tool?: RegisteredTool;
63
+ validated: boolean;
47
64
  }
48
65
  export declare function hasBroadWindowsWriteAcl(icaclsOutput: string): boolean;
49
66
  export declare function discoverRecipeSources(sources: RecipesDiscoverySource[]): RecipesDiscoveryResult;
@@ -52,4 +69,5 @@ export declare function createRecipeIntegrityManifest(result: RecipesDiscoveryRe
52
69
  export declare function getShadowedLaunchDiagnostic(result: RecipesDiscoveryResult, id: string): Record<string, unknown> | undefined;
53
70
  export declare function listDraftRecipes(root: string): Array<Record<string, unknown>>;
54
71
  export declare function summarizeDiscovery(result: RecipesDiscoveryResult): Record<string, unknown>;
72
+ export declare function admitUserRecipe(sourcePath: string, resolutionContext: RecipeResolutionContext, authoredRecipe?: Record<string, unknown>, mutableUsage?: boolean): UserRecipeAdmission;
55
73
  export declare function toRegisteredTool(entry: DiscoveredRecipe): RegisteredTool | undefined;
@@ -94,10 +94,12 @@ function getRecipeRiskLabels(config) {
94
94
  "risk.platform_specific",
95
95
  ].filter((label) => labels.has(label));
96
96
  }
97
- function readDiscoveredRecipe(root, file, priority, defaultTool = false, mutableUsage = false) {
97
+ function readDiscoveredRecipe(root, file, priority, defaultTool = false, mutableUsage = false, resolutionContext) {
98
98
  const id = RecipesReferences.getRecipeIdFromPath(file);
99
99
  try {
100
- const config = RecipesReferences.readResolvedRecipeConfig(file);
100
+ const config = RecipesReferences.readResolvedRecipeConfig(file, [], {
101
+ skillContext: resolutionContext?.activeSkills,
102
+ });
101
103
  const invalid = !config;
102
104
  const disabled = config?.disabled === true;
103
105
  return {
@@ -112,6 +114,7 @@ function readDiscoveredRecipe(root, file, priority, defaultTool = false, mutable
112
114
  disabled,
113
115
  tool: defaultTool && !disabled && !invalid,
114
116
  mutableUsage,
117
+ resolutionContext,
115
118
  diagnostics: getRecipeConfigDiagnostics(file, config),
116
119
  riskLabels: getRecipeRiskLabels(config),
117
120
  shadows: [],
@@ -129,6 +132,7 @@ function readDiscoveredRecipe(root, file, priority, defaultTool = false, mutable
129
132
  disabled: false,
130
133
  tool: false,
131
134
  mutableUsage,
135
+ resolutionContext,
132
136
  diagnostics: [
133
137
  `Failed to load recipe ${file}: ${error instanceof Error ? error.message : String(error)}`,
134
138
  ],
@@ -147,6 +151,7 @@ function filesForSource(source) {
147
151
  file: source.file,
148
152
  defaultTool,
149
153
  mutableUsage,
154
+ resolutionContext: source.resolutionContext,
150
155
  },
151
156
  ];
152
157
  return source.root
@@ -155,6 +160,7 @@ function filesForSource(source) {
155
160
  file,
156
161
  defaultTool,
157
162
  mutableUsage,
163
+ resolutionContext: source.resolutionContext,
158
164
  }))
159
165
  : [];
160
166
  }
@@ -222,7 +228,7 @@ function getRecipeRootDiagnostics(sources) {
222
228
  return diagnostics;
223
229
  }
224
230
  export function discoverRecipeSources(sources) {
225
- const entries = sources.flatMap((source, priority) => filesForSource(source).map(({ root, file, defaultTool, mutableUsage }) => readDiscoveredRecipe(root, file, priority, defaultTool, mutableUsage)));
231
+ const entries = sources.flatMap((source, priority) => filesForSource(source).map(({ root, file, defaultTool, mutableUsage, resolutionContext }) => readDiscoveredRecipe(root, file, priority, defaultTool, mutableUsage, resolutionContext)));
226
232
  const byId = new Map();
227
233
  for (const entry of entries) {
228
234
  const bucket = byId.get(entry.id) ?? [];
@@ -647,12 +653,8 @@ export function summarizeDiscovery(result) {
647
653
  integrity_manifest: createRecipeIntegrityManifest(result),
648
654
  };
649
655
  }
650
- export function toRegisteredTool(entry) {
651
- if (!entry.tool || entry.invalid || entry.disabled || !entry.config)
652
- return undefined;
653
- const cfg = entry.config;
654
- const template = entry.path;
655
- const description = cfg.description ?? `Execute template recipe: ${entry.id}`;
656
+ function projectRegisteredTool(identity, path, cfg, mutableUsage) {
657
+ const description = cfg.description ?? `Execute template recipe: ${identity}`;
656
658
  const argTemplate = cfg.template;
657
659
  const argTemplateConfig = typeof argTemplate === "object" && !Array.isArray(argTemplate)
658
660
  ? {
@@ -669,24 +671,27 @@ export function toRegisteredTool(entry) {
669
671
  return [parsed.arg, parsed.type];
670
672
  }));
671
673
  assertToolSafeRepeatConfig(argTemplateConfig, explicitArgTypes, { ...(cfg.defaults ?? {}), ...(cfg.values ?? {}) });
672
- const argTypes = Schema.getTemplateArgTypes(argTemplateConfig);
673
- Schema.assertCompatibleToolArgTypes(explicitArgTypes, argTypes);
674
+ const inferredArgTypes = Schema.getTemplateArgTypes(argTemplateConfig);
675
+ Schema.assertCompatibleToolArgTypes(explicitArgTypes, inferredArgTypes);
676
+ const effectiveArgTypes = { ...inferredArgTypes, ...explicitArgTypes };
677
+ const args = Schema.getToolArgNames(argTemplateConfig).filter((arg) => !RecipesReferences.isRuntimeOwnedRecipeInput(arg));
678
+ const callerArgSet = new Set(args);
679
+ const argTypes = Object.fromEntries(Object.entries(effectiveArgTypes).filter(([arg]) => callerArgSet.has(arg)));
680
+ const defaults = Object.fromEntries(Object.entries(cfg.defaults ?? {}).filter(([arg]) => callerArgSet.has(arg)));
681
+ const storedArgs = cfg.args?.filter((arg) => callerArgSet.has(Schema.parseToolArgToken(String(arg)).arg));
674
682
  return {
675
- name: entry.id,
683
+ name: identity,
676
684
  description,
677
- template,
685
+ template: path,
678
686
  recipe: cfg,
679
- args: Schema.getToolArgNames(argTemplateConfig),
680
- defaults: Object.fromEntries(Object.entries(cfg.defaults ?? {}).map(([key, value]) => [
681
- key,
682
- String(value),
683
- ])),
687
+ args,
688
+ defaults: Object.fromEntries(Object.entries(defaults).map(([key, value]) => [key, String(value)])),
684
689
  ...(Object.keys(argTypes).length > 0 ? { argTypes } : {}),
685
- ...(entry.mutableUsage ? { sourcePath: entry.path } : {}),
686
- ...(cfg.args ? { storedArgs: cfg.args } : {}),
687
- ...(cfg.defaults
690
+ ...(mutableUsage ? { sourcePath: path } : {}),
691
+ ...(storedArgs ? { storedArgs } : {}),
692
+ ...(Object.keys(defaults).length > 0
688
693
  ? {
689
- storedDefaults: Object.fromEntries(Object.entries(cfg.defaults).map(([key, value]) => [
694
+ storedDefaults: Object.fromEntries(Object.entries(defaults).map(([key, value]) => [
690
695
  key,
691
696
  String(value),
692
697
  ])),
@@ -694,3 +699,71 @@ export function toRegisteredTool(entry) {
694
699
  : {}),
695
700
  };
696
701
  }
702
+ function boundedAdmissionDiagnostic(error) {
703
+ const message = error instanceof Error ? error.message : String(error);
704
+ return message.length <= 4096 ? message : `${message.slice(0, 4095)}…`;
705
+ }
706
+ export function admitUserRecipe(sourcePath, resolutionContext, authoredRecipe, mutableUsage = true) {
707
+ const identity = RecipesReferences.getRecipeIdFromPath(sourcePath);
708
+ try {
709
+ const effectiveRecipe = RecipesReferences.readResolvedRecipeConfig(sourcePath, [], {
710
+ ...(authoredRecipe
711
+ ? { authoredEntry: { path: sourcePath, recipe: authoredRecipe } }
712
+ : {}),
713
+ skillContext: resolutionContext.activeSkills,
714
+ });
715
+ if (!effectiveRecipe) {
716
+ return {
717
+ diagnostics: [
718
+ authoredRecipe
719
+ ? "Recipe must define a valid template."
720
+ : RecipesReferences.diagnoseRawRecipeConfigFailure(sourcePath) ??
721
+ "Recipe must define a valid template.",
722
+ ],
723
+ identity,
724
+ sourcePath,
725
+ validated: false,
726
+ };
727
+ }
728
+ if (effectiveRecipe.disabled === true) {
729
+ return {
730
+ diagnostics: ["Recipe is disabled."],
731
+ effectiveRecipe,
732
+ identity,
733
+ sourcePath,
734
+ validated: false,
735
+ };
736
+ }
737
+ const tool = projectRegisteredTool(identity, sourcePath, effectiveRecipe, mutableUsage);
738
+ return {
739
+ args: tool.args,
740
+ argTypes: tool.argTypes,
741
+ artifacts: effectiveRecipe.artifacts,
742
+ async: effectiveRecipe.async === true,
743
+ control: effectiveRecipe.control,
744
+ defaults: effectiveRecipe.defaults,
745
+ diagnostics: [],
746
+ effectiveRecipe,
747
+ identity,
748
+ sourcePath,
749
+ tool,
750
+ validated: true,
751
+ };
752
+ }
753
+ catch (error) {
754
+ return {
755
+ diagnostics: [boundedAdmissionDiagnostic(error)],
756
+ identity,
757
+ sourcePath,
758
+ validated: false,
759
+ };
760
+ }
761
+ }
762
+ export function toRegisteredTool(entry) {
763
+ if (!entry.tool || entry.invalid || entry.disabled || !entry.config)
764
+ return undefined;
765
+ if (entry.resolutionContext) {
766
+ return admitUserRecipe(entry.path, entry.resolutionContext, undefined, entry.mutableUsage).tool;
767
+ }
768
+ return projectRegisteredTool(entry.id, entry.path, entry.config, entry.mutableUsage);
769
+ }
@@ -12,7 +12,6 @@ export interface TemplateRecipeImportBinding {
12
12
  }
13
13
  export type TemplateRecipeImport = string | TemplateRecipeImportBinding;
14
14
  export interface TemplateRecipeDefinition {
15
- name?: string;
16
15
  description?: string;
17
16
  disabled?: boolean;
18
17
  imports?: Record<string, TemplateRecipeImport>;
@@ -39,6 +38,7 @@ export interface TemplateRecipeDefinition {
39
38
  usage?: Record<string, unknown>;
40
39
  }
41
40
  export interface TemplateRecipeConfig extends TemplateRecipeDefinition {
41
+ name?: string;
42
42
  async?: boolean;
43
43
  recipe_dir?: string;
44
44
  skill_dir?: string;
@@ -46,31 +46,64 @@ export interface TemplateRecipeConfig extends TemplateRecipeDefinition {
46
46
  export interface TemplateRecipeContextRecord {
47
47
  alias?: string;
48
48
  depth: number;
49
- file: string;
50
49
  import_path: string[];
50
+ logical_reference: string;
51
51
  name: string;
52
- qualified_name?: string;
53
52
  recipe: Record<string, unknown>;
54
53
  role: "entry" | "import";
54
+ skill?: string;
55
+ source_file: string;
56
+ source_kind: "active_skill_component" | "explicit_file_recipe" | "user_registry_capability";
55
57
  }
56
58
  export interface ReadResolvedRecipeConfigOptions {
59
+ authoredEntry?: {
60
+ path: string;
61
+ recipe: Record<string, unknown>;
62
+ };
57
63
  includeActorRecipeContext?: boolean;
64
+ skillContext?: ActiveSkillRecipeContext;
58
65
  }
66
+ export declare const RUNTIME_OWNED_RECIPE_INPUT_NAMES: readonly string[];
67
+ export declare function isRuntimeOwnedRecipeInput(name: string): boolean;
59
68
  export interface ActiveSkillRecipeSource {
60
69
  name: string;
61
70
  filePath?: string;
62
71
  baseDir?: string;
63
72
  }
64
- export declare function setActiveSkillRecipeSources(skills: ActiveSkillRecipeSource[]): void;
65
- export declare function getActiveSkillRecipeNamespaces(): Record<string, string[]>;
66
- export declare function resolveRecipePath(value: string, recipeRoot?: string): string;
67
- export declare function resolveRecipeReferencePath(value: unknown, currentRecipeRoot?: string): string | undefined;
68
- export declare function getRecipePath(value: unknown, recipeRoot?: string): string | undefined;
73
+ export interface ActiveSkillRecipeContext {
74
+ readonly namespaces: Readonly<Record<string, readonly string[]>>;
75
+ }
76
+ export declare function createActiveSkillRecipeContext(skills: ActiveSkillRecipeSource[]): ActiveSkillRecipeContext;
77
+ export declare const EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT: ActiveSkillRecipeContext;
78
+ export declare function getActiveSkillRecipeNamespaces(context: ActiveSkillRecipeContext): Record<string, string[]>;
79
+ export interface ActiveSkillRecipeComponent {
80
+ file: string;
81
+ identity: string;
82
+ imports: Record<string, string>;
83
+ skill: string;
84
+ stem: string;
85
+ }
86
+ export interface SkillRecipeComponentDiagnostic {
87
+ file?: string;
88
+ reason: string;
89
+ skill: string;
90
+ stem?: string;
91
+ }
92
+ export interface SkillRecipeComponentInventory {
93
+ components: ActiveSkillRecipeComponent[];
94
+ partial: boolean;
95
+ rejected: SkillRecipeComponentDiagnostic[];
96
+ }
97
+ export declare function inventoryActiveSkillRecipeComponents(context: ActiveSkillRecipeContext): SkillRecipeComponentInventory;
98
+ export declare function listActiveSkillRecipeComponents(context: ActiveSkillRecipeContext): ActiveSkillRecipeComponent[];
99
+ export declare function resolveRecipePath(value: string, baseDir?: string): string;
100
+ export declare function resolveRecipeReferencePath(value: unknown, baseDir?: string, context?: ActiveSkillRecipeContext): string | undefined;
101
+ export declare function getRecipePath(value: unknown, baseDir?: string, context?: ActiveSkillRecipeContext): string | undefined;
69
102
  export declare function diagnoseRawRecipeConfigFailure(path: string): string | undefined;
70
103
  export declare function readRawRecipeConfig(path: string): Record<string, unknown> | undefined;
71
104
  export declare function getRecipeIdFromPath(file: string): string;
72
105
  export declare function readResolvedRecipeConfig(file: string, stack?: string[], options?: ReadResolvedRecipeConfigOptions): TemplateRecipeConfig | undefined;
73
- export declare function buildRecipeContextRecords(file: string): TemplateRecipeContextRecord[];
106
+ export declare function buildRecipeContextRecords(file: string, context?: ActiveSkillRecipeContext): TemplateRecipeContextRecord[];
74
107
  export declare function getRecipeTemplate(value: unknown): CommandTemplateValue | undefined;
75
108
  export declare function isRecipeReference(value: unknown): boolean;
76
109
  export declare function isAsyncRecipeReference(value: unknown): boolean;