@caupulican/pi-adaptative 0.94.0 → 0.95.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 (371) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/bundled-resources/extensions/tmux-agent-manager/README.md +32 -13
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +7 -4
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +173 -293
  6. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
  7. package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +247 -392
  8. package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.d.ts +52 -0
  9. package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.d.ts.map +1 -0
  10. package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.js +118 -0
  11. package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.js.map +1 -0
  12. package/dist/bundled-resources/extensions/tmux-agent-manager/launch-profile.ts +169 -0
  13. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/builder-validator.json +1 -1
  14. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/provider-prompt-smoke.json +1 -1
  15. package/dist/bundled-resources/skills/pi-harness-learning/SKILL.md +13 -7
  16. package/dist/bundled-resources/skills/worker-profile-writer/SKILL.md +11 -11
  17. package/dist/core/agent-paths.d.ts +2 -0
  18. package/dist/core/agent-paths.d.ts.map +1 -1
  19. package/dist/core/agent-paths.js +7 -0
  20. package/dist/core/agent-paths.js.map +1 -1
  21. package/dist/core/agent-session.d.ts +11 -41
  22. package/dist/core/agent-session.d.ts.map +1 -1
  23. package/dist/core/agent-session.js +98 -161
  24. package/dist/core/agent-session.js.map +1 -1
  25. package/dist/core/autonomy/envelope-enforcement.d.ts +6 -1
  26. package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
  27. package/dist/core/autonomy/envelope-enforcement.js +26 -25
  28. package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
  29. package/dist/core/autonomy/lane-private-paths.d.ts.map +1 -1
  30. package/dist/core/autonomy/lane-private-paths.js +2 -1
  31. package/dist/core/autonomy/lane-private-paths.js.map +1 -1
  32. package/dist/core/autonomy/lane-tool-surface.d.ts +8 -8
  33. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  34. package/dist/core/autonomy/lane-tool-surface.js +45 -30
  35. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  36. package/dist/core/autonomy/worker-session-private-scope.d.ts +12 -0
  37. package/dist/core/autonomy/worker-session-private-scope.d.ts.map +1 -0
  38. package/dist/core/autonomy/worker-session-private-scope.js +42 -0
  39. package/dist/core/autonomy/worker-session-private-scope.js.map +1 -0
  40. package/dist/core/autonomy/worker-tool-adapter-registry.d.ts +65 -0
  41. package/dist/core/autonomy/worker-tool-adapter-registry.d.ts.map +1 -0
  42. package/dist/core/autonomy/worker-tool-adapter-registry.js +145 -0
  43. package/dist/core/autonomy/worker-tool-adapter-registry.js.map +1 -0
  44. package/dist/core/background-lane-controller.d.ts +9 -1
  45. package/dist/core/background-lane-controller.d.ts.map +1 -1
  46. package/dist/core/background-lane-controller.js +76 -6
  47. package/dist/core/background-lane-controller.js.map +1 -1
  48. package/dist/core/background-tool-task-controller.d.ts +23 -2
  49. package/dist/core/background-tool-task-controller.d.ts.map +1 -1
  50. package/dist/core/background-tool-task-controller.js +132 -17
  51. package/dist/core/background-tool-task-controller.js.map +1 -1
  52. package/dist/core/context/long-term-memory-trigger.d.ts +3 -1
  53. package/dist/core/context/long-term-memory-trigger.d.ts.map +1 -1
  54. package/dist/core/context/long-term-memory-trigger.js +1 -1
  55. package/dist/core/context/long-term-memory-trigger.js.map +1 -1
  56. package/dist/core/context/okf-memory-provider.d.ts +3 -0
  57. package/dist/core/context/okf-memory-provider.d.ts.map +1 -1
  58. package/dist/core/context/okf-memory-provider.js +66 -31
  59. package/dist/core/context/okf-memory-provider.js.map +1 -1
  60. package/dist/core/context/okf-memory.d.ts +18 -1
  61. package/dist/core/context/okf-memory.d.ts.map +1 -1
  62. package/dist/core/context/okf-memory.js +48 -0
  63. package/dist/core/context/okf-memory.js.map +1 -1
  64. package/dist/core/cost-guard-controller.d.ts +37 -0
  65. package/dist/core/cost-guard-controller.d.ts.map +1 -0
  66. package/dist/core/cost-guard-controller.js +71 -0
  67. package/dist/core/cost-guard-controller.js.map +1 -0
  68. package/dist/core/cost-guard.d.ts +9 -4
  69. package/dist/core/cost-guard.d.ts.map +1 -1
  70. package/dist/core/cost-guard.js +7 -3
  71. package/dist/core/cost-guard.js.map +1 -1
  72. package/dist/core/delegation/worker-agent-control.d.ts +4 -0
  73. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
  74. package/dist/core/delegation/worker-agent-control.js.map +1 -1
  75. package/dist/core/delegation/worker-attempt-executor.d.ts +1 -1
  76. package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
  77. package/dist/core/delegation/worker-attempt-executor.js +0 -1
  78. package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
  79. package/dist/core/delegation/worker-authority-resolver.d.ts +16 -3
  80. package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -1
  81. package/dist/core/delegation/worker-authority-resolver.js +114 -55
  82. package/dist/core/delegation/worker-authority-resolver.js.map +1 -1
  83. package/dist/core/delegation/worker-claim.d.ts +1 -2
  84. package/dist/core/delegation/worker-claim.d.ts.map +1 -1
  85. package/dist/core/delegation/worker-claim.js.map +1 -1
  86. package/dist/core/delegation/worker-delegation-controller.d.ts +19 -6
  87. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
  88. package/dist/core/delegation/worker-delegation-controller.js +125 -40
  89. package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
  90. package/dist/core/delegation/worker-delegation-request.d.ts +3 -3
  91. package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
  92. package/dist/core/delegation/worker-delegation-request.js +13 -19
  93. package/dist/core/delegation/worker-delegation-request.js.map +1 -1
  94. package/dist/core/delegation/worker-execution-policy.d.ts +3 -2
  95. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
  96. package/dist/core/delegation/worker-execution-policy.js +54 -39
  97. package/dist/core/delegation/worker-execution-policy.js.map +1 -1
  98. package/dist/core/delegation/worker-fleet-limits.d.ts +3 -3
  99. package/dist/core/delegation/worker-fleet-limits.d.ts.map +1 -1
  100. package/dist/core/delegation/worker-fleet-limits.js +7 -7
  101. package/dist/core/delegation/worker-fleet-limits.js.map +1 -1
  102. package/dist/core/delegation/worker-machine-scope.d.ts +12 -0
  103. package/dist/core/delegation/worker-machine-scope.d.ts.map +1 -0
  104. package/dist/core/delegation/worker-machine-scope.js +38 -0
  105. package/dist/core/delegation/worker-machine-scope.js.map +1 -0
  106. package/dist/core/delegation/worker-notification-coordinator.d.ts +10 -0
  107. package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
  108. package/dist/core/delegation/worker-notification-coordinator.js +69 -3
  109. package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
  110. package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
  111. package/dist/core/delegation/worker-recovery-coordinator.js +6 -1
  112. package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
  113. package/dist/core/delegation/worker-runner.d.ts +5 -7
  114. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  115. package/dist/core/delegation/worker-runner.js +1 -4
  116. package/dist/core/delegation/worker-runner.js.map +1 -1
  117. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +3 -2
  118. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -1
  119. package/dist/core/delegation/worker-write-reservation-coordinator.js +50 -25
  120. package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -1
  121. package/dist/core/durable-custom-message-turn-controller.d.ts +6 -0
  122. package/dist/core/durable-custom-message-turn-controller.d.ts.map +1 -1
  123. package/dist/core/durable-custom-message-turn-controller.js +38 -15
  124. package/dist/core/durable-custom-message-turn-controller.js.map +1 -1
  125. package/dist/core/extension-binding-controller.d.ts +5 -1
  126. package/dist/core/extension-binding-controller.d.ts.map +1 -1
  127. package/dist/core/extension-binding-controller.js +15 -0
  128. package/dist/core/extension-binding-controller.js.map +1 -1
  129. package/dist/core/extensions/factory-runtime.d.ts.map +1 -1
  130. package/dist/core/extensions/factory-runtime.js +5 -0
  131. package/dist/core/extensions/factory-runtime.js.map +1 -1
  132. package/dist/core/extensions/runner.d.ts.map +1 -1
  133. package/dist/core/extensions/runner.js +1 -0
  134. package/dist/core/extensions/runner.js.map +1 -1
  135. package/dist/core/extensions/types.d.ts +8 -4
  136. package/dist/core/extensions/types.d.ts.map +1 -1
  137. package/dist/core/extensions/types.js.map +1 -1
  138. package/dist/core/foreground-terminal-handoff-controller.d.ts +31 -0
  139. package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -1
  140. package/dist/core/foreground-terminal-handoff-controller.js +239 -55
  141. package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
  142. package/dist/core/goals/goal-session-controller.d.ts +2 -0
  143. package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
  144. package/dist/core/goals/goal-session-controller.js +8 -0
  145. package/dist/core/goals/goal-session-controller.js.map +1 -1
  146. package/dist/core/goals/goal-tool-core.d.ts +5 -4
  147. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  148. package/dist/core/goals/goal-tool-core.js +23 -19
  149. package/dist/core/goals/goal-tool-core.js.map +1 -1
  150. package/dist/core/learning/auto-learn-settings.d.ts +84 -0
  151. package/dist/core/learning/auto-learn-settings.d.ts.map +1 -0
  152. package/dist/core/learning/auto-learn-settings.js +66 -0
  153. package/dist/core/learning/auto-learn-settings.js.map +1 -0
  154. package/dist/core/learning/learning-audit.d.ts +5 -1
  155. package/dist/core/learning/learning-audit.d.ts.map +1 -1
  156. package/dist/core/learning/learning-audit.js +32 -1
  157. package/dist/core/learning/learning-audit.js.map +1 -1
  158. package/dist/core/learning/reflection-engine.d.ts +24 -0
  159. package/dist/core/learning/reflection-engine.d.ts.map +1 -1
  160. package/dist/core/learning/reflection-engine.js +104 -8
  161. package/dist/core/learning/reflection-engine.js.map +1 -1
  162. package/dist/core/local-prefix-warm-controller.d.ts +24 -0
  163. package/dist/core/local-prefix-warm-controller.d.ts.map +1 -0
  164. package/dist/core/local-prefix-warm-controller.js +79 -0
  165. package/dist/core/local-prefix-warm-controller.js.map +1 -0
  166. package/dist/core/memory/okf-project-memory-store.d.ts +28 -0
  167. package/dist/core/memory/okf-project-memory-store.d.ts.map +1 -0
  168. package/dist/core/memory/okf-project-memory-store.js +111 -0
  169. package/dist/core/memory/okf-project-memory-store.js.map +1 -0
  170. package/dist/core/memory/providers/file-store.d.ts +44 -1
  171. package/dist/core/memory/providers/file-store.d.ts.map +1 -1
  172. package/dist/core/memory/providers/file-store.js +341 -24
  173. package/dist/core/memory/providers/file-store.js.map +1 -1
  174. package/dist/core/memory/worker-memory-tools.d.ts +5 -0
  175. package/dist/core/memory/worker-memory-tools.d.ts.map +1 -0
  176. package/dist/core/memory/worker-memory-tools.js +5 -0
  177. package/dist/core/memory/worker-memory-tools.js.map +1 -0
  178. package/dist/core/memory-controller.d.ts +10 -1
  179. package/dist/core/memory-controller.d.ts.map +1 -1
  180. package/dist/core/memory-controller.js +72 -8
  181. package/dist/core/memory-controller.js.map +1 -1
  182. package/dist/core/model-capability.d.ts +7 -0
  183. package/dist/core/model-capability.d.ts.map +1 -1
  184. package/dist/core/model-capability.js +12 -0
  185. package/dist/core/model-capability.js.map +1 -1
  186. package/dist/core/model-registry.d.ts.map +1 -1
  187. package/dist/core/model-registry.js +2 -10
  188. package/dist/core/model-registry.js.map +1 -1
  189. package/dist/core/model-router-controller.d.ts +3 -2
  190. package/dist/core/model-router-controller.d.ts.map +1 -1
  191. package/dist/core/model-router-controller.js +3 -2
  192. package/dist/core/model-router-controller.js.map +1 -1
  193. package/dist/core/orchestration/contracts.d.ts +16 -12
  194. package/dist/core/orchestration/contracts.d.ts.map +1 -1
  195. package/dist/core/orchestration/contracts.js +2 -2
  196. package/dist/core/orchestration/contracts.js.map +1 -1
  197. package/dist/core/orchestration/lane-tool-manifests.d.ts +2 -2
  198. package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
  199. package/dist/core/orchestration/lane-tool-manifests.js +6 -1
  200. package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
  201. package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
  202. package/dist/core/orchestration/profile-registry.js +14 -0
  203. package/dist/core/orchestration/profile-registry.js.map +1 -1
  204. package/dist/core/orchestration/task-profile-writer.d.ts +7 -4
  205. package/dist/core/orchestration/task-profile-writer.d.ts.map +1 -1
  206. package/dist/core/orchestration/task-profile-writer.js +71 -59
  207. package/dist/core/orchestration/task-profile-writer.js.map +1 -1
  208. package/dist/core/orchestration/thinking-level-schema.d.ts +7 -0
  209. package/dist/core/orchestration/thinking-level-schema.d.ts.map +1 -0
  210. package/dist/core/orchestration/thinking-level-schema.js +19 -0
  211. package/dist/core/orchestration/thinking-level-schema.js.map +1 -0
  212. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
  213. package/dist/core/orchestration/worker-execution-contract.js +12 -5
  214. package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
  215. package/dist/core/provider-prompt-contracts.d.ts +1 -4
  216. package/dist/core/provider-prompt-contracts.d.ts.map +1 -1
  217. package/dist/core/provider-prompt-contracts.js +13 -29
  218. package/dist/core/provider-prompt-contracts.js.map +1 -1
  219. package/dist/core/provider-request-context-controller.d.ts +2 -0
  220. package/dist/core/provider-request-context-controller.d.ts.map +1 -1
  221. package/dist/core/provider-request-context-controller.js +10 -3
  222. package/dist/core/provider-request-context-controller.js.map +1 -1
  223. package/dist/core/reflection-controller.d.ts +63 -27
  224. package/dist/core/reflection-controller.d.ts.map +1 -1
  225. package/dist/core/reflection-controller.js +300 -132
  226. package/dist/core/reflection-controller.js.map +1 -1
  227. package/dist/core/runtime-builder.d.ts +1 -0
  228. package/dist/core/runtime-builder.d.ts.map +1 -1
  229. package/dist/core/runtime-builder.js +25 -14
  230. package/dist/core/runtime-builder.js.map +1 -1
  231. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
  232. package/dist/core/secrets/credential-exposure-guard.js +55 -10
  233. package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
  234. package/dist/core/session-role.d.ts +6 -8
  235. package/dist/core/session-role.d.ts.map +1 -1
  236. package/dist/core/session-role.js +8 -18
  237. package/dist/core/session-role.js.map +1 -1
  238. package/dist/core/settings-manager.d.ts +13 -16
  239. package/dist/core/settings-manager.d.ts.map +1 -1
  240. package/dist/core/settings-manager.js +53 -50
  241. package/dist/core/settings-manager.js.map +1 -1
  242. package/dist/core/skill-vault.d.ts +15 -0
  243. package/dist/core/skill-vault.d.ts.map +1 -1
  244. package/dist/core/skill-vault.js +79 -45
  245. package/dist/core/skill-vault.js.map +1 -1
  246. package/dist/core/skills.d.ts +3 -0
  247. package/dist/core/skills.d.ts.map +1 -1
  248. package/dist/core/skills.js +6 -6
  249. package/dist/core/skills.js.map +1 -1
  250. package/dist/core/system-prompt-builder.d.ts +2 -0
  251. package/dist/core/system-prompt-builder.d.ts.map +1 -1
  252. package/dist/core/system-prompt-builder.js +52 -12
  253. package/dist/core/system-prompt-builder.js.map +1 -1
  254. package/dist/core/system-prompt.js +1 -1
  255. package/dist/core/system-prompt.js.map +1 -1
  256. package/dist/core/tool-capability-policy.d.ts +3 -0
  257. package/dist/core/tool-capability-policy.d.ts.map +1 -1
  258. package/dist/core/tool-capability-policy.js +13 -2
  259. package/dist/core/tool-capability-policy.js.map +1 -1
  260. package/dist/core/toolkit/script-runner.d.ts +2 -1
  261. package/dist/core/toolkit/script-runner.d.ts.map +1 -1
  262. package/dist/core/toolkit/script-runner.js +10 -2
  263. package/dist/core/toolkit/script-runner.js.map +1 -1
  264. package/dist/core/tools/delegate-status.d.ts +3 -1
  265. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  266. package/dist/core/tools/delegate-status.js +5 -1
  267. package/dist/core/tools/delegate-status.js.map +1 -1
  268. package/dist/core/tools/delegate.d.ts +4 -13
  269. package/dist/core/tools/delegate.d.ts.map +1 -1
  270. package/dist/core/tools/delegate.js +173 -73
  271. package/dist/core/tools/delegate.js.map +1 -1
  272. package/dist/core/tools/goal.d.ts +3 -4
  273. package/dist/core/tools/goal.d.ts.map +1 -1
  274. package/dist/core/tools/goal.js +24 -7
  275. package/dist/core/tools/goal.js.map +1 -1
  276. package/dist/core/tools/profile-writer.d.ts +2 -8
  277. package/dist/core/tools/profile-writer.d.ts.map +1 -1
  278. package/dist/core/tools/profile-writer.js +6 -18
  279. package/dist/core/tools/profile-writer.js.map +1 -1
  280. package/dist/core/tools/run-toolkit-script.d.ts +1 -1
  281. package/dist/core/tools/run-toolkit-script.d.ts.map +1 -1
  282. package/dist/core/tools/run-toolkit-script.js +2 -2
  283. package/dist/core/tools/run-toolkit-script.js.map +1 -1
  284. package/dist/core/tools/skill-audit.d.ts +28 -1
  285. package/dist/core/tools/skill-audit.d.ts.map +1 -1
  286. package/dist/core/tools/skill-audit.js +56 -12
  287. package/dist/core/tools/skill-audit.js.map +1 -1
  288. package/dist/core/tools/skill.d.ts +12 -1
  289. package/dist/core/tools/skill.d.ts.map +1 -1
  290. package/dist/core/tools/skill.js +52 -0
  291. package/dist/core/tools/skill.js.map +1 -1
  292. package/dist/core/tools/skillify.d.ts.map +1 -1
  293. package/dist/core/tools/skillify.js +16 -7
  294. package/dist/core/tools/skillify.js.map +1 -1
  295. package/dist/core/tools/task-steps.js +1 -1
  296. package/dist/core/tools/task-steps.js.map +1 -1
  297. package/dist/core/tools/tmux-dispatch.d.ts +4 -16
  298. package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
  299. package/dist/core/tools/tmux-dispatch.js +5 -20
  300. package/dist/core/tools/tmux-dispatch.js.map +1 -1
  301. package/dist/core/tools/tool-task.d.ts +1 -0
  302. package/dist/core/tools/tool-task.d.ts.map +1 -1
  303. package/dist/core/tools/tool-task.js +13 -8
  304. package/dist/core/tools/tool-task.js.map +1 -1
  305. package/dist/core/util/atomic-file.d.ts +2 -0
  306. package/dist/core/util/atomic-file.d.ts.map +1 -1
  307. package/dist/core/util/atomic-file.js +4 -0
  308. package/dist/core/util/atomic-file.js.map +1 -1
  309. package/dist/core/worktree-sync/codes.d.ts +1 -2
  310. package/dist/core/worktree-sync/codes.d.ts.map +1 -1
  311. package/dist/core/worktree-sync/codes.js +1 -2
  312. package/dist/core/worktree-sync/codes.js.map +1 -1
  313. package/dist/core/worktree-sync/lane-gate.d.ts +4 -8
  314. package/dist/core/worktree-sync/lane-gate.d.ts.map +1 -1
  315. package/dist/core/worktree-sync/lane-gate.js +5 -51
  316. package/dist/core/worktree-sync/lane-gate.js.map +1 -1
  317. package/dist/index.d.ts +5 -0
  318. package/dist/index.d.ts.map +1 -1
  319. package/dist/index.js +7 -0
  320. package/dist/index.js.map +1 -1
  321. package/dist/modes/interactive/auto-learn-controller.d.ts +6 -7
  322. package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
  323. package/dist/modes/interactive/auto-learn-controller.js +32 -207
  324. package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
  325. package/dist/modes/interactive/autonomy-commands.js +2 -2
  326. package/dist/modes/interactive/autonomy-commands.js.map +1 -1
  327. package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
  328. package/dist/modes/interactive/components/activity-lane.js +12 -23
  329. package/dist/modes/interactive/components/activity-lane.js.map +1 -1
  330. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  331. package/dist/modes/interactive/components/custom-message.js +142 -1
  332. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  333. package/dist/modes/interactive/components/fitness-role-selector.d.ts.map +1 -1
  334. package/dist/modes/interactive/components/fitness-role-selector.js +2 -2
  335. package/dist/modes/interactive/components/fitness-role-selector.js.map +1 -1
  336. package/dist/modes/interactive/components/footer.js +1 -1
  337. package/dist/modes/interactive/components/footer.js.map +1 -1
  338. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  339. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  340. package/dist/modes/interactive/components/settings-selector.js +150 -73
  341. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  342. package/dist/modes/interactive/report-commands.d.ts.map +1 -1
  343. package/dist/modes/interactive/report-commands.js +8 -4
  344. package/dist/modes/interactive/report-commands.js.map +1 -1
  345. package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -1
  346. package/dist/modes/interactive/settings-selector-flow.js +10 -0
  347. package/dist/modes/interactive/settings-selector-flow.js.map +1 -1
  348. package/docs/extensions.md +8 -0
  349. package/docs/harness-architecture.md +28 -32
  350. package/docs/index.md +1 -1
  351. package/docs/process-matrix.md +8 -6
  352. package/docs/resources.md +1 -1
  353. package/docs/settings.md +61 -51
  354. package/docs/tmux-agent-manager.md +47 -40
  355. package/docs/usage.md +1 -1
  356. package/docs/worker-profiles.md +8 -6
  357. package/docs/worktree-sync.md +26 -20
  358. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  359. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  360. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  361. package/examples/extensions/sandbox/package-lock.json +2 -2
  362. package/examples/extensions/sandbox/package.json +1 -1
  363. package/examples/extensions/with-deps/package-lock.json +2 -2
  364. package/examples/extensions/with-deps/package.json +1 -1
  365. package/npm-shrinkwrap.json +12 -12
  366. package/package.json +4 -4
  367. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +0 -133
  368. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +0 -1
  369. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +0 -199
  370. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +0 -1
  371. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +0 -312
