@selesai/code 0.13.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/core/agent-session.d.ts +1 -1
  3. package/dist/core/agent-session.js +1 -1
  4. package/dist/core/sdk.d.ts +2 -2
  5. package/dist/core/sdk.js +1 -1
  6. package/dist/core/system-prompt.d.ts +1 -1
  7. package/dist/core/system-prompt.js +1 -1
  8. package/dist/extensions/package.json +1 -2
  9. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
  10. package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
  11. package/dist/extensions/pi-hermes-memory/README.md +643 -0
  12. package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
  13. package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
  14. package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
  15. package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
  16. package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
  17. package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
  18. package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
  19. package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
  20. package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
  21. package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
  22. package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
  23. package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
  24. package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
  25. package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
  26. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
  27. package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
  28. package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
  29. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
  30. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
  31. package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
  32. package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
  33. package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
  34. package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
  35. package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
  36. package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
  37. package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
  38. package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
  39. package/dist/extensions/pi-hermes-memory/package.json +66 -0
  40. package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
  41. package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
  42. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
  43. package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
  44. package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
  45. package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
  46. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
  47. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
  48. package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
  49. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
  50. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
  51. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
  52. package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
  53. package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
  54. package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
  55. package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
  56. package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
  57. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
  58. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
  59. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
  60. package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
  61. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
  62. package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
  63. package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
  64. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
  65. package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
  66. package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
  67. package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
  68. package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
  69. package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
  70. package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
  71. package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
  72. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
  73. package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
  74. package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
  75. package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
  76. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
  77. package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
  78. package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
  79. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
  80. package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
  82. package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
  83. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
  84. package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
  85. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
  86. package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
  87. package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
  88. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
  89. package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
  90. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
  91. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
  92. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
  93. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
  94. package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
  95. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
  96. package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
  97. package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
  98. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
  99. package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
  100. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
  101. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
  102. package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
  103. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
  104. package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
  105. package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
  106. package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
  107. package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
  108. package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
  109. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
  110. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
  111. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
  112. package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
  113. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
  114. package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
  115. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
  116. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
  117. package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
  118. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
  119. package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
  120. package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
  121. package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
  122. package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
  123. package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
  124. package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
  125. package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
  126. package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
  127. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
  128. package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
  129. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
  130. package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
  131. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
  132. package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
  133. package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
  134. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
  135. package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
  136. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
  137. package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
  138. package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
  139. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
  140. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
  141. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
  142. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
  143. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
  144. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
  145. package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
  146. package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
  147. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
  148. package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
  149. package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
  150. package/dist/extensions/pi-rewind-hook/README.md +4 -1
  151. package/dist/extensions/pi-rewind-hook/index.ts +151 -21
  152. package/dist/extensions/pi-rewind-hook/package.json +5 -3
  153. package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
  154. package/dist/extensions/pi-subagents/AGENTS.md +5 -0
  155. package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
  156. package/dist/extensions/pi-subagents/README.md +12 -6
  157. package/dist/extensions/pi-subagents/VISION.md +81 -0
  158. package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
  159. package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
  160. package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
  161. package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
  162. package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
  163. package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
  164. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
  165. package/dist/extensions/pi-subagents/docs/agents.md +488 -0
  166. package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
  167. package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
  168. package/dist/extensions/pi-subagents/docs/models.md +27 -4
  169. package/dist/extensions/pi-subagents/docs/observability.md +10 -9
  170. package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
  171. package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
  172. package/dist/extensions/pi-subagents/package-lock.json +389 -2
  173. package/dist/extensions/pi-subagents/package.json +3 -1
  174. package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
  175. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
  176. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
  177. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
  178. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  179. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
  180. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
  181. package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
  182. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
  183. package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
  184. package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
  185. package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
  186. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
  187. package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
  188. package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
  189. package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
  190. package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
  191. package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
  192. package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
  193. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
  194. package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
  195. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
  196. package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
  197. package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
  198. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
  199. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
  200. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
  201. package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
  202. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -7
  203. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
  204. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
  205. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
  206. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
  207. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
  208. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
  209. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
  210. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
  211. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
  212. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
  213. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
  214. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
  215. package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
  216. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
  217. package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
  218. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
  219. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
  220. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
  221. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
  222. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
  223. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
  224. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
  225. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
  226. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
  227. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
  228. package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
  229. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
  230. package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
  231. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
  232. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
  233. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
  234. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
  235. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
  236. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
  237. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
  238. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
  239. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
  240. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
  241. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
  242. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
  243. package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
  244. package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
  245. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
  246. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
  247. package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
  248. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
  249. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
  250. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
  251. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
  252. package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
  253. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
  254. package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
  255. package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
  256. package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
  257. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
  258. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
  259. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
  260. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
  261. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
  262. package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
  263. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
  264. package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
  265. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
  266. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
  267. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
  268. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
  269. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
  270. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
  271. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
  272. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
  273. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
  274. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
  275. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
  276. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
  277. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
  278. package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
  279. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
  280. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
  281. package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
  282. package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
  283. package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
  284. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
  285. package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
  286. package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
  287. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
  288. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
  289. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
  290. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
  291. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
  292. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
  293. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
  294. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
  295. package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
  296. package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
  297. package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
  298. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
  299. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
  300. package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
  301. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
  302. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
  303. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
  304. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
  305. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
  306. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  307. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
  308. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
  309. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
  310. package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
  311. package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
  312. package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
  313. package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
  314. package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
  315. package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
  316. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
  317. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
  318. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
  319. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
  320. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
  321. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
  322. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
  323. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
  324. package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
  325. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
  326. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
  327. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
  328. package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
  329. package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
  330. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
  331. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
  332. package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
  333. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
  334. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
  335. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
  336. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
  337. package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
  338. package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
  339. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
  340. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
  341. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
  342. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
  343. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
  344. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
  345. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
  346. package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
  347. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
  348. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
  349. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
  350. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
  351. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
  352. package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
  353. package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
  354. package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
  355. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
  356. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
  357. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
  358. package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
  359. package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
  360. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
  361. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
  362. package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
  363. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
  364. package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
  365. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
  366. package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
  367. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
  368. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
  369. package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
  370. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
  371. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
  372. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
  373. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +136 -6
  374. package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
  375. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
  376. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
  377. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
  378. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
  379. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
  380. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
  381. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
  382. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
  383. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
  384. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
  385. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
  386. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
  387. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
  388. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
  389. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
  390. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
  391. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
  392. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
  393. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
  394. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
  395. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
  396. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
  397. package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
  398. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
  399. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
  400. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
  401. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
  402. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
  403. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
  404. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
  405. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
  406. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
  407. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
  408. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  409. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
  410. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
  411. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
  412. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
  413. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
  414. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
  415. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
  416. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
  417. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
  418. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
  419. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
  420. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
  421. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
  422. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
  423. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
  424. package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
  425. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
  426. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
  427. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
  428. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
  429. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
  430. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
  431. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
  432. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
  433. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
  434. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
  435. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
  436. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
  437. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
  438. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
  439. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
  440. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
  441. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
  442. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
  443. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
  444. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
  445. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
  446. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
  447. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
  448. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
  449. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
  450. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
  451. package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
  452. package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
  453. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
  454. package/dist/modes/interactive/interactive-mode.js +7 -7
  455. package/dist/skills/workflow/SKILL.md +65 -50
  456. package/package.json +112 -110
  457. package/dist/extensions/enable-readonly-tools.test.ts +0 -63
  458. package/dist/extensions/enable-readonly-tools.ts +0 -24
  459. package/dist/extensions/model-prompt-injector/config.json +0 -16
  460. package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
  461. package/dist/extensions/model-prompt-injector/index.ts +0 -148
  462. package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
  463. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