@@ -59,6 +59,16 @@ export type SkillLoadResult = {
59
59
  reason: "not_found" | "body_too_large" | "invalid_body" | "read_failed" | "pin_limit";
60
60
  message: string;
61
61
  };
62
+ export type SkillReadResult = {
63
+ ok: true;
64
+ name: string;
65
+ description: string;
66
+ body: string;
67
+ } | {
68
+ ok: false;
69
+ reason: "not_found" | "body_too_large" | "invalid_body" | "read_failed";
70
+ message: string;
71
+ };
62
72
  export interface SkillVaultControllerOptions {
63
73
  getSkills(): readonly Skill[];
64
74
  now?: () => number;
@@ -80,6 +90,10 @@ export declare class SkillVaultController {
80
90
  private contextRevision;
81
91
  constructor(options: SkillVaultControllerOptions);
82
92
  search(rawQuery: string): SkillSearchResult;
93
+ /** Read one eligible skill body without loading, evicting, or otherwise mutating the vault. */
94
+ read(name: string, requester?: SkillVaultRequester): SkillReadResult;
95
+ /** Host-only metadata snapshot for read-only audit brokers; paths never cross the tool boundary. */
96
+ getSkillsSnapshot(): readonly Skill[];
83
97
  load(name: string, requester: SkillVaultRequester, pin?: boolean): SkillLoadResult;
84
98
  unload(name?: string): {
85
99
  ok: true;
@@ -96,6 +110,7 @@ export declare class SkillVaultController {
96
110
  /** Record host-observed work derived from an active skill, independent of agent cooperation. */
97
111
  noteActivity(): void;
98
112
  private slotStatus;
113
+ private readSkillBody;
99
114
  private reconcile;
100
115
  private reconcileSlot;
101
116
  private replaceState;
@@ -1 +1 @@
1
- {"version":3,"file":"skill-vault.d.ts","sourceRoot":"","sources":["../../src/core/skill-vault.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill-vault.d.ts","sourceRoot":"","sources":["../../src/core/skill-vault.ts"],"names":[],"mappings":"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"}
@@ -47,6 +47,9 @@ function aggregateBodyBytes(slots) {
47
47
  total += slot.bodyBytes;
48
48
  return total;
49
49
  }
50
+ function skillReadFailure() {
51
+ return { ok: false, reason: "read_failed", message: "Skill could not be read." };
52
+ }
50
53
  /** Per-skill use is unobservable host-side (every loaded body rides every request), so eviction is honest FIFO by loadedAtMs: oldest unpinned first, oldest pinned only once no unpinned slot remains. */
51
54
  function evictionVictimName(slots, excludeName) {
52
55
  let victim;
@@ -96,6 +99,20 @@ export class SkillVaultController {
96
99
  .map(({ skill }) => ({ name: skill.name, description: compactDescription(skill.description) }));
97
100
  return { candidates };
98
101
  }
102
+ /** Read one eligible skill body without loading, evicting, or otherwise mutating the vault. */
103
+ read(name, requester = "model") {
104
+ const skill = this.getSkills().find((candidate) => candidate.name === name && (requester === "user" || !candidate.disableModelInvocation));
105
+ if (!skill)
106
+ return { ok: false, reason: "not_found", message: `No eligible skill named ${JSON.stringify(name)}.` };
107
+ const bodyResult = this.readSkillBody(skill, this.resolveMaxBodyBytes(), "read");
108
+ if (!bodyResult.ok)
109
+ return bodyResult;
110
+ return { ok: true, name: skill.name, description: skill.description, body: bodyResult.body };
111
+ }
112
+ /** Host-only metadata snapshot for read-only audit brokers; paths never cross the tool boundary. */
113
+ getSkillsSnapshot() {
114
+ return this.getSkills().map((skill) => ({ ...skill, sourceInfo: { ...skill.sourceInfo } }));
115
+ }
99
116
  load(name, requester, pin = false) {
100
117
  const now = this.now();
101
118
  this.reconcile(now);
@@ -118,51 +135,10 @@ export class SkillVaultController {
118
135
  }
119
136
  }
120
137
  const maxBodyBytes = this.resolveMaxBodyBytes();
121
- let before;
122
- try {
123
- before = statSync(skill.filePath);
124
- }
125
- catch (error) {
126
- return { ok: false, reason: "read_failed", message: error instanceof Error ? error.message : String(error) };
127
- }
128
- let raw;
129
- try {
130
- raw = readBoundedTextFileSync(skill.filePath, maxBodyBytes + MAX_SKILL_FRONTMATTER_BYTES, `Skill ${JSON.stringify(skill.name)}`);
131
- }
132
- catch (error) {
133
- const message = error instanceof Error ? error.message : String(error);
134
- return message.includes("exceeds its byte limit")
135
- ? {
136
- ok: false,
137
- reason: "body_too_large",
138
- message: `Skill body exceeds ${maxBodyBytes} bytes; not truncated.`,
139
- }
140
- : { ok: false, reason: "read_failed", message };
141
- }
142
- const parsed = parseFrontmatter(raw);
143
- const currentName = parsed.frontmatter.name ?? skill.name;
144
- const body = stripResourceProfileBlocks(parsed.body).trim();
145
- if (currentName !== skill.name || !parsed.frontmatter.description || !body) {
146
- return { ok: false, reason: "invalid_body", message: "Skill metadata changed or its body is empty." };
147
- }
148
- const bodyBytes = Buffer.byteLength(body, "utf8");
149
- if (bodyBytes > maxBodyBytes) {
150
- return {
151
- ok: false,
152
- reason: "body_too_large",
153
- message: `Skill body exceeds ${maxBodyBytes} bytes; not truncated.`,
154
- };
155
- }
156
- let file;
157
- try {
158
- file = statSync(skill.filePath);
159
- }
160
- catch (error) {
161
- return { ok: false, reason: "read_failed", message: error instanceof Error ? error.message : String(error) };
162
- }
163
- if (!sameFileVersion(before, file)) {
164
- return { ok: false, reason: "read_failed", message: "Skill changed while it was being loaded." };
165
- }
138
+ const bodyResult = this.readSkillBody(skill, maxBodyBytes, "load");
139
+ if (!bodyResult.ok)
140
+ return bodyResult;
141
+ const { body, bodyBytes, file } = bodyResult;
166
142
  const next = new Map(this.slots);
167
143
  next.set(skill.name, {
168
144
  state: "loaded_pending",
@@ -281,6 +257,64 @@ export class SkillVaultController {
281
257
  useCount: slot.useCount,
282
258
  };
283
259
  }
260
+ readSkillBody(skill, maxBodyBytes, mode) {
261
+ let before;
262
+ try {
263
+ before = statSync(skill.filePath);
264
+ }
265
+ catch (error) {
266
+ return mode === "read"
267
+ ? skillReadFailure()
268
+ : { ok: false, reason: "read_failed", message: error instanceof Error ? error.message : String(error) };
269
+ }
270
+ let raw;
271
+ try {
272
+ raw = readBoundedTextFileSync(skill.filePath, maxBodyBytes + MAX_SKILL_FRONTMATTER_BYTES, `Skill ${JSON.stringify(skill.name)}`);
273
+ }
274
+ catch (error) {
275
+ const message = error instanceof Error ? error.message : String(error);
276
+ return message.includes("exceeds its byte limit")
277
+ ? {
278
+ ok: false,
279
+ reason: "body_too_large",
280
+ message: `Skill body exceeds ${maxBodyBytes} bytes; not truncated.`,
281
+ }
282
+ : mode === "read"
283
+ ? skillReadFailure()
284
+ : { ok: false, reason: "read_failed", message };
285
+ }
286
+ const parsed = parseFrontmatter(raw);
287
+ const currentName = parsed.frontmatter.name ?? skill.name;
288
+ const body = stripResourceProfileBlocks(parsed.body).trim();
289
+ if (currentName !== skill.name || !parsed.frontmatter.description || !body) {
290
+ return { ok: false, reason: "invalid_body", message: "Skill metadata changed or its body is empty." };
291
+ }
292
+ const bodyBytes = Buffer.byteLength(body, "utf8");
293
+ if (bodyBytes > maxBodyBytes) {
294
+ return {
295
+ ok: false,
296
+ reason: "body_too_large",
297
+ message: `Skill body exceeds ${maxBodyBytes} bytes; not truncated.`,
298
+ };
299
+ }
300
+ let file;
301
+ try {
302
+ file = statSync(skill.filePath);
303
+ }
304
+ catch (error) {
305
+ return mode === "read"
306
+ ? skillReadFailure()
307
+ : { ok: false, reason: "read_failed", message: error instanceof Error ? error.message : String(error) };
308
+ }
309
+ if (!sameFileVersion(before, file)) {
310
+ return {
311
+ ok: false,
312
+ reason: "read_failed",
313
+ message: mode === "read" ? "Skill changed while it was being read." : "Skill changed while it was being loaded.",
314
+ };
315
+ }
316
+ return { ok: true, body, bodyBytes, file };
317
+ }
284
318
  reconcile(now) {
285
319
  if (this.slots.size === 0)
286
320
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"skill-vault.js","sourceRoot":"","sources":["../../src/core/skill-vault.ts"],"names":[],"mappings":"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","sourcesContent":["import { statSync } from \"node:fs\";\nimport { performance } from \"node:perf_hooks\";\nimport { composeRequestSystemPrompt } from \"@caupulican/pi-agent-core/provider-request-planner\";\nimport { parseFrontmatter } from \"../utils/frontmatter.ts\";\nimport { stripResourceProfileBlocks } from \"./resource-profile-blocks.ts\";\nimport { MAX_SKILL_FRONTMATTER_BYTES, type Skill, type SkillFrontmatter } from \"./skills.ts\";\nimport { readBoundedTextFileSync, sameFileVersion } from \"./util/bounded-file.ts\";\n\nexport const DEFAULT_SKILL_IDLE_TIMEOUT_MS = 10 * 60 * 1000;\nexport const MAX_ACTIVE_SKILL_BODY_BYTES = 64 * 1024;\nexport const MIN_ACTIVE_SKILL_BODY_BYTES = 4 * 1024;\nexport const MAX_LOADED_SKILLS = 3;\nexport const MAX_PINNED_SKILLS = 2;\nconst MAX_SEARCH_RESULTS = 5;\nconst MAX_SEARCH_DESCRIPTION_CHARS = 240;\n\ntype SkillVaultRequester = \"model\" | \"user\";\ntype SkillVaultUnloadReason = \"explicit\" | \"idle_expired\" | \"resource_unavailable\" | \"budget_exceeded\";\n\ninterface LoadedSkill {\n\tskill: Skill;\n\tbodyBytes: number;\n\tsystemPromptSection: string;\n\trequester: SkillVaultRequester;\n\tpinned: boolean;\n\tloadedAtMs: number;\n\tfileDevice: number;\n\tfileInode: number;\n\tfileSize: number;\n\tfileModifiedAtMs: number;\n\tfileChangedAtMs: number;\n}\n\ntype SkillSlotState =\n\t| ({ state: \"loaded_pending\" } & LoadedSkill)\n\t| ({ state: \"active\"; lastUsedAtMs: number; useCount: number } & LoadedSkill);\n\nexport interface SkillSlotStatus {\n\tstate: SkillSlotState[\"state\"];\n\tname: string;\n\tpinned: boolean;\n\tloadedAtMs: number;\n\tlastUsedAtMs?: number;\n\tidleForMs?: number;\n\texpiresInMs?: number;\n\tuseCount?: number;\n}\n\nexport interface SkillVaultStatus {\n\tidleTimeoutMs: number;\n\tslots: SkillSlotStatus[];\n\treason?: SkillVaultUnloadReason;\n}\n\nexport interface SkillSearchResult {\n\tcandidates: Array<{ name: string; description: string }>;\n}\n\nexport type SkillLoadResult =\n\t| { ok: true; state: \"loaded_pending\"; name: string; baseDir: string; pinned: boolean; evicted?: string[] }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"not_found\" | \"body_too_large\" | \"invalid_body\" | \"read_failed\" | \"pin_limit\";\n\t\t\tmessage: string;\n\t };\n\nexport interface SkillVaultControllerOptions {\n\tgetSkills(): readonly Skill[];\n\tnow?: () => number;\n\tidleTimeoutMs?: number;\n\tgetMaxBodyBytes?: () => number;\n\tonSkillUsed?: (skill: Skill, usedAtMs: number) => void;\n}\n\nfunction compactDescription(description: string): string {\n\tconst normalized = description.replace(/\\s+/g, \" \").trim();\n\tif (normalized.length <= MAX_SEARCH_DESCRIPTION_CHARS) return normalized;\n\treturn `${normalized.slice(0, MAX_SEARCH_DESCRIPTION_CHARS - 1)}…`;\n}\n\nfunction queryTokens(value: string): string[] {\n\treturn [...new Set(value.toLowerCase().match(/[\\p{L}\\p{N}]+/gu) ?? [])];\n}\n\nfunction searchScore(skill: Skill, query: string, tokens: readonly string[]): number {\n\tconst name = skill.name.toLowerCase();\n\tconst description = skill.description.toLowerCase();\n\tlet score = name === query ? 100 : name.includes(query) ? 40 : description.includes(query) ? 20 : 0;\n\tfor (const token of tokens) {\n\t\tif (name === token) score += 16;\n\t\telse if (name.includes(token)) score += 8;\n\t\tif (description.includes(token)) score += 3;\n\t}\n\treturn score;\n}\n\nfunction activeSkillContext(skill: Skill, body: string): string {\n\treturn [`ACTIVE SKILL ${skill.name}`, `BASE ${skill.baseDir}`, \"NON-NEGOTIABLE WHILE ACTIVE:\", body].join(\"\\n\");\n}\n\nfunction slotLastUsedAtMs(slot: SkillSlotState): number {\n\treturn slot.state === \"loaded_pending\" ? slot.loadedAtMs : slot.lastUsedAtMs;\n}\n\nfunction aggregateBodyBytes(slots: ReadonlyMap<string, SkillSlotState>): number {\n\tlet total = 0;\n\tfor (const slot of slots.values()) total += slot.bodyBytes;\n\treturn total;\n}\n\n/** Per-skill use is unobservable host-side (every loaded body rides every request), so eviction is honest FIFO by loadedAtMs: oldest unpinned first, oldest pinned only once no unpinned slot remains. */\nfunction evictionVictimName(slots: ReadonlyMap<string, SkillSlotState>, excludeName?: string): string | undefined {\n\tlet victim: { name: string; pinned: boolean; loadedAtMs: number } | undefined;\n\tfor (const [name, slot] of slots) {\n\t\tif (name === excludeName) continue;\n\t\tif (\n\t\t\tvictim === undefined ||\n\t\t\t(victim.pinned && !slot.pinned) ||\n\t\t\t(victim.pinned === slot.pinned && slot.loadedAtMs < victim.loadedAtMs)\n\t\t) {\n\t\t\tvictim = { name, pinned: slot.pinned, loadedAtMs: slot.loadedAtMs };\n\t\t}\n\t}\n\treturn victim?.name;\n}\n\n/** Reserve at most roughly one context token's worth of bytes per advertised context token. */\nexport function resolveActiveSkillBodyByteLimit(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || !Number.isFinite(contextWindow) || contextWindow <= 0) {\n\t\treturn MAX_ACTIVE_SKILL_BODY_BYTES;\n\t}\n\treturn Math.min(MAX_ACTIVE_SKILL_BODY_BYTES, Math.max(MIN_ACTIVE_SKILL_BODY_BYTES, Math.floor(contextWindow)));\n}\n\n/** One host-owned, event-driven lifecycle for lazy skill discovery and transient context projection. */\nexport class SkillVaultController {\n\tprivate readonly getSkills: () => readonly Skill[];\n\tprivate readonly now: () => number;\n\tprivate readonly idleTimeoutMs: number;\n\tprivate readonly getMaxBodyBytes: () => number;\n\tprivate readonly onSkillUsed: ((skill: Skill, usedAtMs: number) => void) | undefined;\n\tprivate slots = new Map<string, SkillSlotState>();\n\tprivate unloadReason: SkillVaultUnloadReason | undefined;\n\tprivate contextRevision = 0;\n\n\tconstructor(options: SkillVaultControllerOptions) {\n\t\tif (!Number.isFinite(options.idleTimeoutMs ?? DEFAULT_SKILL_IDLE_TIMEOUT_MS)) {\n\t\t\tthrow new TypeError(\"Skill idle timeout must be finite.\");\n\t\t}\n\t\tthis.getSkills = options.getSkills;\n\t\tthis.now = options.now ?? (() => performance.now());\n\t\tthis.idleTimeoutMs = Math.max(1, options.idleTimeoutMs ?? DEFAULT_SKILL_IDLE_TIMEOUT_MS);\n\t\tthis.getMaxBodyBytes = options.getMaxBodyBytes ?? (() => MAX_ACTIVE_SKILL_BODY_BYTES);\n\t\tthis.onSkillUsed = options.onSkillUsed;\n\t}\n\n\tsearch(rawQuery: string): SkillSearchResult {\n\t\tconst query = rawQuery.trim().toLowerCase();\n\t\tconst tokens = queryTokens(query);\n\t\tif (!query || tokens.length === 0) return { candidates: [] };\n\t\tconst candidates = this.getSkills()\n\t\t\t.filter((skill) => !skill.disableModelInvocation)\n\t\t\t.map((skill) => ({ skill, score: searchScore(skill, query, tokens) }))\n\t\t\t.filter((entry) => entry.score > 0)\n\t\t\t.sort((left, right) => right.score - left.score || left.skill.name.localeCompare(right.skill.name))\n\t\t\t.slice(0, MAX_SEARCH_RESULTS)\n\t\t\t.map(({ skill }) => ({ name: skill.name, description: compactDescription(skill.description) }));\n\t\treturn { candidates };\n\t}\n\n\tload(name: string, requester: SkillVaultRequester, pin = false): SkillLoadResult {\n\t\tconst now = this.now();\n\t\tthis.reconcile(now);\n\t\tconst skill = this.getSkills().find(\n\t\t\t(candidate) => candidate.name === name && (requester === \"user\" || !candidate.disableModelInvocation),\n\t\t);\n\t\tif (!skill) {\n\t\t\treturn { ok: false, reason: \"not_found\", message: `No eligible skill named ${JSON.stringify(name)}.` };\n\t\t}\n\t\tif (pin) {\n\t\t\tlet pinnedCount = 0;\n\t\t\tfor (const [slotName, slot] of this.slots) {\n\t\t\t\tif (slotName !== skill.name && slot.pinned) pinnedCount++;\n\t\t\t}\n\t\t\tif (pinnedCount >= MAX_PINNED_SKILLS) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\treason: \"pin_limit\",\n\t\t\t\t\tmessage: `At most ${MAX_PINNED_SKILLS} skills can be pinned; unload a pinned skill or reload it without pin first.`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tconst maxBodyBytes = this.resolveMaxBodyBytes();\n\t\tlet before: ReturnType<typeof statSync>;\n\t\ttry {\n\t\t\tbefore = statSync(skill.filePath);\n\t\t} catch (error) {\n\t\t\treturn { ok: false, reason: \"read_failed\", message: error instanceof Error ? error.message : String(error) };\n\t\t}\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = readBoundedTextFileSync(\n\t\t\t\tskill.filePath,\n\t\t\t\tmaxBodyBytes + MAX_SKILL_FRONTMATTER_BYTES,\n\t\t\t\t`Skill ${JSON.stringify(skill.name)}`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\treturn message.includes(\"exceeds its byte limit\")\n\t\t\t\t? {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\treason: \"body_too_large\",\n\t\t\t\t\t\tmessage: `Skill body exceeds ${maxBodyBytes} bytes; not truncated.`,\n\t\t\t\t\t}\n\t\t\t\t: { ok: false, reason: \"read_failed\", message };\n\t\t}\n\t\tconst parsed = parseFrontmatter<SkillFrontmatter>(raw);\n\t\tconst currentName = parsed.frontmatter.name ?? skill.name;\n\t\tconst body = stripResourceProfileBlocks(parsed.body).trim();\n\t\tif (currentName !== skill.name || !parsed.frontmatter.description || !body) {\n\t\t\treturn { ok: false, reason: \"invalid_body\", message: \"Skill metadata changed or its body is empty.\" };\n\t\t}\n\t\tconst bodyBytes = Buffer.byteLength(body, \"utf8\");\n\t\tif (bodyBytes > maxBodyBytes) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"body_too_large\",\n\t\t\t\tmessage: `Skill body exceeds ${maxBodyBytes} bytes; not truncated.`,\n\t\t\t};\n\t\t}\n\t\tlet file: ReturnType<typeof statSync>;\n\t\ttry {\n\t\t\tfile = statSync(skill.filePath);\n\t\t} catch (error) {\n\t\t\treturn { ok: false, reason: \"read_failed\", message: error instanceof Error ? error.message : String(error) };\n\t\t}\n\t\tif (!sameFileVersion(before, file)) {\n\t\t\treturn { ok: false, reason: \"read_failed\", message: \"Skill changed while it was being loaded.\" };\n\t\t}\n\t\tconst next = new Map(this.slots);\n\t\tnext.set(skill.name, {\n\t\t\tstate: \"loaded_pending\",\n\t\t\tskill,\n\t\t\tbodyBytes,\n\t\t\tsystemPromptSection: activeSkillContext(skill, body),\n\t\t\trequester,\n\t\t\tpinned: pin,\n\t\t\tloadedAtMs: now,\n\t\t\tfileDevice: file.dev,\n\t\t\tfileInode: file.ino,\n\t\t\tfileSize: file.size,\n\t\t\tfileModifiedAtMs: file.mtimeMs,\n\t\t\tfileChangedAtMs: file.ctimeMs,\n\t\t});\n\t\tconst evicted: string[] = [];\n\t\twhile (next.size > MAX_LOADED_SKILLS || aggregateBodyBytes(next) > maxBodyBytes) {\n\t\t\tconst victim = evictionVictimName(next, skill.name);\n\t\t\tif (!victim) break;\n\t\t\tnext.delete(victim);\n\t\t\tevicted.push(victim);\n\t\t}\n\t\tthis.replaceState(next);\n\t\treturn {\n\t\t\tok: true,\n\t\t\tstate: \"loaded_pending\",\n\t\t\tname: skill.name,\n\t\t\tbaseDir: skill.baseDir,\n\t\t\tpinned: pin,\n\t\t\t...(evicted.length > 0 ? { evicted } : {}),\n\t\t};\n\t}\n\n\tunload(name?: string): { ok: true; unloaded: string[] } {\n\t\tthis.reconcile(this.now());\n\t\tconst target = name?.trim();\n\t\tconst unloaded = !target ? [...this.slots.keys()] : this.slots.has(target) ? [target] : [];\n\t\tif (unloaded.length > 0) {\n\t\t\tconst next = new Map(this.slots);\n\t\t\tfor (const slotName of unloaded) next.delete(slotName);\n\t\t\tthis.replaceState(next, \"explicit\");\n\t\t}\n\t\treturn { ok: true, unloaded };\n\t}\n\n\tstatus(): SkillVaultStatus {\n\t\tconst now = this.now();\n\t\tthis.reconcile(now);\n\t\tconst slots = [...this.slots.values()].map((slot) => this.slotStatus(slot, now));\n\t\treturn {\n\t\t\tidleTimeoutMs: this.idleTimeoutMs,\n\t\t\tslots,\n\t\t\t...(slots.length === 0 && this.unloadReason ? { reason: this.unloadReason } : {}),\n\t\t};\n\t}\n\n\tcommitSystemPromptSection(): string | undefined {\n\t\tconst now = this.now();\n\t\tthis.reconcile(now);\n\t\tif (this.slots.size === 0) return undefined;\n\t\tconst sections: string[] = [];\n\t\tfor (const [name, slot] of this.slots) {\n\t\t\tsections.push(slot.systemPromptSection);\n\t\t\tconst firstUse = slot.state === \"loaded_pending\";\n\t\t\tconst useCount = firstUse ? 1 : slot.useCount + 1;\n\t\t\tthis.slots.set(name, { ...slot, state: \"active\", lastUsedAtMs: now, useCount });\n\t\t\tif (firstUse) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.onSkillUsed?.(slot.skill, now);\n\t\t\t\t} catch {\n\t\t\t\t\t// Usage telemetry must never block skill application.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn sections.join(\"\\n\\n\");\n\t}\n\n\t/** Model the next request's transient system cost without treating a diagnostic read as use. */\n\tpreviewSystemPromptSection(): string | undefined {\n\t\tthis.reconcile(this.now());\n\t\tif (this.slots.size === 0) return undefined;\n\t\treturn [...this.slots.values()].map((slot) => slot.systemPromptSection).join(\"\\n\\n\");\n\t}\n\n\t/** Compose the exact provider system prompt for read-only diagnostics. */\n\tpreviewRequestSystemPrompt(base: string | undefined): string | undefined {\n\t\treturn composeRequestSystemPrompt(base, this.previewSystemPromptSection());\n\t}\n\n\t/** Monotonic identity for provider-visible skill projection changes. */\n\tgetContextRevision(): number {\n\t\tthis.reconcile(this.now());\n\t\treturn this.contextRevision;\n\t}\n\n\t/** Record host-observed work derived from an active skill, independent of agent cooperation. */\n\tnoteActivity(): void {\n\t\tconst now = this.now();\n\t\tfor (const [name, slot] of this.slots) {\n\t\t\tif (slot.state === \"active\") {\n\t\t\t\tthis.slots.set(name, { ...slot, lastUsedAtMs: now });\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate slotStatus(slot: SkillSlotState, now: number): SkillSlotStatus {\n\t\tif (slot.state === \"loaded_pending\") {\n\t\t\treturn { state: \"loaded_pending\", name: slot.skill.name, pinned: slot.pinned, loadedAtMs: slot.loadedAtMs };\n\t\t}\n\t\tconst idleForMs = Math.max(0, now - slot.lastUsedAtMs);\n\t\treturn {\n\t\t\tstate: \"active\",\n\t\t\tname: slot.skill.name,\n\t\t\tpinned: slot.pinned,\n\t\t\tloadedAtMs: slot.loadedAtMs,\n\t\t\tlastUsedAtMs: slot.lastUsedAtMs,\n\t\t\tidleForMs,\n\t\t\texpiresInMs: Math.max(0, this.idleTimeoutMs - idleForMs),\n\t\t\tuseCount: slot.useCount,\n\t\t};\n\t}\n\n\tprivate reconcile(now: number): void {\n\t\tif (this.slots.size === 0) return;\n\t\tconst maxBodyBytes = this.resolveMaxBodyBytes();\n\t\tconst skills = this.getSkills();\n\t\tconst next = new Map(this.slots);\n\t\tlet reason: SkillVaultUnloadReason | undefined;\n\t\tfor (const [name, slot] of this.slots) {\n\t\t\tconst slotReason = this.reconcileSlot(slot, skills, maxBodyBytes, now);\n\t\t\tif (slotReason !== undefined) {\n\t\t\t\tnext.delete(name);\n\t\t\t\treason = slotReason;\n\t\t\t}\n\t\t}\n\t\twhile (aggregateBodyBytes(next) > maxBodyBytes) {\n\t\t\tconst victim = evictionVictimName(next);\n\t\t\tif (!victim) break;\n\t\t\tnext.delete(victim);\n\t\t\treason = \"budget_exceeded\";\n\t\t}\n\t\tif (next.size !== this.slots.size) {\n\t\t\tthis.replaceState(next, reason);\n\t\t}\n\t}\n\n\tprivate reconcileSlot(\n\t\tslot: SkillSlotState,\n\t\tskills: readonly Skill[],\n\t\tmaxBodyBytes: number,\n\t\tnow: number,\n\t): SkillVaultUnloadReason | undefined {\n\t\tif (slot.bodyBytes > maxBodyBytes) return \"budget_exceeded\";\n\t\tconst currentSkill = skills.find(\n\t\t\t(skill) =>\n\t\t\t\tskill.name === slot.skill.name &&\n\t\t\t\tskill.filePath === slot.skill.filePath &&\n\t\t\t\t(slot.requester === \"user\" || !skill.disableModelInvocation),\n\t\t);\n\t\tif (!currentSkill) return \"resource_unavailable\";\n\t\ttry {\n\t\t\tconst file = statSync(slot.skill.filePath);\n\t\t\tif (\n\t\t\t\tfile.dev !== slot.fileDevice ||\n\t\t\t\tfile.ino !== slot.fileInode ||\n\t\t\t\tfile.size !== slot.fileSize ||\n\t\t\t\tfile.mtimeMs !== slot.fileModifiedAtMs ||\n\t\t\t\tfile.ctimeMs !== slot.fileChangedAtMs\n\t\t\t) {\n\t\t\t\treturn \"resource_unavailable\";\n\t\t\t}\n\t\t} catch {\n\t\t\treturn \"resource_unavailable\";\n\t\t}\n\t\tif (now - slotLastUsedAtMs(slot) >= this.idleTimeoutMs) return \"idle_expired\";\n\t\treturn undefined;\n\t}\n\n\tprivate replaceState(slots: Map<string, SkillSlotState>, unloadReason?: SkillVaultUnloadReason): void {\n\t\tthis.slots = slots;\n\t\tif (unloadReason !== undefined) this.unloadReason = unloadReason;\n\t\tthis.contextRevision++;\n\t}\n\n\tprivate resolveMaxBodyBytes(): number {\n\t\tconst configured = this.getMaxBodyBytes();\n\t\tif (!Number.isFinite(configured)) return 1;\n\t\treturn Math.min(MAX_ACTIVE_SKILL_BODY_BYTES, Math.max(1, Math.floor(configured)));\n\t}\n}\n"]}
1
+ {"version":3,"file":"skill-vault.js","sourceRoot":"","sources":["../../src/core/skill-vault.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Stats, statSync } from \"node:fs\";\nimport { performance } from \"node:perf_hooks\";\nimport { composeRequestSystemPrompt } from \"@caupulican/pi-agent-core/provider-request-planner\";\nimport { parseFrontmatter } from \"../utils/frontmatter.ts\";\nimport { stripResourceProfileBlocks } from \"./resource-profile-blocks.ts\";\nimport { MAX_SKILL_FRONTMATTER_BYTES, type Skill, type SkillFrontmatter } from \"./skills.ts\";\nimport { readBoundedTextFileSync, sameFileVersion } from \"./util/bounded-file.ts\";\n\nexport const DEFAULT_SKILL_IDLE_TIMEOUT_MS = 10 * 60 * 1000;\nexport const MAX_ACTIVE_SKILL_BODY_BYTES = 64 * 1024;\nexport const MIN_ACTIVE_SKILL_BODY_BYTES = 4 * 1024;\nexport const MAX_LOADED_SKILLS = 3;\nexport const MAX_PINNED_SKILLS = 2;\nconst MAX_SEARCH_RESULTS = 5;\nconst MAX_SEARCH_DESCRIPTION_CHARS = 240;\n\ntype SkillVaultRequester = \"model\" | \"user\";\ntype SkillVaultUnloadReason = \"explicit\" | \"idle_expired\" | \"resource_unavailable\" | \"budget_exceeded\";\ntype SkillBodyReadMode = \"read\" | \"load\";\ntype SkillFileStat = Stats;\n\ninterface LoadedSkill {\n\tskill: Skill;\n\tbodyBytes: number;\n\tsystemPromptSection: string;\n\trequester: SkillVaultRequester;\n\tpinned: boolean;\n\tloadedAtMs: number;\n\tfileDevice: number;\n\tfileInode: number;\n\tfileSize: number;\n\tfileModifiedAtMs: number;\n\tfileChangedAtMs: number;\n}\n\ntype SkillSlotState =\n\t| ({ state: \"loaded_pending\" } & LoadedSkill)\n\t| ({ state: \"active\"; lastUsedAtMs: number; useCount: number } & LoadedSkill);\n\nexport interface SkillSlotStatus {\n\tstate: SkillSlotState[\"state\"];\n\tname: string;\n\tpinned: boolean;\n\tloadedAtMs: number;\n\tlastUsedAtMs?: number;\n\tidleForMs?: number;\n\texpiresInMs?: number;\n\tuseCount?: number;\n}\n\nexport interface SkillVaultStatus {\n\tidleTimeoutMs: number;\n\tslots: SkillSlotStatus[];\n\treason?: SkillVaultUnloadReason;\n}\n\nexport interface SkillSearchResult {\n\tcandidates: Array<{ name: string; description: string }>;\n}\n\nexport type SkillLoadResult =\n\t| { ok: true; state: \"loaded_pending\"; name: string; baseDir: string; pinned: boolean; evicted?: string[] }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"not_found\" | \"body_too_large\" | \"invalid_body\" | \"read_failed\" | \"pin_limit\";\n\t\t\tmessage: string;\n\t };\n\nexport type SkillReadResult =\n\t| { ok: true; name: string; description: string; body: string }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"not_found\" | \"body_too_large\" | \"invalid_body\" | \"read_failed\";\n\t\t\tmessage: string;\n\t };\n\ntype SkillReadFailure = Exclude<SkillReadResult, { ok: true }>;\ntype SkillBodyReadResult = { ok: true; body: string; bodyBytes: number; file: SkillFileStat } | SkillReadFailure;\n\nexport interface SkillVaultControllerOptions {\n\tgetSkills(): readonly Skill[];\n\tnow?: () => number;\n\tidleTimeoutMs?: number;\n\tgetMaxBodyBytes?: () => number;\n\tonSkillUsed?: (skill: Skill, usedAtMs: number) => void;\n}\n\nfunction compactDescription(description: string): string {\n\tconst normalized = description.replace(/\\s+/g, \" \").trim();\n\tif (normalized.length <= MAX_SEARCH_DESCRIPTION_CHARS) return normalized;\n\treturn `${normalized.slice(0, MAX_SEARCH_DESCRIPTION_CHARS - 1)}…`;\n}\n\nfunction queryTokens(value: string): string[] {\n\treturn [...new Set(value.toLowerCase().match(/[\\p{L}\\p{N}]+/gu) ?? [])];\n}\n\nfunction searchScore(skill: Skill, query: string, tokens: readonly string[]): number {\n\tconst name = skill.name.toLowerCase();\n\tconst description = skill.description.toLowerCase();\n\tlet score = name === query ? 100 : name.includes(query) ? 40 : description.includes(query) ? 20 : 0;\n\tfor (const token of tokens) {\n\t\tif (name === token) score += 16;\n\t\telse if (name.includes(token)) score += 8;\n\t\tif (description.includes(token)) score += 3;\n\t}\n\treturn score;\n}\n\nfunction activeSkillContext(skill: Skill, body: string): string {\n\treturn [`ACTIVE SKILL ${skill.name}`, `BASE ${skill.baseDir}`, \"NON-NEGOTIABLE WHILE ACTIVE:\", body].join(\"\\n\");\n}\n\nfunction slotLastUsedAtMs(slot: SkillSlotState): number {\n\treturn slot.state === \"loaded_pending\" ? slot.loadedAtMs : slot.lastUsedAtMs;\n}\n\nfunction aggregateBodyBytes(slots: ReadonlyMap<string, SkillSlotState>): number {\n\tlet total = 0;\n\tfor (const slot of slots.values()) total += slot.bodyBytes;\n\treturn total;\n}\n\nfunction skillReadFailure(): SkillReadFailure {\n\treturn { ok: false, reason: \"read_failed\", message: \"Skill could not be read.\" };\n}\n\n/** Per-skill use is unobservable host-side (every loaded body rides every request), so eviction is honest FIFO by loadedAtMs: oldest unpinned first, oldest pinned only once no unpinned slot remains. */\nfunction evictionVictimName(slots: ReadonlyMap<string, SkillSlotState>, excludeName?: string): string | undefined {\n\tlet victim: { name: string; pinned: boolean; loadedAtMs: number } | undefined;\n\tfor (const [name, slot] of slots) {\n\t\tif (name === excludeName) continue;\n\t\tif (\n\t\t\tvictim === undefined ||\n\t\t\t(victim.pinned && !slot.pinned) ||\n\t\t\t(victim.pinned === slot.pinned && slot.loadedAtMs < victim.loadedAtMs)\n\t\t) {\n\t\t\tvictim = { name, pinned: slot.pinned, loadedAtMs: slot.loadedAtMs };\n\t\t}\n\t}\n\treturn victim?.name;\n}\n\n/** Reserve at most roughly one context token's worth of bytes per advertised context token. */\nexport function resolveActiveSkillBodyByteLimit(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || !Number.isFinite(contextWindow) || contextWindow <= 0) {\n\t\treturn MAX_ACTIVE_SKILL_BODY_BYTES;\n\t}\n\treturn Math.min(MAX_ACTIVE_SKILL_BODY_BYTES, Math.max(MIN_ACTIVE_SKILL_BODY_BYTES, Math.floor(contextWindow)));\n}\n\n/** One host-owned, event-driven lifecycle for lazy skill discovery and transient context projection. */\nexport class SkillVaultController {\n\tprivate readonly getSkills: () => readonly Skill[];\n\tprivate readonly now: () => number;\n\tprivate readonly idleTimeoutMs: number;\n\tprivate readonly getMaxBodyBytes: () => number;\n\tprivate readonly onSkillUsed: ((skill: Skill, usedAtMs: number) => void) | undefined;\n\tprivate slots = new Map<string, SkillSlotState>();\n\tprivate unloadReason: SkillVaultUnloadReason | undefined;\n\tprivate contextRevision = 0;\n\n\tconstructor(options: SkillVaultControllerOptions) {\n\t\tif (!Number.isFinite(options.idleTimeoutMs ?? DEFAULT_SKILL_IDLE_TIMEOUT_MS)) {\n\t\t\tthrow new TypeError(\"Skill idle timeout must be finite.\");\n\t\t}\n\t\tthis.getSkills = options.getSkills;\n\t\tthis.now = options.now ?? (() => performance.now());\n\t\tthis.idleTimeoutMs = Math.max(1, options.idleTimeoutMs ?? DEFAULT_SKILL_IDLE_TIMEOUT_MS);\n\t\tthis.getMaxBodyBytes = options.getMaxBodyBytes ?? (() => MAX_ACTIVE_SKILL_BODY_BYTES);\n\t\tthis.onSkillUsed = options.onSkillUsed;\n\t}\n\n\tsearch(rawQuery: string): SkillSearchResult {\n\t\tconst query = rawQuery.trim().toLowerCase();\n\t\tconst tokens = queryTokens(query);\n\t\tif (!query || tokens.length === 0) return { candidates: [] };\n\t\tconst candidates = this.getSkills()\n\t\t\t.filter((skill) => !skill.disableModelInvocation)\n\t\t\t.map((skill) => ({ skill, score: searchScore(skill, query, tokens) }))\n\t\t\t.filter((entry) => entry.score > 0)\n\t\t\t.sort((left, right) => right.score - left.score || left.skill.name.localeCompare(right.skill.name))\n\t\t\t.slice(0, MAX_SEARCH_RESULTS)\n\t\t\t.map(({ skill }) => ({ name: skill.name, description: compactDescription(skill.description) }));\n\t\treturn { candidates };\n\t}\n\n\t/** Read one eligible skill body without loading, evicting, or otherwise mutating the vault. */\n\tread(name: string, requester: SkillVaultRequester = \"model\"): SkillReadResult {\n\t\tconst skill = this.getSkills().find(\n\t\t\t(candidate) => candidate.name === name && (requester === \"user\" || !candidate.disableModelInvocation),\n\t\t);\n\t\tif (!skill)\n\t\t\treturn { ok: false, reason: \"not_found\", message: `No eligible skill named ${JSON.stringify(name)}.` };\n\t\tconst bodyResult = this.readSkillBody(skill, this.resolveMaxBodyBytes(), \"read\");\n\t\tif (!bodyResult.ok) return bodyResult;\n\t\treturn { ok: true, name: skill.name, description: skill.description, body: bodyResult.body };\n\t}\n\n\t/** Host-only metadata snapshot for read-only audit brokers; paths never cross the tool boundary. */\n\tgetSkillsSnapshot(): readonly Skill[] {\n\t\treturn this.getSkills().map((skill) => ({ ...skill, sourceInfo: { ...skill.sourceInfo } }));\n\t}\n\n\tload(name: string, requester: SkillVaultRequester, pin = false): SkillLoadResult {\n\t\tconst now = this.now();\n\t\tthis.reconcile(now);\n\t\tconst skill = this.getSkills().find(\n\t\t\t(candidate) => candidate.name === name && (requester === \"user\" || !candidate.disableModelInvocation),\n\t\t);\n\t\tif (!skill) {\n\t\t\treturn { ok: false, reason: \"not_found\", message: `No eligible skill named ${JSON.stringify(name)}.` };\n\t\t}\n\t\tif (pin) {\n\t\t\tlet pinnedCount = 0;\n\t\t\tfor (const [slotName, slot] of this.slots) {\n\t\t\t\tif (slotName !== skill.name && slot.pinned) pinnedCount++;\n\t\t\t}\n\t\t\tif (pinnedCount >= MAX_PINNED_SKILLS) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\treason: \"pin_limit\",\n\t\t\t\t\tmessage: `At most ${MAX_PINNED_SKILLS} skills can be pinned; unload a pinned skill or reload it without pin first.`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tconst maxBodyBytes = this.resolveMaxBodyBytes();\n\t\tconst bodyResult = this.readSkillBody(skill, maxBodyBytes, \"load\");\n\t\tif (!bodyResult.ok) return bodyResult;\n\t\tconst { body, bodyBytes, file } = bodyResult;\n\t\tconst next = new Map(this.slots);\n\t\tnext.set(skill.name, {\n\t\t\tstate: \"loaded_pending\",\n\t\t\tskill,\n\t\t\tbodyBytes,\n\t\t\tsystemPromptSection: activeSkillContext(skill, body),\n\t\t\trequester,\n\t\t\tpinned: pin,\n\t\t\tloadedAtMs: now,\n\t\t\tfileDevice: file.dev,\n\t\t\tfileInode: file.ino,\n\t\t\tfileSize: file.size,\n\t\t\tfileModifiedAtMs: file.mtimeMs,\n\t\t\tfileChangedAtMs: file.ctimeMs,\n\t\t});\n\t\tconst evicted: string[] = [];\n\t\twhile (next.size > MAX_LOADED_SKILLS || aggregateBodyBytes(next) > maxBodyBytes) {\n\t\t\tconst victim = evictionVictimName(next, skill.name);\n\t\t\tif (!victim) break;\n\t\t\tnext.delete(victim);\n\t\t\tevicted.push(victim);\n\t\t}\n\t\tthis.replaceState(next);\n\t\treturn {\n\t\t\tok: true,\n\t\t\tstate: \"loaded_pending\",\n\t\t\tname: skill.name,\n\t\t\tbaseDir: skill.baseDir,\n\t\t\tpinned: pin,\n\t\t\t...(evicted.length > 0 ? { evicted } : {}),\n\t\t};\n\t}\n\n\tunload(name?: string): { ok: true; unloaded: string[] } {\n\t\tthis.reconcile(this.now());\n\t\tconst target = name?.trim();\n\t\tconst unloaded = !target ? [...this.slots.keys()] : this.slots.has(target) ? [target] : [];\n\t\tif (unloaded.length > 0) {\n\t\t\tconst next = new Map(this.slots);\n\t\t\tfor (const slotName of unloaded) next.delete(slotName);\n\t\t\tthis.replaceState(next, \"explicit\");\n\t\t}\n\t\treturn { ok: true, unloaded };\n\t}\n\n\tstatus(): SkillVaultStatus {\n\t\tconst now = this.now();\n\t\tthis.reconcile(now);\n\t\tconst slots = [...this.slots.values()].map((slot) => this.slotStatus(slot, now));\n\t\treturn {\n\t\t\tidleTimeoutMs: this.idleTimeoutMs,\n\t\t\tslots,\n\t\t\t...(slots.length === 0 && this.unloadReason ? { reason: this.unloadReason } : {}),\n\t\t};\n\t}\n\n\tcommitSystemPromptSection(): string | undefined {\n\t\tconst now = this.now();\n\t\tthis.reconcile(now);\n\t\tif (this.slots.size === 0) return undefined;\n\t\tconst sections: string[] = [];\n\t\tfor (const [name, slot] of this.slots) {\n\t\t\tsections.push(slot.systemPromptSection);\n\t\t\tconst firstUse = slot.state === \"loaded_pending\";\n\t\t\tconst useCount = firstUse ? 1 : slot.useCount + 1;\n\t\t\tthis.slots.set(name, { ...slot, state: \"active\", lastUsedAtMs: now, useCount });\n\t\t\tif (firstUse) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.onSkillUsed?.(slot.skill, now);\n\t\t\t\t} catch {\n\t\t\t\t\t// Usage telemetry must never block skill application.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn sections.join(\"\\n\\n\");\n\t}\n\n\t/** Model the next request's transient system cost without treating a diagnostic read as use. */\n\tpreviewSystemPromptSection(): string | undefined {\n\t\tthis.reconcile(this.now());\n\t\tif (this.slots.size === 0) return undefined;\n\t\treturn [...this.slots.values()].map((slot) => slot.systemPromptSection).join(\"\\n\\n\");\n\t}\n\n\t/** Compose the exact provider system prompt for read-only diagnostics. */\n\tpreviewRequestSystemPrompt(base: string | undefined): string | undefined {\n\t\treturn composeRequestSystemPrompt(base, this.previewSystemPromptSection());\n\t}\n\n\t/** Monotonic identity for provider-visible skill projection changes. */\n\tgetContextRevision(): number {\n\t\tthis.reconcile(this.now());\n\t\treturn this.contextRevision;\n\t}\n\n\t/** Record host-observed work derived from an active skill, independent of agent cooperation. */\n\tnoteActivity(): void {\n\t\tconst now = this.now();\n\t\tfor (const [name, slot] of this.slots) {\n\t\t\tif (slot.state === \"active\") {\n\t\t\t\tthis.slots.set(name, { ...slot, lastUsedAtMs: now });\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate slotStatus(slot: SkillSlotState, now: number): SkillSlotStatus {\n\t\tif (slot.state === \"loaded_pending\") {\n\t\t\treturn { state: \"loaded_pending\", name: slot.skill.name, pinned: slot.pinned, loadedAtMs: slot.loadedAtMs };\n\t\t}\n\t\tconst idleForMs = Math.max(0, now - slot.lastUsedAtMs);\n\t\treturn {\n\t\t\tstate: \"active\",\n\t\t\tname: slot.skill.name,\n\t\t\tpinned: slot.pinned,\n\t\t\tloadedAtMs: slot.loadedAtMs,\n\t\t\tlastUsedAtMs: slot.lastUsedAtMs,\n\t\t\tidleForMs,\n\t\t\texpiresInMs: Math.max(0, this.idleTimeoutMs - idleForMs),\n\t\t\tuseCount: slot.useCount,\n\t\t};\n\t}\n\n\tprivate readSkillBody(skill: Skill, maxBodyBytes: number, mode: SkillBodyReadMode): SkillBodyReadResult {\n\t\tlet before: SkillFileStat;\n\t\ttry {\n\t\t\tbefore = statSync(skill.filePath) as Stats;\n\t\t} catch (error) {\n\t\t\treturn mode === \"read\"\n\t\t\t\t? skillReadFailure()\n\t\t\t\t: { ok: false, reason: \"read_failed\", message: error instanceof Error ? error.message : String(error) };\n\t\t}\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = readBoundedTextFileSync(\n\t\t\t\tskill.filePath,\n\t\t\t\tmaxBodyBytes + MAX_SKILL_FRONTMATTER_BYTES,\n\t\t\t\t`Skill ${JSON.stringify(skill.name)}`,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\treturn message.includes(\"exceeds its byte limit\")\n\t\t\t\t? {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\treason: \"body_too_large\",\n\t\t\t\t\t\tmessage: `Skill body exceeds ${maxBodyBytes} bytes; not truncated.`,\n\t\t\t\t\t}\n\t\t\t\t: mode === \"read\"\n\t\t\t\t\t? skillReadFailure()\n\t\t\t\t\t: { ok: false, reason: \"read_failed\", message };\n\t\t}\n\t\tconst parsed = parseFrontmatter<SkillFrontmatter>(raw);\n\t\tconst currentName = parsed.frontmatter.name ?? skill.name;\n\t\tconst body = stripResourceProfileBlocks(parsed.body).trim();\n\t\tif (currentName !== skill.name || !parsed.frontmatter.description || !body) {\n\t\t\treturn { ok: false, reason: \"invalid_body\", message: \"Skill metadata changed or its body is empty.\" };\n\t\t}\n\t\tconst bodyBytes = Buffer.byteLength(body, \"utf8\");\n\t\tif (bodyBytes > maxBodyBytes) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"body_too_large\",\n\t\t\t\tmessage: `Skill body exceeds ${maxBodyBytes} bytes; not truncated.`,\n\t\t\t};\n\t\t}\n\t\tlet file: SkillFileStat;\n\t\ttry {\n\t\t\tfile = statSync(skill.filePath) as Stats;\n\t\t} catch (error) {\n\t\t\treturn mode === \"read\"\n\t\t\t\t? skillReadFailure()\n\t\t\t\t: { ok: false, reason: \"read_failed\", message: error instanceof Error ? error.message : String(error) };\n\t\t}\n\t\tif (!sameFileVersion(before, file)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"read_failed\",\n\t\t\t\tmessage:\n\t\t\t\t\tmode === \"read\" ? \"Skill changed while it was being read.\" : \"Skill changed while it was being loaded.\",\n\t\t\t};\n\t\t}\n\t\treturn { ok: true, body, bodyBytes, file };\n\t}\n\n\tprivate reconcile(now: number): void {\n\t\tif (this.slots.size === 0) return;\n\t\tconst maxBodyBytes = this.resolveMaxBodyBytes();\n\t\tconst skills = this.getSkills();\n\t\tconst next = new Map(this.slots);\n\t\tlet reason: SkillVaultUnloadReason | undefined;\n\t\tfor (const [name, slot] of this.slots) {\n\t\t\tconst slotReason = this.reconcileSlot(slot, skills, maxBodyBytes, now);\n\t\t\tif (slotReason !== undefined) {\n\t\t\t\tnext.delete(name);\n\t\t\t\treason = slotReason;\n\t\t\t}\n\t\t}\n\t\twhile (aggregateBodyBytes(next) > maxBodyBytes) {\n\t\t\tconst victim = evictionVictimName(next);\n\t\t\tif (!victim) break;\n\t\t\tnext.delete(victim);\n\t\t\treason = \"budget_exceeded\";\n\t\t}\n\t\tif (next.size !== this.slots.size) {\n\t\t\tthis.replaceState(next, reason);\n\t\t}\n\t}\n\n\tprivate reconcileSlot(\n\t\tslot: SkillSlotState,\n\t\tskills: readonly Skill[],\n\t\tmaxBodyBytes: number,\n\t\tnow: number,\n\t): SkillVaultUnloadReason | undefined {\n\t\tif (slot.bodyBytes > maxBodyBytes) return \"budget_exceeded\";\n\t\tconst currentSkill = skills.find(\n\t\t\t(skill) =>\n\t\t\t\tskill.name === slot.skill.name &&\n\t\t\t\tskill.filePath === slot.skill.filePath &&\n\t\t\t\t(slot.requester === \"user\" || !skill.disableModelInvocation),\n\t\t);\n\t\tif (!currentSkill) return \"resource_unavailable\";\n\t\ttry {\n\t\t\tconst file = statSync(slot.skill.filePath);\n\t\t\tif (\n\t\t\t\tfile.dev !== slot.fileDevice ||\n\t\t\t\tfile.ino !== slot.fileInode ||\n\t\t\t\tfile.size !== slot.fileSize ||\n\t\t\t\tfile.mtimeMs !== slot.fileModifiedAtMs ||\n\t\t\t\tfile.ctimeMs !== slot.fileChangedAtMs\n\t\t\t) {\n\t\t\t\treturn \"resource_unavailable\";\n\t\t\t}\n\t\t} catch {\n\t\t\treturn \"resource_unavailable\";\n\t\t}\n\t\tif (now - slotLastUsedAtMs(slot) >= this.idleTimeoutMs) return \"idle_expired\";\n\t\treturn undefined;\n\t}\n\n\tprivate replaceState(slots: Map<string, SkillSlotState>, unloadReason?: SkillVaultUnloadReason): void {\n\t\tthis.slots = slots;\n\t\tif (unloadReason !== undefined) this.unloadReason = unloadReason;\n\t\tthis.contextRevision++;\n\t}\n\n\tprivate resolveMaxBodyBytes(): number {\n\t\tconst configured = this.getMaxBodyBytes();\n\t\tif (!Number.isFinite(configured)) return 1;\n\t\treturn Math.min(MAX_ACTIVE_SKILL_BODY_BYTES, Math.max(1, Math.floor(configured)));\n\t}\n}\n"]}
@@ -3,6 +3,9 @@ import type { ResourceDiagnostic } from "./diagnostics.ts";
3
3
  import { type SourceInfo } from "./source-info.ts";
4
4
  /** Discovery retains only this bounded metadata prefix, never the whole skill body. */
5
5
  export declare const MAX_SKILL_FRONTMATTER_BYTES: number;
6
+ export declare const MAX_SKILL_NAME_LENGTH = 64;
7
+ /** Max description length per spec */
8
+ export declare const MAX_SKILL_DESCRIPTION_LENGTH = 1024;
6
9
  export interface SkillFrontmatter {
7
10
  name?: string;
8
11
  description?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAM/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG3D,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9E,uFAAuF;AACvF,eAAO,MAAM,2BAA2B,QAAY,CAAC;AAgBrD,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,sBAAsB,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,WAAW,EAAE,kBAAkB,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBxD;AAiBD,MAAM,WAAW,wBAAwB;IACxC,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C;AA0BD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA6BjE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,gBAAgB,CAGrF;AAuED,MAAM,WAAW,iBAAiB;IACjC,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,0CAA0C;IAC1C,eAAe,EAAE,OAAO,CAAC;IACzB,iFAAiF;IACjF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAiGvE"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAM/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG3D,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9E,uFAAuF;AACvF,eAAO,MAAM,2BAA2B,QAAY,CAAC;AAGrD,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,sCAAsC;AACtC,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAUjD,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,sBAAsB,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,WAAW,EAAE,kBAAkB,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBxD;AAiBD,MAAM,WAAW,wBAAwB;IACxC,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C;AA0BD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA6BjE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,gBAAgB,CAGrF;AAuED,MAAM,WAAW,iBAAiB;IACjC,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,0CAA0C;IAC1C,eAAe,EAAE,OAAO,CAAC;IACzB,iFAAiF;IACjF,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAiGvE"}
@@ -10,9 +10,9 @@ import { sameFileVersion } from "./util/bounded-file.js";
10
10
  /** Discovery retains only this bounded metadata prefix, never the whole skill body. */
11
11
  export const MAX_SKILL_FRONTMATTER_BYTES = 16 * 1024;
12
12
  const SKILL_FRONTMATTER_READ_CHUNK_BYTES = 1024;
13
- const MAX_NAME_LENGTH = 64;
13
+ export const MAX_SKILL_NAME_LENGTH = 64;
14
14
  /** Max description length per spec */
15
- const MAX_DESCRIPTION_LENGTH = 1024;
15
+ export const MAX_SKILL_DESCRIPTION_LENGTH = 1024;
16
16
  // Kept local rather than imported from settings-manager.ts's ThinkingLevel validation: that module
17
17
  // already imports validateSkillName FROM this file, so importing back would cycle. The literal set
18
18
  // is small and stable (mirrors settings-manager.ts's own VALID_THINKING_LEVELS).
@@ -26,8 +26,8 @@ function isSkillThinkingLevel(value) {
26
26
  */
27
27
  export function validateSkillName(name) {
28
28
  const errors = [];
29
- if (name.length > MAX_NAME_LENGTH) {
30
- errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);
29
+ if (name.length > MAX_SKILL_NAME_LENGTH) {
30
+ errors.push(`name exceeds ${MAX_SKILL_NAME_LENGTH} characters (${name.length})`);
31
31
  }
32
32
  if (!/^[a-z0-9-]+$/.test(name)) {
33
33
  errors.push(`name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)`);
@@ -48,8 +48,8 @@ function validateDescription(description) {
48
48
  if (!description || description.trim() === "") {
49
49
  errors.push("description is required");
50
50
  }
51
- else if (description.length > MAX_DESCRIPTION_LENGTH) {
52
- errors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`);
51
+ else if (description.length > MAX_SKILL_DESCRIPTION_LENGTH) {
52
+ errors.push(`description exceeds ${MAX_SKILL_DESCRIPTION_LENGTH} characters (${description.length})`);
53
53
  }
54
54
  return errors;
55
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@caupulican/pi-agent-core\";\nimport { closeSync, existsSync, fstatSync, openSync, readSync, statSync } from \"fs\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { parseFrontmatter } from \"../utils/frontmatter.ts\";\nimport { canonicalizePath, resolvePath } from \"../utils/paths.ts\";\nimport type { ResourceDiagnostic } from \"./diagnostics.ts\";\nimport { isResourcePathWithin } from \"./resource-traversal.ts\";\nimport { discoverSkillFiles } from \"./skill-discovery.ts\";\nimport { createSyntheticSourceInfo, type SourceInfo } from \"./source-info.ts\";\nimport { sameFileVersion } from \"./util/bounded-file.ts\";\n\n/** Discovery retains only this bounded metadata prefix, never the whole skill body. */\nexport const MAX_SKILL_FRONTMATTER_BYTES = 16 * 1024;\nconst SKILL_FRONTMATTER_READ_CHUNK_BYTES = 1024;\n\nconst MAX_NAME_LENGTH = 64;\n\n/** Max description length per spec */\nconst MAX_DESCRIPTION_LENGTH = 1024;\n\n// Kept local rather than imported from settings-manager.ts's ThinkingLevel validation: that module\n// already imports validateSkillName FROM this file, so importing back would cycle. The literal set\n// is small and stable (mirrors settings-manager.ts's own VALID_THINKING_LEVELS).\nconst VALID_SKILL_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\", \"ultra\"] as const;\nfunction isSkillThinkingLevel(value: unknown): value is ThinkingLevel {\n\treturn typeof value === \"string\" && (VALID_SKILL_THINKING_LEVELS as readonly string[]).includes(value);\n}\n\nexport interface SkillFrontmatter {\n\tname?: string;\n\tdescription?: string;\n\t\"disable-model-invocation\"?: boolean;\n\t/** Optional thinking-level hint (R1 follow-up); see Skill.thinking. */\n\tthinking?: string;\n\t/** Reflection-generated skill marker used by the curator. */\n\tpromoted?: boolean;\n\t[key: string]: unknown;\n}\n\nexport interface Skill {\n\tname: string;\n\tdescription: string;\n\tfilePath: string;\n\tbaseDir: string;\n\tsourceInfo: SourceInfo;\n\tdisableModelInvocation: boolean;\n\tpromoted?: boolean;\n\t/**\n\t * Optional thinking-level hint parsed from frontmatter (R1 follow-up: skill-surfaced thinking\n\t * governance, alongside resource-profile thinking). Core only parses and surfaces this value —\n\t * nothing in pi-adaptative core applies it to a session's thinking level yet. Unlike an active\n\t * resource profile (a persistent \"situation\", see settings-manager.ts's activeResourceProfile)\n\t * or a routed turn (bracketed by a try/finally swap/restore, see agent-session.ts's\n\t * _runAgentPromptWithModelRouter), a skill has no session-lifecycle hook marking when it starts\n\t * or stops governing a turn, so applying this is left to the consumer (e.g. a skill-router\n\t * extension) via the existing ctx.setThinkingLevel() extension API.\n\t */\n\tthinking?: ThinkingLevel;\n}\n\nexport interface LoadSkillsResult {\n\tskills: Skill[];\n\tdiagnostics: ResourceDiagnostic[];\n}\n\n/**\n * Validate skill name per Agent Skills spec.\n * Returns array of validation error messages (empty if valid).\n */\nexport function validateSkillName(name: string): string[] {\n\tconst errors: string[] = [];\n\n\tif (name.length > MAX_NAME_LENGTH) {\n\t\terrors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);\n\t}\n\n\tif (!/^[a-z0-9-]+$/.test(name)) {\n\t\terrors.push(`name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)`);\n\t}\n\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) {\n\t\terrors.push(`name must not start or end with a hyphen`);\n\t}\n\n\tif (name.includes(\"--\")) {\n\t\terrors.push(`name must not contain consecutive hyphens`);\n\t}\n\n\treturn errors;\n}\n\n/**\n * Validate description per Agent Skills spec.\n */\nfunction validateDescription(description: string | undefined): string[] {\n\tconst errors: string[] = [];\n\n\tif (!description || description.trim() === \"\") {\n\t\terrors.push(\"description is required\");\n\t} else if (description.length > MAX_DESCRIPTION_LENGTH) {\n\t\terrors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`);\n\t}\n\n\treturn errors;\n}\n\nexport interface LoadSkillsFromDirOptions {\n\t/** Directory to scan for skills */\n\tdir: string;\n\t/** Source identifier for these skills */\n\tsource: string;\n\t/** Profile UAC gate: when provided, files it denies are never read from disk. */\n\tisPathAllowed?: (path: string) => boolean;\n}\n\nfunction createSkillSourceInfo(filePath: string, baseDir: string, source: string): SourceInfo {\n\tswitch (source) {\n\t\tcase \"user\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tscope: \"user\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tcase \"project\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tscope: \"project\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tcase \"path\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tdefault:\n\t\t\treturn createSyntheticSourceInfo(filePath, { source, baseDir });\n\t}\n}\n\n/**\n * Read one stable, bounded frontmatter prefix. The closing delimiter ends the read, so discovery\n * cost depends on metadata size, never body size. Unterminated metadata fails at the explicit cap.\n */\nexport function readSkillFrontmatterFile(filePath: string): string {\n\tconst fileDescriptor = openSync(filePath, \"r\");\n\ttry {\n\t\tconst before = fstatSync(fileDescriptor);\n\t\tif (!before.isFile()) throw new Error(\"Skill is not a regular file.\");\n\t\tconst chunks: Buffer[] = [];\n\t\tlet totalBytes = 0;\n\t\twhile (totalBytes < MAX_SKILL_FRONTMATTER_BYTES) {\n\t\t\tconst chunk = Buffer.allocUnsafe(\n\t\t\t\tMath.min(SKILL_FRONTMATTER_READ_CHUNK_BYTES, MAX_SKILL_FRONTMATTER_BYTES - totalBytes),\n\t\t\t);\n\t\t\tconst bytesRead = readSync(fileDescriptor, chunk, 0, chunk.length, totalBytes);\n\t\t\tif (bytesRead > 0) {\n\t\t\t\tchunks.push(chunk.subarray(0, bytesRead));\n\t\t\t\ttotalBytes += bytesRead;\n\t\t\t}\n\t\t\tconst prefix = Buffer.concat(chunks, totalBytes).toString(\"utf8\").replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\t\t\tconst hasOpeningDelimiter = prefix.length >= 3 && prefix.startsWith(\"---\");\n\t\t\tconst closingDelimiter = hasOpeningDelimiter ? prefix.indexOf(\"\\n---\", 3) : -1;\n\t\t\tif (!hasOpeningDelimiter || closingDelimiter !== -1 || bytesRead === 0) {\n\t\t\t\tconst after = fstatSync(fileDescriptor);\n\t\t\t\tif (!sameFileVersion(before, after)) throw new Error(\"Skill changed while metadata was being read.\");\n\t\t\t\treturn closingDelimiter === -1 ? prefix : prefix.slice(0, closingDelimiter + 4);\n\t\t\t}\n\t\t}\n\t\tthrow new Error(`Skill frontmatter exceeds ${MAX_SKILL_FRONTMATTER_BYTES} bytes or is unterminated.`);\n\t} finally {\n\t\tcloseSync(fileDescriptor);\n\t}\n}\n\n/**\n * Load skills from a directory.\n *\n * Discovery rules:\n * - if a directory contains SKILL.md, treat it as a skill root and do not recurse further\n * - otherwise, load direct .md children in the root\n * - recurse into subdirectories to find SKILL.md\n */\nexport function loadSkillsFromDir(options: LoadSkillsFromDirOptions): LoadSkillsResult {\n\tconst { dir, source } = options;\n\treturn loadSkillsFromDirInternal(dir, source, options.isPathAllowed);\n}\n\nfunction loadSkillsFromDirInternal(\n\tdir: string,\n\tsource: string,\n\tisPathAllowed?: (path: string) => boolean,\n): LoadSkillsResult {\n\tconst skills: Skill[] = [];\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\tfor (const filePath of discoverSkillFiles(dir, \"pi\")) {\n\t\t// Profile UAC: denied skill contents are never read from disk.\n\t\tif (isPathAllowed && !isPathAllowed(filePath)) continue;\n\t\tconst result = loadSkillFromFile(filePath, source);\n\t\tif (result.skill) skills.push(result.skill);\n\t\tdiagnostics.push(...result.diagnostics);\n\t}\n\n\treturn { skills, diagnostics };\n}\n\nfunction loadSkillFromFile(\n\tfilePath: string,\n\tsource: string,\n): { skill: Skill | null; diagnostics: ResourceDiagnostic[] } {\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\n\ttry {\n\t\tconst { frontmatter } = parseFrontmatter<SkillFrontmatter>(readSkillFrontmatterFile(filePath));\n\t\tconst skillDir = dirname(filePath);\n\t\tconst parentDirName = basename(skillDir);\n\n\t\t// Validate description\n\t\tconst descErrors = validateDescription(frontmatter.description);\n\t\tfor (const error of descErrors) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\t}\n\n\t\t// Use name from frontmatter, or fall back to parent directory name\n\t\tconst name = frontmatter.name || parentDirName;\n\n\t\t// Validate name\n\t\tconst nameErrors = validateSkillName(name);\n\t\tfor (const error of nameErrors) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\t}\n\n\t\t// Still load the skill even with warnings (unless description is completely missing)\n\t\tif (!frontmatter.description || frontmatter.description.trim() === \"\") {\n\t\t\treturn { skill: null, diagnostics };\n\t\t}\n\n\t\treturn {\n\t\t\tskill: {\n\t\t\t\tname,\n\t\t\t\tdescription: frontmatter.description,\n\t\t\t\tfilePath,\n\t\t\t\tbaseDir: skillDir,\n\t\t\t\tsourceInfo: createSkillSourceInfo(filePath, skillDir, source),\n\t\t\t\tdisableModelInvocation: frontmatter[\"disable-model-invocation\"] === true,\n\t\t\t\tpromoted: frontmatter.promoted === true,\n\t\t\t\tthinking: isSkillThinkingLevel(frontmatter.thinking) ? frontmatter.thinking : undefined,\n\t\t\t},\n\t\t\tdiagnostics,\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"failed to parse skill file\";\n\t\tdiagnostics.push({ type: \"warning\", message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n}\n\nexport interface LoadSkillsOptions {\n\t/** Working directory for project-local skills. */\n\tcwd: string;\n\t/** Agent config directory for global skills. */\n\tagentDir: string;\n\t/** Explicit skill paths (files or directories) */\n\tskillPaths: string[];\n\t/** Include default skills directories. */\n\tincludeDefaults: boolean;\n\t/** Profile UAC gate: when provided, files it denies are never read from disk. */\n\tisPathAllowed?: (path: string) => boolean;\n}\n\n/**\n * Load skills from all configured locations.\n * Returns skills and any validation diagnostics.\n */\nexport function loadSkills(options: LoadSkillsOptions): LoadSkillsResult {\n\tconst { agentDir, skillPaths, includeDefaults } = options;\n\n\t// Resolve agentDir - if not provided, use default from config\n\tconst resolvedCwd = resolvePath(options.cwd);\n\tconst resolvedAgentDir = resolvePath(agentDir ?? getAgentDir());\n\n\tconst skillMap = new Map<string, Skill>();\n\tconst realPathSet = new Set<string>();\n\tconst allDiagnostics: ResourceDiagnostic[] = [];\n\tconst collisionDiagnostics: ResourceDiagnostic[] = [];\n\n\tfunction addSkills(result: LoadSkillsResult) {\n\t\tallDiagnostics.push(...result.diagnostics);\n\t\tfor (const skill of result.skills) {\n\t\t\t// Resolve symlinks to detect duplicate files\n\t\t\tconst realPath = canonicalizePath(skill.filePath);\n\n\t\t\t// Skip silently if we've already loaded this exact file (via symlink)\n\t\t\tif (realPathSet.has(realPath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst existing = skillMap.get(skill.name);\n\t\t\tif (existing) {\n\t\t\t\tcollisionDiagnostics.push({\n\t\t\t\t\ttype: \"collision\",\n\t\t\t\t\tmessage: `name \"${skill.name}\" collision`,\n\t\t\t\t\tpath: skill.filePath,\n\t\t\t\t\tcollision: {\n\t\t\t\t\t\tresourceType: \"skill\",\n\t\t\t\t\t\tname: skill.name,\n\t\t\t\t\t\twinnerPath: existing.filePath,\n\t\t\t\t\t\tloserPath: skill.filePath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tskillMap.set(skill.name, skill);\n\t\t\t\trealPathSet.add(realPath);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (includeDefaults) {\n\t\taddSkills(loadSkillsFromDirInternal(join(resolvedAgentDir, \"skills\"), \"user\", options.isPathAllowed));\n\t\taddSkills(\n\t\t\tloadSkillsFromDirInternal(resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\"), \"project\", options.isPathAllowed),\n\t\t);\n\t}\n\n\tconst userSkillsDir = join(resolvedAgentDir, \"skills\");\n\tconst projectSkillsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\");\n\n\tconst getSource = (resolvedPath: string): \"user\" | \"project\" | \"path\" => {\n\t\tif (!includeDefaults) {\n\t\t\tif (isResourcePathWithin(resolvedPath, userSkillsDir)) return \"user\";\n\t\t\tif (isResourcePathWithin(resolvedPath, projectSkillsDir)) return \"project\";\n\t\t}\n\t\treturn \"path\";\n\t};\n\n\tfor (const rawPath of skillPaths) {\n\t\tconst resolvedPath = resolvePath(rawPath, resolvedCwd, { trim: true });\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path does not exist\", path: resolvedPath });\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stats = statSync(resolvedPath);\n\t\t\tconst source = getSource(resolvedPath);\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\taddSkills(loadSkillsFromDirInternal(resolvedPath, source, options.isPathAllowed));\n\t\t\t} else if (stats.isFile() && resolvedPath.endsWith(\".md\")) {\n\t\t\t\t// Profile UAC: a denied skill file is never read from disk.\n\t\t\t\tif (options.isPathAllowed && !options.isPathAllowed(resolvedPath)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst result = loadSkillFromFile(resolvedPath, source);\n\t\t\t\tif (result.skill) {\n\t\t\t\t\taddSkills({ skills: [result.skill], diagnostics: result.diagnostics });\n\t\t\t\t} else {\n\t\t\t\t\tallDiagnostics.push(...result.diagnostics);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path is not a markdown file\", path: resolvedPath });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : \"failed to read skill path\";\n\t\t\tallDiagnostics.push({ type: \"warning\", message, path: resolvedPath });\n\t\t}\n\t}\n\n\treturn {\n\t\tskills: Array.from(skillMap.values()),\n\t\tdiagnostics: [...allDiagnostics, ...collisionDiagnostics],\n\t};\n}\n"]}
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@caupulican/pi-agent-core\";\nimport { closeSync, existsSync, fstatSync, openSync, readSync, statSync } from \"fs\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { parseFrontmatter } from \"../utils/frontmatter.ts\";\nimport { canonicalizePath, resolvePath } from \"../utils/paths.ts\";\nimport type { ResourceDiagnostic } from \"./diagnostics.ts\";\nimport { isResourcePathWithin } from \"./resource-traversal.ts\";\nimport { discoverSkillFiles } from \"./skill-discovery.ts\";\nimport { createSyntheticSourceInfo, type SourceInfo } from \"./source-info.ts\";\nimport { sameFileVersion } from \"./util/bounded-file.ts\";\n\n/** Discovery retains only this bounded metadata prefix, never the whole skill body. */\nexport const MAX_SKILL_FRONTMATTER_BYTES = 16 * 1024;\nconst SKILL_FRONTMATTER_READ_CHUNK_BYTES = 1024;\n\nexport const MAX_SKILL_NAME_LENGTH = 64;\n\n/** Max description length per spec */\nexport const MAX_SKILL_DESCRIPTION_LENGTH = 1024;\n\n// Kept local rather than imported from settings-manager.ts's ThinkingLevel validation: that module\n// already imports validateSkillName FROM this file, so importing back would cycle. The literal set\n// is small and stable (mirrors settings-manager.ts's own VALID_THINKING_LEVELS).\nconst VALID_SKILL_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\", \"ultra\"] as const;\nfunction isSkillThinkingLevel(value: unknown): value is ThinkingLevel {\n\treturn typeof value === \"string\" && (VALID_SKILL_THINKING_LEVELS as readonly string[]).includes(value);\n}\n\nexport interface SkillFrontmatter {\n\tname?: string;\n\tdescription?: string;\n\t\"disable-model-invocation\"?: boolean;\n\t/** Optional thinking-level hint (R1 follow-up); see Skill.thinking. */\n\tthinking?: string;\n\t/** Reflection-generated skill marker used by the curator. */\n\tpromoted?: boolean;\n\t[key: string]: unknown;\n}\n\nexport interface Skill {\n\tname: string;\n\tdescription: string;\n\tfilePath: string;\n\tbaseDir: string;\n\tsourceInfo: SourceInfo;\n\tdisableModelInvocation: boolean;\n\tpromoted?: boolean;\n\t/**\n\t * Optional thinking-level hint parsed from frontmatter (R1 follow-up: skill-surfaced thinking\n\t * governance, alongside resource-profile thinking). Core only parses and surfaces this value —\n\t * nothing in pi-adaptative core applies it to a session's thinking level yet. Unlike an active\n\t * resource profile (a persistent \"situation\", see settings-manager.ts's activeResourceProfile)\n\t * or a routed turn (bracketed by a try/finally swap/restore, see agent-session.ts's\n\t * _runAgentPromptWithModelRouter), a skill has no session-lifecycle hook marking when it starts\n\t * or stops governing a turn, so applying this is left to the consumer (e.g. a skill-router\n\t * extension) via the existing ctx.setThinkingLevel() extension API.\n\t */\n\tthinking?: ThinkingLevel;\n}\n\nexport interface LoadSkillsResult {\n\tskills: Skill[];\n\tdiagnostics: ResourceDiagnostic[];\n}\n\n/**\n * Validate skill name per Agent Skills spec.\n * Returns array of validation error messages (empty if valid).\n */\nexport function validateSkillName(name: string): string[] {\n\tconst errors: string[] = [];\n\n\tif (name.length > MAX_SKILL_NAME_LENGTH) {\n\t\terrors.push(`name exceeds ${MAX_SKILL_NAME_LENGTH} characters (${name.length})`);\n\t}\n\n\tif (!/^[a-z0-9-]+$/.test(name)) {\n\t\terrors.push(`name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)`);\n\t}\n\n\tif (name.startsWith(\"-\") || name.endsWith(\"-\")) {\n\t\terrors.push(`name must not start or end with a hyphen`);\n\t}\n\n\tif (name.includes(\"--\")) {\n\t\terrors.push(`name must not contain consecutive hyphens`);\n\t}\n\n\treturn errors;\n}\n\n/**\n * Validate description per Agent Skills spec.\n */\nfunction validateDescription(description: string | undefined): string[] {\n\tconst errors: string[] = [];\n\n\tif (!description || description.trim() === \"\") {\n\t\terrors.push(\"description is required\");\n\t} else if (description.length > MAX_SKILL_DESCRIPTION_LENGTH) {\n\t\terrors.push(`description exceeds ${MAX_SKILL_DESCRIPTION_LENGTH} characters (${description.length})`);\n\t}\n\n\treturn errors;\n}\n\nexport interface LoadSkillsFromDirOptions {\n\t/** Directory to scan for skills */\n\tdir: string;\n\t/** Source identifier for these skills */\n\tsource: string;\n\t/** Profile UAC gate: when provided, files it denies are never read from disk. */\n\tisPathAllowed?: (path: string) => boolean;\n}\n\nfunction createSkillSourceInfo(filePath: string, baseDir: string, source: string): SourceInfo {\n\tswitch (source) {\n\t\tcase \"user\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tscope: \"user\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tcase \"project\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tscope: \"project\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tcase \"path\":\n\t\t\treturn createSyntheticSourceInfo(filePath, {\n\t\t\t\tsource: \"local\",\n\t\t\t\tbaseDir,\n\t\t\t});\n\t\tdefault:\n\t\t\treturn createSyntheticSourceInfo(filePath, { source, baseDir });\n\t}\n}\n\n/**\n * Read one stable, bounded frontmatter prefix. The closing delimiter ends the read, so discovery\n * cost depends on metadata size, never body size. Unterminated metadata fails at the explicit cap.\n */\nexport function readSkillFrontmatterFile(filePath: string): string {\n\tconst fileDescriptor = openSync(filePath, \"r\");\n\ttry {\n\t\tconst before = fstatSync(fileDescriptor);\n\t\tif (!before.isFile()) throw new Error(\"Skill is not a regular file.\");\n\t\tconst chunks: Buffer[] = [];\n\t\tlet totalBytes = 0;\n\t\twhile (totalBytes < MAX_SKILL_FRONTMATTER_BYTES) {\n\t\t\tconst chunk = Buffer.allocUnsafe(\n\t\t\t\tMath.min(SKILL_FRONTMATTER_READ_CHUNK_BYTES, MAX_SKILL_FRONTMATTER_BYTES - totalBytes),\n\t\t\t);\n\t\t\tconst bytesRead = readSync(fileDescriptor, chunk, 0, chunk.length, totalBytes);\n\t\t\tif (bytesRead > 0) {\n\t\t\t\tchunks.push(chunk.subarray(0, bytesRead));\n\t\t\t\ttotalBytes += bytesRead;\n\t\t\t}\n\t\t\tconst prefix = Buffer.concat(chunks, totalBytes).toString(\"utf8\").replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\t\t\tconst hasOpeningDelimiter = prefix.length >= 3 && prefix.startsWith(\"---\");\n\t\t\tconst closingDelimiter = hasOpeningDelimiter ? prefix.indexOf(\"\\n---\", 3) : -1;\n\t\t\tif (!hasOpeningDelimiter || closingDelimiter !== -1 || bytesRead === 0) {\n\t\t\t\tconst after = fstatSync(fileDescriptor);\n\t\t\t\tif (!sameFileVersion(before, after)) throw new Error(\"Skill changed while metadata was being read.\");\n\t\t\t\treturn closingDelimiter === -1 ? prefix : prefix.slice(0, closingDelimiter + 4);\n\t\t\t}\n\t\t}\n\t\tthrow new Error(`Skill frontmatter exceeds ${MAX_SKILL_FRONTMATTER_BYTES} bytes or is unterminated.`);\n\t} finally {\n\t\tcloseSync(fileDescriptor);\n\t}\n}\n\n/**\n * Load skills from a directory.\n *\n * Discovery rules:\n * - if a directory contains SKILL.md, treat it as a skill root and do not recurse further\n * - otherwise, load direct .md children in the root\n * - recurse into subdirectories to find SKILL.md\n */\nexport function loadSkillsFromDir(options: LoadSkillsFromDirOptions): LoadSkillsResult {\n\tconst { dir, source } = options;\n\treturn loadSkillsFromDirInternal(dir, source, options.isPathAllowed);\n}\n\nfunction loadSkillsFromDirInternal(\n\tdir: string,\n\tsource: string,\n\tisPathAllowed?: (path: string) => boolean,\n): LoadSkillsResult {\n\tconst skills: Skill[] = [];\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\tfor (const filePath of discoverSkillFiles(dir, \"pi\")) {\n\t\t// Profile UAC: denied skill contents are never read from disk.\n\t\tif (isPathAllowed && !isPathAllowed(filePath)) continue;\n\t\tconst result = loadSkillFromFile(filePath, source);\n\t\tif (result.skill) skills.push(result.skill);\n\t\tdiagnostics.push(...result.diagnostics);\n\t}\n\n\treturn { skills, diagnostics };\n}\n\nfunction loadSkillFromFile(\n\tfilePath: string,\n\tsource: string,\n): { skill: Skill | null; diagnostics: ResourceDiagnostic[] } {\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\n\ttry {\n\t\tconst { frontmatter } = parseFrontmatter<SkillFrontmatter>(readSkillFrontmatterFile(filePath));\n\t\tconst skillDir = dirname(filePath);\n\t\tconst parentDirName = basename(skillDir);\n\n\t\t// Validate description\n\t\tconst descErrors = validateDescription(frontmatter.description);\n\t\tfor (const error of descErrors) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\t}\n\n\t\t// Use name from frontmatter, or fall back to parent directory name\n\t\tconst name = frontmatter.name || parentDirName;\n\n\t\t// Validate name\n\t\tconst nameErrors = validateSkillName(name);\n\t\tfor (const error of nameErrors) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: error, path: filePath });\n\t\t}\n\n\t\t// Still load the skill even with warnings (unless description is completely missing)\n\t\tif (!frontmatter.description || frontmatter.description.trim() === \"\") {\n\t\t\treturn { skill: null, diagnostics };\n\t\t}\n\n\t\treturn {\n\t\t\tskill: {\n\t\t\t\tname,\n\t\t\t\tdescription: frontmatter.description,\n\t\t\t\tfilePath,\n\t\t\t\tbaseDir: skillDir,\n\t\t\t\tsourceInfo: createSkillSourceInfo(filePath, skillDir, source),\n\t\t\t\tdisableModelInvocation: frontmatter[\"disable-model-invocation\"] === true,\n\t\t\t\tpromoted: frontmatter.promoted === true,\n\t\t\t\tthinking: isSkillThinkingLevel(frontmatter.thinking) ? frontmatter.thinking : undefined,\n\t\t\t},\n\t\t\tdiagnostics,\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"failed to parse skill file\";\n\t\tdiagnostics.push({ type: \"warning\", message, path: filePath });\n\t\treturn { skill: null, diagnostics };\n\t}\n}\n\nexport interface LoadSkillsOptions {\n\t/** Working directory for project-local skills. */\n\tcwd: string;\n\t/** Agent config directory for global skills. */\n\tagentDir: string;\n\t/** Explicit skill paths (files or directories) */\n\tskillPaths: string[];\n\t/** Include default skills directories. */\n\tincludeDefaults: boolean;\n\t/** Profile UAC gate: when provided, files it denies are never read from disk. */\n\tisPathAllowed?: (path: string) => boolean;\n}\n\n/**\n * Load skills from all configured locations.\n * Returns skills and any validation diagnostics.\n */\nexport function loadSkills(options: LoadSkillsOptions): LoadSkillsResult {\n\tconst { agentDir, skillPaths, includeDefaults } = options;\n\n\t// Resolve agentDir - if not provided, use default from config\n\tconst resolvedCwd = resolvePath(options.cwd);\n\tconst resolvedAgentDir = resolvePath(agentDir ?? getAgentDir());\n\n\tconst skillMap = new Map<string, Skill>();\n\tconst realPathSet = new Set<string>();\n\tconst allDiagnostics: ResourceDiagnostic[] = [];\n\tconst collisionDiagnostics: ResourceDiagnostic[] = [];\n\n\tfunction addSkills(result: LoadSkillsResult) {\n\t\tallDiagnostics.push(...result.diagnostics);\n\t\tfor (const skill of result.skills) {\n\t\t\t// Resolve symlinks to detect duplicate files\n\t\t\tconst realPath = canonicalizePath(skill.filePath);\n\n\t\t\t// Skip silently if we've already loaded this exact file (via symlink)\n\t\t\tif (realPathSet.has(realPath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst existing = skillMap.get(skill.name);\n\t\t\tif (existing) {\n\t\t\t\tcollisionDiagnostics.push({\n\t\t\t\t\ttype: \"collision\",\n\t\t\t\t\tmessage: `name \"${skill.name}\" collision`,\n\t\t\t\t\tpath: skill.filePath,\n\t\t\t\t\tcollision: {\n\t\t\t\t\t\tresourceType: \"skill\",\n\t\t\t\t\t\tname: skill.name,\n\t\t\t\t\t\twinnerPath: existing.filePath,\n\t\t\t\t\t\tloserPath: skill.filePath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tskillMap.set(skill.name, skill);\n\t\t\t\trealPathSet.add(realPath);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (includeDefaults) {\n\t\taddSkills(loadSkillsFromDirInternal(join(resolvedAgentDir, \"skills\"), \"user\", options.isPathAllowed));\n\t\taddSkills(\n\t\t\tloadSkillsFromDirInternal(resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\"), \"project\", options.isPathAllowed),\n\t\t);\n\t}\n\n\tconst userSkillsDir = join(resolvedAgentDir, \"skills\");\n\tconst projectSkillsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, \"skills\");\n\n\tconst getSource = (resolvedPath: string): \"user\" | \"project\" | \"path\" => {\n\t\tif (!includeDefaults) {\n\t\t\tif (isResourcePathWithin(resolvedPath, userSkillsDir)) return \"user\";\n\t\t\tif (isResourcePathWithin(resolvedPath, projectSkillsDir)) return \"project\";\n\t\t}\n\t\treturn \"path\";\n\t};\n\n\tfor (const rawPath of skillPaths) {\n\t\tconst resolvedPath = resolvePath(rawPath, resolvedCwd, { trim: true });\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path does not exist\", path: resolvedPath });\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stats = statSync(resolvedPath);\n\t\t\tconst source = getSource(resolvedPath);\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\taddSkills(loadSkillsFromDirInternal(resolvedPath, source, options.isPathAllowed));\n\t\t\t} else if (stats.isFile() && resolvedPath.endsWith(\".md\")) {\n\t\t\t\t// Profile UAC: a denied skill file is never read from disk.\n\t\t\t\tif (options.isPathAllowed && !options.isPathAllowed(resolvedPath)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst result = loadSkillFromFile(resolvedPath, source);\n\t\t\t\tif (result.skill) {\n\t\t\t\t\taddSkills({ skills: [result.skill], diagnostics: result.diagnostics });\n\t\t\t\t} else {\n\t\t\t\t\tallDiagnostics.push(...result.diagnostics);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tallDiagnostics.push({ type: \"warning\", message: \"skill path is not a markdown file\", path: resolvedPath });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : \"failed to read skill path\";\n\t\t\tallDiagnostics.push({ type: \"warning\", message, path: resolvedPath });\n\t\t}\n\t}\n\n\treturn {\n\t\tskills: Array.from(skillMap.values()),\n\t\tdiagnostics: [...allDiagnostics, ...collisionDiagnostics],\n\t};\n}\n"]}
@@ -49,6 +49,8 @@ export interface SystemPromptBuilderDeps {
49
49
  getActiveExtensions(): ReadonlyArray<Extension>;
50
50
  /** The authoritative profile used by tools, lanes, and stable prompt shaping. */
51
51
  getModelCapabilityProfile(): ModelCapabilityProfile;
52
+ /** Child/worker sessions never receive root autonomy or reflection instructions. */
53
+ isChildSession(): boolean;
52
54
  }
53
55
  export declare function collectSelfModificationSourceCandidates(settings: {
54
56
  sourcePath?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt-builder.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAA4C,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC9G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,KAAK,wBAAwB,EAAqB,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEjG,MAAM,WAAW,uBAAuB;IACvC,kGAAkG;IAClG,MAAM,IAAI,MAAM,CAAC;IACjB,mGAAmG;IACnG,kBAAkB,IAAI,eAAe,CAAC;IACtC,qFAAqF;IACrF,iBAAiB,IAAI,cAAc,CAAC;IACpC,gGAAgG;IAChG,gBAAgB,IAAI,aAAa,CAAC;IAClC,kEAAkE;IAClE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,iEAAiE;IACjE,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACvD,iEAAiE;IACjE,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5D,6EAA6E;IAC7E,uBAAuB,IAAI,SAAS,mBAAmB,EAAE,CAAC;IAC1D;;;;;;;OAOG;IACH,qBAAqB,CAAC,IAAI,SAAS,iBAAiB,EAAE,CAAC;IACvD,iDAAiD;IACjD,mBAAmB,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;IAChD,iFAAiF;IACjF,yBAAyB,IAAI,sBAAsB,CAAC;CACpD;AAED,wBAAgB,uCAAuC,CAAC,QAAQ,EAAE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,GAAG,MAAM,EAAE,CAWX;AAED,qBAAa,mBAAmB;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,wBAAwB,CAA4B;IAE5D,YAAY,IAAI,EAAE,uBAAuB,EAExC;IAED,qGAAqG;IACrG,0BAA0B,IAAI,wBAAwB,CAErD;IAED,kGAAkG;IAClG,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEtD;IAED,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAEnE;IAED,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAEpE;IAED;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAMjC,OAAO,CAAC,4BAA4B;IAoCpC,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,2BAA2B;IAOnC,8FAA8F;IAC9F,OAAO,CAAC,6BAA6B;IAIrC,OAAO,CAAC,6BAA6B;IAwBrC,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,qCAAqC;IAsD7C,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAG/C;IAED;;;;;;OAMG;IACH,6BAA6B,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAEzD;CACD"}
1
+ {"version":3,"file":"system-prompt-builder.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAGN,KAAK,sBAAsB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,KAAK,wBAAwB,EAAqB,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEjG,MAAM,WAAW,uBAAuB;IACvC,kGAAkG;IAClG,MAAM,IAAI,MAAM,CAAC;IACjB,mGAAmG;IACnG,kBAAkB,IAAI,eAAe,CAAC;IACtC,qFAAqF;IACrF,iBAAiB,IAAI,cAAc,CAAC;IACpC,gGAAgG;IAChG,gBAAgB,IAAI,aAAa,CAAC;IAClC,kEAAkE;IAClE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,iEAAiE;IACjE,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACvD,iEAAiE;IACjE,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5D,6EAA6E;IAC7E,uBAAuB,IAAI,SAAS,mBAAmB,EAAE,CAAC;IAC1D;;;;;;;OAOG;IACH,qBAAqB,CAAC,IAAI,SAAS,iBAAiB,EAAE,CAAC;IACvD,iDAAiD;IACjD,mBAAmB,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;IAChD,iFAAiF;IACjF,yBAAyB,IAAI,sBAAsB,CAAC;IACpD,oFAAoF;IACpF,cAAc,IAAI,OAAO,CAAC;CAC1B;AAED,wBAAgB,uCAAuC,CAAC,QAAQ,EAAE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,GAAG,MAAM,EAAE,CAWX;AAqCD,qBAAa,mBAAmB;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,wBAAwB,CAA4B;IAE5D,YAAY,IAAI,EAAE,uBAAuB,EAExC;IAED,qGAAqG;IACrG,0BAA0B,IAAI,wBAAwB,CAErD;IAED,kGAAkG;IAClG,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEtD;IAED,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAEnE;IAED,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAEpE;IAED;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAMjC,OAAO,CAAC,4BAA4B;IAoCpC,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,2BAA2B;IAOnC,8FAA8F;IAC9F,OAAO,CAAC,6BAA6B;IAIrC,OAAO,CAAC,6BAA6B;IAwBrC,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,qCAAqC;IA0D7C,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAG/C;IAED;;;;;;OAMG;IACH,6BAA6B,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAEzD;CACD"}