@@ -0,0 +1,478 @@
1
+ /**
2
+ * Unit tests for skill tool registration and execute function.
3
+ */
4
+
5
+ import { describe, it } from "node:test";
6
+ import * as assert from "node:assert/strict";
7
+ import { registerSkillTool, SKILL_MANAGE_TOOL_NAME } from "../../src/tools/skill-tool.js";
8
+ import { SkillStore } from "../../src/store/skill-store.js";
9
+ import * as path from "node:path";
10
+ import * as os from "node:os";
11
+ import * as fs from "node:fs/promises";
12
+
13
+ let ROOT_DIR = "";
14
+ let GLOBAL_SKILLS_DIR = "";
15
+ let PROJECT_SKILLS_DIR = "";
16
+
17
+ async function makeStore(withProject = true): Promise<SkillStore> {
18
+ ROOT_DIR = await fs.mkdtemp(path.join(os.tmpdir(), "pi-skill-tool-test-"));
19
+ GLOBAL_SKILLS_DIR = path.join(ROOT_DIR, "global-skills");
20
+ PROJECT_SKILLS_DIR = path.join(ROOT_DIR, "project-skills");
21
+ await fs.mkdir(GLOBAL_SKILLS_DIR, { recursive: true });
22
+ if (withProject) await fs.mkdir(PROJECT_SKILLS_DIR, { recursive: true });
23
+
24
+ return new SkillStore({
25
+ globalSkillsDir: GLOBAL_SKILLS_DIR,
26
+ projectSkillsDir: withProject ? PROJECT_SKILLS_DIR : null,
27
+ projectName: withProject ? "demo-project" : null,
28
+ legacySkillsDir: path.join(ROOT_DIR, "legacy-skills"),
29
+ migrationSentinelPath: path.join(ROOT_DIR, ".skill-migration"),
30
+ });
31
+ }
32
+
33
+ async function cleanup(): Promise<void> {
34
+ try {
35
+ await fs.rm(ROOT_DIR, { recursive: true, force: true });
36
+ } catch {
37
+ // ignore
38
+ }
39
+ }
40
+
41
+ describe("registerSkillTool", () => {
42
+ it("registers tool with name 'skill_manage'", async () => {
43
+ let captured: any;
44
+ const mockPi = {
45
+ registerTool: (def: any) => { captured = def; },
46
+ } as any;
47
+
48
+ const store = await makeStore();
49
+ registerSkillTool(mockPi, store);
50
+ await cleanup();
51
+
52
+ assert.strictEqual(captured.name, SKILL_MANAGE_TOOL_NAME);
53
+ assert.strictEqual(captured.label, "Skill Manager");
54
+ assert.ok(captured.description.length > 0);
55
+ assert.ok(captured.promptSnippet.length > 0);
56
+ assert.ok(Array.isArray(captured.promptGuidelines));
57
+ assert.ok(captured.parameters);
58
+ });
59
+
60
+ it("create requires name, description, a body or structured fields, and scope", async () => {
61
+ let captured: any;
62
+ const mockPi = {
63
+ registerTool: (def: any) => { captured = def; },
64
+ } as any;
65
+
66
+ const store = await makeStore();
67
+ registerSkillTool(mockPi, store);
68
+
69
+ let result = await captured.execute("tc-1", { action: "create", description: "desc", content: "body" }, undefined, undefined, undefined);
70
+ assert.strictEqual(JSON.parse(result.content[0].text).success, false);
71
+
72
+ result = await captured.execute("tc-1", { action: "create", name: "test", content: "body" }, undefined, undefined, undefined);
73
+ assert.strictEqual(JSON.parse(result.content[0].text).success, false);
74
+
75
+ result = await captured.execute("tc-1", { action: "create", name: "test", description: "desc" }, undefined, undefined, undefined);
76
+ const missingBody = JSON.parse(result.content[0].text);
77
+ assert.strictEqual(missingBody.success, false);
78
+ assert.match(missingBody.error, /Either content or structured fields are required/i);
79
+
80
+ result = await captured.execute("tc-1", {
81
+ action: "create",
82
+ name: "test",
83
+ description: "desc",
84
+ content: "body",
85
+ }, undefined, undefined, undefined);
86
+ const missingScope = JSON.parse(result.content[0].text);
87
+ assert.strictEqual(missingScope.success, false);
88
+ assert.match(missingScope.error, /scope is required/i);
89
+
90
+ await cleanup();
91
+ });
92
+
93
+ it("create succeeds with raw markdown content and returns skill_id", async () => {
94
+ let captured: any;
95
+ const mockPi = {
96
+ registerTool: (def: any) => { captured = def; },
97
+ } as any;
98
+
99
+ const store = await makeStore();
100
+ registerSkillTool(mockPi, store);
101
+
102
+ const result = await captured.execute("tc-1", {
103
+ action: "create",
104
+ name: "test-skill",
105
+ description: "A test skill",
106
+ scope: "global",
107
+ content: "## Procedure\n1. Do it",
108
+ }, undefined, undefined, undefined);
109
+
110
+ const parsed = JSON.parse(result.content[0].text);
111
+ assert.strictEqual(parsed.success, true);
112
+ assert.strictEqual(parsed.skillId, "global:test-skill");
113
+ assert.strictEqual(parsed.scope, "global");
114
+
115
+ await cleanup();
116
+ });
117
+
118
+ it("create builds a valid skill body from structured fields", async () => {
119
+ let captured: any;
120
+ const mockPi = {
121
+ registerTool: (def: any) => { captured = def; },
122
+ } as any;
123
+
124
+ const store = await makeStore();
125
+ registerSkillTool(mockPi, store);
126
+
127
+ const result = await captured.execute("tc-1", {
128
+ action: "create",
129
+ name: "debug-typescript-errors",
130
+ description: "Debug TypeScript build failures in this repo",
131
+ scope: "project",
132
+ when_to_use: "Use when the repo's TypeScript build fails locally or in CI.",
133
+ procedure_steps: [
134
+ "Run pnpm tsc --noEmit to get the full error list.",
135
+ "Fix dependency and config errors before leaf-module errors.",
136
+ ],
137
+ pitfalls: [
138
+ "Do not rely on editor-only diagnostics.",
139
+ ],
140
+ verification_steps: [
141
+ "pnpm tsc --noEmit exits successfully.",
142
+ ],
143
+ }, undefined, undefined, undefined);
144
+
145
+ const parsed = JSON.parse(result.content[0].text);
146
+ assert.strictEqual(parsed.success, true);
147
+
148
+ const created = await store.loadSkill(parsed.skillId);
149
+ assert.match(created?.body || "", /## When to Use/);
150
+ assert.match(created?.body || "", /## Procedure/);
151
+ assert.match(created?.body || "", /1\. Run pnpm tsc --noEmit/);
152
+ assert.match(created?.body || "", /## Pitfalls/);
153
+ assert.match(created?.body || "", /## Verification/);
154
+
155
+ await cleanup();
156
+ });
157
+
158
+ it("create supports explicit project scope", async () => {
159
+ let captured: any;
160
+ const mockPi = {
161
+ registerTool: (def: any) => { captured = def; },
162
+ } as any;
163
+
164
+ const store = await makeStore();
165
+ registerSkillTool(mockPi, store);
166
+
167
+ const result = await captured.execute("tc-1", {
168
+ action: "create",
169
+ name: "release-app",
170
+ description: "Release this app",
171
+ scope: "project",
172
+ content: "## Procedure\n1. Run pnpm build",
173
+ }, undefined, undefined, undefined);
174
+
175
+ const parsed = JSON.parse(result.content[0].text);
176
+ assert.strictEqual(parsed.success, true);
177
+ assert.strictEqual(parsed.skillId, "project:demo-project:release-app");
178
+ assert.strictEqual(parsed.scope, "project");
179
+
180
+ await cleanup();
181
+ });
182
+
183
+ it("view without skill_id lists all skills", async () => {
184
+ let captured: any;
185
+ const mockPi = {
186
+ registerTool: (def: any) => { captured = def; },
187
+ } as any;
188
+
189
+ const store = await makeStore();
190
+ await store.create("skill-a", "First", "body a");
191
+ await store.create("skill-b", "Second", "body b", "project");
192
+ registerSkillTool(mockPi, store);
193
+
194
+ const result = await captured.execute("tc-1", { action: "view" }, undefined, undefined, undefined);
195
+ const parsed = JSON.parse(result.content[0].text);
196
+ assert.strictEqual(parsed.success, true);
197
+ assert.strictEqual(parsed.skills.length, 2);
198
+
199
+ await cleanup();
200
+ });
201
+
202
+ it("view with skill_id returns full document", async () => {
203
+ let captured: any;
204
+ const mockPi = {
205
+ registerTool: (def: any) => { captured = def; },
206
+ } as any;
207
+
208
+ const store = await makeStore();
209
+ const created = await store.create("my-skill", "A skill", "## Body content here");
210
+ registerSkillTool(mockPi, store);
211
+
212
+ const result = await captured.execute("tc-1", { action: "view", skill_id: created.skillId }, undefined, undefined, undefined);
213
+ const parsed = JSON.parse(result.content[0].text);
214
+ assert.strictEqual(parsed.success, true);
215
+ assert.strictEqual(parsed.name, "my-skill");
216
+ assert.ok(parsed.body.includes("## Body content here"));
217
+
218
+ await cleanup();
219
+ });
220
+
221
+ it("view with invalid skill_id returns error", async () => {
222
+ let captured: any;
223
+ const mockPi = {
224
+ registerTool: (def: any) => { captured = def; },
225
+ } as any;
226
+
227
+ const store = await makeStore();
228
+ registerSkillTool(mockPi, store);
229
+
230
+ const result = await captured.execute("tc-1", { action: "view", skill_id: "global:missing" }, undefined, undefined, undefined);
231
+ const parsed = JSON.parse(result.content[0].text);
232
+ assert.strictEqual(parsed.success, false);
233
+ assert.ok(parsed.error.includes("not found"));
234
+
235
+ await cleanup();
236
+ });
237
+
238
+ it("patch requires skill_id, section, and content or structured fields", async () => {
239
+ let captured: any;
240
+ const mockPi = {
241
+ registerTool: (def: any) => { captured = def; },
242
+ } as any;
243
+
244
+ const store = await makeStore();
245
+ registerSkillTool(mockPi, store);
246
+
247
+ let result = await captured.execute("tc-1", { action: "patch", section: "Procedure", content: "new" }, undefined, undefined, undefined);
248
+ assert.strictEqual(JSON.parse(result.content[0].text).success, false);
249
+
250
+ result = await captured.execute("tc-1", { action: "patch", skill_id: "global:test", content: "new" }, undefined, undefined, undefined);
251
+ assert.strictEqual(JSON.parse(result.content[0].text).success, false);
252
+
253
+ result = await captured.execute("tc-1", { action: "patch", skill_id: "global:test", section: "Procedure" }, undefined, undefined, undefined);
254
+ assert.strictEqual(JSON.parse(result.content[0].text).success, false);
255
+
256
+ await cleanup();
257
+ });
258
+
259
+ it("patch accepts structured procedure_steps for a section update", async () => {
260
+ let captured: any;
261
+ const mockPi = {
262
+ registerTool: (def: any) => { captured = def; },
263
+ } as any;
264
+
265
+ const store = await makeStore();
266
+ const created = await store.create(
267
+ "patch-me",
268
+ "desc",
269
+ "## Procedure\n1. Old way\n\n## Pitfalls\n- Keep me\n\n## Verification\n1. Still works",
270
+ );
271
+ registerSkillTool(mockPi, store);
272
+
273
+ const result = await captured.execute("tc-1", {
274
+ action: "patch",
275
+ skill_id: created.skillId,
276
+ section: "Procedure",
277
+ procedure_steps: ["Do the new first step", "Do the new second step"],
278
+ }, undefined, undefined, undefined);
279
+
280
+ const parsed = JSON.parse(result.content[0].text);
281
+ assert.strictEqual(parsed.success, true);
282
+
283
+ const doc = await store.loadSkill(created.skillId!);
284
+ assert.match(doc!.body, /## Procedure\n1\. Do the new first step\n2\. Do the new second step/);
285
+ assert.match(doc!.body, /## Pitfalls\n- Keep me/);
286
+ assert.match(doc!.body, /## Verification\n1\. Still works/);
287
+ assert.doesNotMatch(doc!.body, /Old way/);
288
+
289
+ await cleanup();
290
+ });
291
+
292
+ it("patch rejects JSON object content strings", async () => {
293
+ let captured: any;
294
+ const mockPi = {
295
+ registerTool: (def: any) => { captured = def; },
296
+ } as any;
297
+
298
+ const store = await makeStore();
299
+ const created = await store.create("patch-me", "desc", "## Procedure\n1. Keep");
300
+ registerSkillTool(mockPi, store);
301
+
302
+ const result = await captured.execute("tc-1", {
303
+ action: "patch",
304
+ skill_id: created.skillId,
305
+ section: "Procedure",
306
+ content: '{"steps":["bad"]}',
307
+ }, undefined, undefined, undefined);
308
+
309
+ const parsed = JSON.parse(result.content[0].text);
310
+ assert.strictEqual(parsed.success, false);
311
+ assert.match(parsed.error, /JSON object/i);
312
+ assert.equal((await store.loadSkill(created.skillId!))!.version, 1);
313
+
314
+ await cleanup();
315
+ });
316
+
317
+ it("patch coerces JSON array content strings into Markdown lists", async () => {
318
+ let captured: any;
319
+ const mockPi = {
320
+ registerTool: (def: any) => { captured = def; },
321
+ } as any;
322
+
323
+ const store = await makeStore();
324
+ const created = await store.create("patch-me", "desc", "## Pitfalls\n- old");
325
+ registerSkillTool(mockPi, store);
326
+
327
+ const result = await captured.execute("tc-1", {
328
+ action: "patch",
329
+ skill_id: created.skillId,
330
+ section: "Pitfalls",
331
+ content: '["Do not skip verification", "Do not wipe other sections"]',
332
+ }, undefined, undefined, undefined);
333
+
334
+ const parsed = JSON.parse(result.content[0].text);
335
+ assert.strictEqual(parsed.success, true);
336
+
337
+ const doc = await store.loadSkill(created.skillId!);
338
+ assert.match(doc!.body, /## Pitfalls\n- Do not skip verification\n- Do not wipe other sections/);
339
+ assert.doesNotMatch(doc!.body, /\[\"Do not skip verification\"/);
340
+
341
+ await cleanup();
342
+ });
343
+
344
+ it("update requires skill_id", async () => {
345
+ let captured: any;
346
+ const mockPi = {
347
+ registerTool: (def: any) => { captured = def; },
348
+ } as any;
349
+
350
+ const store = await makeStore();
351
+ registerSkillTool(mockPi, store);
352
+
353
+ const result = await captured.execute("tc-1", { action: "update", description: "new desc" }, undefined, undefined, undefined);
354
+ const parsed = JSON.parse(result.content[0].text);
355
+ assert.strictEqual(parsed.success, false);
356
+ assert.ok(parsed.error.includes("skill_id"));
357
+
358
+ await cleanup();
359
+ });
360
+
361
+ it("update aliases to full skill rewrite", async () => {
362
+ let captured: any;
363
+ const mockPi = {
364
+ registerTool: (def: any) => { captured = def; },
365
+ } as any;
366
+
367
+ const store = await makeStore();
368
+ const created = await store.create("my-skill", "Old desc", "## Old body", "global");
369
+ registerSkillTool(mockPi, store);
370
+
371
+ const result = await captured.execute("tc-1", {
372
+ action: "update",
373
+ skill_id: created.skillId,
374
+ description: "New desc",
375
+ content: "## New body",
376
+ }, undefined, undefined, undefined);
377
+
378
+ const parsed = JSON.parse(result.content[0].text);
379
+ assert.strictEqual(parsed.success, true);
380
+
381
+ const updated = await store.loadSkill(created.skillId!);
382
+ assert.strictEqual(updated?.description, "New desc");
383
+ assert.match(updated?.body || "", /New body/);
384
+
385
+ await cleanup();
386
+ });
387
+
388
+ it("update can rebuild the body from structured fields", async () => {
389
+ let captured: any;
390
+ const mockPi = {
391
+ registerTool: (def: any) => { captured = def; },
392
+ } as any;
393
+
394
+ const store = await makeStore();
395
+ const created = await store.create("my-skill", "Old desc", "## Old body", "global");
396
+ registerSkillTool(mockPi, store);
397
+
398
+ const result = await captured.execute("tc-1", {
399
+ action: "update",
400
+ skill_id: created.skillId,
401
+ description: "New desc",
402
+ when_to_use: "Use when validating the new rewrite path.",
403
+ procedure_steps: ["Perform the new sequence."],
404
+ verification_steps: ["Confirm the new sequence works."],
405
+ }, undefined, undefined, undefined);
406
+
407
+ const parsed = JSON.parse(result.content[0].text);
408
+ assert.strictEqual(parsed.success, true);
409
+
410
+ const updated = await store.loadSkill(created.skillId!);
411
+ assert.match(updated?.body || "", /## When to Use/);
412
+ assert.match(updated?.body || "", /Perform the new sequence/);
413
+ assert.match(updated?.body || "", /No notable pitfalls recorded yet/);
414
+
415
+ await cleanup();
416
+ });
417
+
418
+ it("legacy edit alias still rewrites the skill", async () => {
419
+ let captured: any;
420
+ const mockPi = {
421
+ registerTool: (def: any) => { captured = def; },
422
+ } as any;
423
+
424
+ const store = await makeStore();
425
+ const created = await store.create("legacy-skill", "Old desc", "## Old body", "global");
426
+ registerSkillTool(mockPi, store);
427
+
428
+ const result = await captured.execute("tc-1", {
429
+ action: "edit",
430
+ skill_id: created.skillId,
431
+ description: "Legacy desc",
432
+ content: "## Legacy body",
433
+ }, undefined, undefined, undefined);
434
+
435
+ const parsed = JSON.parse(result.content[0].text);
436
+ assert.strictEqual(parsed.success, true);
437
+
438
+ const updated = await store.loadSkill(created.skillId!);
439
+ assert.strictEqual(updated?.description, "Legacy desc");
440
+ assert.match(updated?.body || "", /Legacy body/);
441
+
442
+ await cleanup();
443
+ });
444
+
445
+ it("delete requires skill_id", async () => {
446
+ let captured: any;
447
+ const mockPi = {
448
+ registerTool: (def: any) => { captured = def; },
449
+ } as any;
450
+
451
+ const store = await makeStore();
452
+ registerSkillTool(mockPi, store);
453
+
454
+ const result = await captured.execute("tc-1", { action: "delete" }, undefined, undefined, undefined);
455
+ const parsed = JSON.parse(result.content[0].text);
456
+ assert.strictEqual(parsed.success, false);
457
+ assert.ok(parsed.error.includes("skill_id"));
458
+
459
+ await cleanup();
460
+ });
461
+
462
+ it("unknown action returns error", async () => {
463
+ let captured: any;
464
+ const mockPi = {
465
+ registerTool: (def: any) => { captured = def; },
466
+ } as any;
467
+
468
+ const store = await makeStore();
469
+ registerSkillTool(mockPi, store);
470
+
471
+ const result = await captured.execute("tc-1", { action: "explode" }, undefined, undefined, undefined);
472
+ const parsed = JSON.parse(result.content[0].text);
473
+ assert.strictEqual(parsed.success, false);
474
+ assert.ok(parsed.error.includes("Unknown action"));
475
+
476
+ await cleanup();
477
+ });
478
+ });
@@ -0,0 +1,40 @@
1
+ import { describe, it } from "node:test";
2
+ import * as assert from "node:assert/strict";
3
+ import { registerMemoryTool } from "../../src/tools/memory-tool.js";
4
+ import { registerMemorySearchTool } from "../../src/tools/memory-search-tool.js";
5
+ import { registerSessionSearchTool } from "../../src/tools/session-search-tool.js";
6
+ import { registerSkillTool } from "../../src/tools/skill-tool.js";
7
+
8
+ function capture(register: (pi: any) => void): any {
9
+ let definition: any;
10
+ register({ registerTool(value: any) { definition = value; } });
11
+ return definition;
12
+ }
13
+
14
+ describe("tool result renderer wiring", () => {
15
+ it("registers renderResult on memory and memory_search", () => {
16
+ const memory = capture((pi) => registerMemoryTool(pi, {} as any, null));
17
+ const memorySearch = capture((pi) => registerMemorySearchTool(pi, {} as any));
18
+
19
+ assert.equal(typeof memory.renderResult, "function");
20
+ assert.equal(typeof memorySearch.renderResult, "function");
21
+ });
22
+
23
+ it("registers renderResult on both session_search variants", () => {
24
+ const legacy = capture((pi) => registerSessionSearchTool(pi, {} as any));
25
+ const anchors = capture((pi) => registerSessionSearchTool(
26
+ pi,
27
+ {} as any,
28
+ { variant: "anchors" },
29
+ { sessionsDir: "/path-independent-sessions" },
30
+ ));
31
+
32
+ assert.equal(typeof legacy.renderResult, "function");
33
+ assert.equal(typeof anchors.renderResult, "function");
34
+ });
35
+
36
+ it("registers renderResult on skill_manage", () => {
37
+ const skill = capture((pi) => registerSkillTool(pi, {} as any));
38
+ assert.equal(typeof skill.renderResult, "function");
39
+ });
40
+ });
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
6
+ "lib": ["ES2022"],
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "sourceMap": true
16
+ },
17
+ "include": ["src/**/*.ts"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }
@@ -12,7 +12,7 @@ Rewind metadata lives in the session itself as hidden entries, so rewind history
12
12
 
13
13
  ## Requirements
14
14
 
15
- - Pi agent v0.65.0+
15
+ - Pi agent v0.74.0+
16
16
  - Node.js (for installation)
17
17
  - Git repository
18
18
 
@@ -181,6 +181,8 @@ Rewind restores the exact file state for the snapshot domain it owns:
181
181
 
182
182
  Before restoring target contents, it deletes paths present in the current snapshot but absent from the target snapshot, then restores the target snapshot into the worktree only.
183
183
 
184
+ Submodules are supported only when their paths stay unchanged, their worktrees are clean and initialized, and each target commit is already available locally. Rewind checks out those target commits without fetching. Exact restore is refused with a clear error for dirty or unavailable submodule state, added or removed submodule paths, and nested submodules; uncommitted files inside submodules are not part of snapshots.
185
+
184
186
  Out of scope:
185
187
 
186
188
  - ignored files
@@ -240,6 +242,7 @@ grep '"customType":"rewind-' ~/.pi/agent/sessions/**/*.jsonl
240
242
  ## Limitations
241
243
 
242
244
  - Only works in git repositories
245
+ - Submodule snapshots contain gitlink commits, not uncommitted nested files; unsupported submodule states are refused instead of reported as exact restores
243
246
  - Session metadata grows append-only; retention only trims git reachability
244
247
  - Discovery for retention is best-effort across discovered Pi session roots and explicit `parentSession` ancestors
245
248
  - Ignored files and empty directories are outside the snapshot model