@selesai/code 0.12.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (466) hide show
  1. package/CHANGELOG.md +17 -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/core/usage-totals.d.ts +2 -0
  9. package/dist/core/usage-totals.js +10 -0
  10. package/dist/extensions/ascii.txt +9 -0
  11. package/dist/extensions/package.json +1 -2
  12. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
  13. package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
  14. package/dist/extensions/pi-hermes-memory/README.md +643 -0
  15. package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
  16. package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
  17. package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
  18. package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
  19. package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
  20. package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
  21. package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
  22. package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
  23. package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
  24. package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
  25. package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
  26. package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
  27. package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
  28. package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
  29. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
  30. package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
  31. package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
  32. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
  33. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
  34. package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
  35. package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
  36. package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
  37. package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
  38. package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
  39. package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
  40. package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
  41. package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
  42. package/dist/extensions/pi-hermes-memory/package.json +66 -0
  43. package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
  44. package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
  45. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
  46. package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
  47. package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
  48. package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
  49. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
  50. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
  51. package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
  52. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
  53. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
  54. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
  55. package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
  56. package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
  57. package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
  58. package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
  59. package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
  60. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
  61. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
  62. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
  63. package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
  64. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
  65. package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
  66. package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
  67. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
  68. package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
  69. package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
  70. package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
  71. package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
  72. package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
  73. package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
  74. package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
  75. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
  76. package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
  77. package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
  78. package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
  79. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
  80. package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
  82. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
  83. package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
  84. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
  85. package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
  86. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
  87. package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
  88. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
  89. package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
  90. package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
  91. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
  92. package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
  93. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
  94. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
  95. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
  96. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
  97. package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
  98. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
  99. package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
  100. package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
  101. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
  102. package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
  103. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
  104. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
  105. package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
  106. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
  107. package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
  108. package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
  109. package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
  110. package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
  111. package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
  112. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
  113. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
  114. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
  115. package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
  116. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
  117. package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
  118. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
  119. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
  120. package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
  121. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
  122. package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
  123. package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
  124. package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
  125. package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
  126. package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
  127. package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
  128. package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
  129. package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
  130. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
  131. package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
  132. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
  133. package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
  134. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
  135. package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
  136. package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
  137. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
  138. package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
  139. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
  140. package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
  141. package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
  142. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
  143. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
  144. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
  145. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
  146. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
  147. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
  148. package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
  149. package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
  150. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
  151. package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
  152. package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
  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 -3
  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 +132 -0
  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/extensions/pi-zentui/extensions/zentui/format.ts +2 -1
  455. package/dist/extensions/pi-zentui/test/format.test.ts +15 -1
  456. package/dist/modes/interactive/components/footer.js +2 -2
  457. package/dist/modes/interactive/interactive-mode.js +11 -11
  458. package/dist/skills/workflow/SKILL.md +65 -50
  459. package/package.json +112 -110
  460. package/dist/extensions/enable-readonly-tools.test.ts +0 -63
  461. package/dist/extensions/enable-readonly-tools.ts +0 -24
  462. package/dist/extensions/model-prompt-injector/config.json +0 -16
  463. package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
  464. package/dist/extensions/model-prompt-injector/index.ts +0 -148
  465. package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
  466. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
@@ -0,0 +1,21 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { formatFrontmatter } from "../../src/store/skill-utils.js";
4
+
5
+ describe("formatFrontmatter", () => {
6
+ it("quotes string fields safely for YAML", () => {
7
+ const raw = formatFrontmatter({
8
+ name: "audit-agents-md",
9
+ displayName: "Audit AGENTS.md",
10
+ description: "Audit and restructure AGENTS.md files: remove cross-references between sections",
11
+ version: 1,
12
+ created: "2026-05-18",
13
+ updated: "2026-05-18",
14
+ body: "# Steps\n1. Do thing",
15
+ });
16
+
17
+ assert.ok(raw.includes('name: "audit-agents-md"'));
18
+ assert.ok(raw.includes('description: "Audit and restructure AGENTS.md files: remove cross-references between sections"'));
19
+ assert.ok(raw.includes('display_name: "Audit AGENTS.md"'));
20
+ });
21
+ });
@@ -0,0 +1,78 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { spawnSync } from "node:child_process";
4
+ import fs from "node:fs";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+
9
+ const srcRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../src");
10
+
11
+ const POISON_REQUIRE = [
12
+ 'import Module from "node:module";',
13
+ 'import path from "node:path";',
14
+ "const original = Module.prototype.require;",
15
+ "Module.prototype.require = function (id: string) {",
16
+ ' if (id === "better-sqlite3") {',
17
+ " throw Object.assign(new Error(\"Cannot find package 'better-sqlite3'\"), { code: \"MODULE_NOT_FOUND\" });",
18
+ " }",
19
+ " return original.apply(this, arguments as never);",
20
+ "};",
21
+ ].join("\n");
22
+
23
+ /**
24
+ * Run `body` in a child process where `require("better-sqlite3")` always fails,
25
+ * standing in for compiled Pi, whose Bun resolver cannot find the package from
26
+ * an on-disk extension file.
27
+ */
28
+ function runWithoutBetterSqlite3(body: string): { status: number | null; output: string } {
29
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "hermes-lazy-sqlite-"));
30
+ try {
31
+ const child = path.join(dir, "probe.mts");
32
+ fs.writeFileSync(child, `${POISON_REQUIRE}\n${body}\n`);
33
+ const result = spawnSync(process.execPath, ["--import", "tsx", child], { encoding: "utf-8" });
34
+ return { status: result.status, output: `${result.stdout ?? ""}${result.stderr ?? ""}` };
35
+ } finally {
36
+ fs.rmSync(dir, { recursive: true, force: true });
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Regression guard for issue #117: a module-scope native load turned an
42
+ * unresolvable better-sqlite3 into "Failed to load extension", bricking the
43
+ * extension for every compiled-Pi user instead of failing at the point of use.
44
+ */
45
+ describe("SQLite native loading is deferred past extension load", () => {
46
+ it("imports the extension-load module graph without resolving better-sqlite3", () => {
47
+ // Dynamic import: the specifiers are absolute paths built at runtime so the
48
+ // poisoned require hook is installed before the graph is evaluated.
49
+ const body = [
50
+ `for (const specifier of ${JSON.stringify([
51
+ path.join(srcRoot, "extension-root-migration.ts"),
52
+ path.join(srcRoot, "store/db.ts"),
53
+ path.join(srcRoot, "store/atomic-lock-coordinator.ts"),
54
+ ])}) {`,
55
+ " await import(specifier);",
56
+ "}",
57
+ 'console.log("IMPORTED_OK");',
58
+ ].join("\n");
59
+
60
+ const { status, output } = runWithoutBetterSqlite3(body);
61
+ assert.match(output, /IMPORTED_OK/);
62
+ assert.equal(status, 0);
63
+ });
64
+
65
+ it("still fails loudly when SQLite is actually used", () => {
66
+ const body = [
67
+ `const { AtomicLockCoordinator } = await import(${JSON.stringify(path.join(srcRoot, "store/atomic-lock-coordinator.ts"))});`,
68
+ 'const dir = fs.mkdtempSync(path.join(os.tmpdir(), "hermes-lazy-sqlite-use-"));',
69
+ 'new AtomicLockCoordinator(path.join(dir, "locks.sqlite")).tryAcquire("k", { staleMs: 1000 });',
70
+ ].join("\n");
71
+
72
+ const { status, output } = runWithoutBetterSqlite3(
73
+ `import fs from "node:fs";\nimport os from "node:os";\n${body}`,
74
+ );
75
+ assert.notEqual(status, 0);
76
+ assert.match(output, /better-sqlite3/);
77
+ });
78
+ });
@@ -0,0 +1,543 @@
1
+ import { describe, it, beforeEach, afterEach } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import os from 'node:os';
6
+ import { DatabaseManager } from '../../src/store/db.js';
7
+ import {
8
+ addMemory,
9
+ searchMemories,
10
+ getMemories,
11
+ removeMemory,
12
+ touchMemory,
13
+ getMemoryStats,
14
+ syncMemoryEntry,
15
+ replaceSyncedMemories,
16
+ removeSyncedMemories,
17
+ parseMarkdownMemoryEntry,
18
+ formatFailureMemoryContent,
19
+ reconcileMarkdownMemoryScope,
20
+ reconcileMarkdownFailureScopes,
21
+ } from '../../src/store/sqlite-memory-store.js';
22
+ import { MemoryStore } from '../../src/store/memory-store.js';
23
+
24
+ describe('sqlite-memory-store', () => {
25
+ let tmpDir: string;
26
+ let dbManager: DatabaseManager;
27
+
28
+ beforeEach(() => {
29
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'memory-store-test-'));
30
+ dbManager = new DatabaseManager(tmpDir);
31
+ });
32
+
33
+ afterEach(() => {
34
+ dbManager.close();
35
+ fs.rmSync(tmpDir, { recursive: true, force: true });
36
+ });
37
+
38
+ describe('addMemory', () => {
39
+ it('should add a memory entry', () => {
40
+ const entry = addMemory(dbManager, 'prefers pnpm over npm');
41
+ assert.ok(entry.id > 0);
42
+ assert.strictEqual(entry.target, 'memory');
43
+ assert.strictEqual(entry.content, 'prefers pnpm over npm');
44
+ assert.ok(entry.created.length > 0);
45
+ assert.ok(entry.lastReferenced.length > 0);
46
+ });
47
+
48
+ it('should add a user entry', () => {
49
+ const entry = addMemory(dbManager, 'name: Chandrateja', 'user');
50
+ assert.strictEqual(entry.target, 'user');
51
+ });
52
+
53
+ it('should add a project-specific entry', () => {
54
+ const entry = addMemory(dbManager, 'uses Prisma', 'memory', 'my-project');
55
+ assert.strictEqual(entry.project, 'my-project');
56
+ });
57
+
58
+ it('should add a global entry (null project)', () => {
59
+ const entry = addMemory(dbManager, 'timezone: AEST');
60
+ assert.strictEqual(entry.project, null);
61
+ });
62
+ });
63
+
64
+ describe('syncMemoryEntry', () => {
65
+ it('deduplicates exact logical entries', () => {
66
+ const first = syncMemoryEntry(dbManager, {
67
+ content: 'prefers pnpm over npm',
68
+ target: 'memory',
69
+ });
70
+ const second = syncMemoryEntry(dbManager, {
71
+ content: 'prefers pnpm over npm',
72
+ target: 'memory',
73
+ });
74
+
75
+ assert.strictEqual(first.action, 'inserted');
76
+ assert.strictEqual(second.action, 'existing');
77
+ assert.strictEqual(getMemories(dbManager).length, 1);
78
+ });
79
+
80
+ it('stores project-scoped memory with project name', () => {
81
+ syncMemoryEntry(dbManager, {
82
+ content: 'uses Prisma',
83
+ target: 'memory',
84
+ project: 'project-a',
85
+ });
86
+
87
+ const results = getMemories(dbManager, { project: 'project-a' });
88
+ assert.strictEqual(results.length, 1);
89
+ assert.strictEqual(results[0].project, 'project-a');
90
+ assert.strictEqual(results[0].target, 'memory');
91
+ });
92
+
93
+ it('preserves failure category metadata', () => {
94
+ syncMemoryEntry(dbManager, {
95
+ content: formatFailureMemoryContent('pnpm lockfile mismatch', {
96
+ category: 'tool-quirk',
97
+ failureReason: 'npm install rewrote lockfile',
98
+ }),
99
+ target: 'failure',
100
+ category: 'tool-quirk',
101
+ failureReason: 'npm install rewrote lockfile',
102
+ });
103
+
104
+ const results = getMemories(dbManager, { target: 'failure', category: 'tool-quirk' });
105
+ assert.strictEqual(results.length, 1);
106
+ assert.strictEqual(results[0].category, 'tool-quirk');
107
+ assert.strictEqual(results[0].failureReason, 'npm install rewrote lockfile');
108
+ });
109
+
110
+ it('parses Markdown failure entries for backfill', () => {
111
+ const parsed = parseMarkdownMemoryEntry(
112
+ '[correction] use pnpm — Failed: npm install rewrote lockfile <!-- created=2026-05-08, last=2026-05-09 -->',
113
+ 'failure',
114
+ );
115
+
116
+ assert.strictEqual(parsed.category, 'correction');
117
+ assert.strictEqual(parsed.failureReason, 'npm install rewrote lockfile');
118
+ assert.strictEqual(parsed.created, '2026-05-08');
119
+ assert.strictEqual(parsed.lastReferenced, '2026-05-09');
120
+ });
121
+
122
+ it('does not infer project scope from spoofable failure content', () => {
123
+ const raw = '[correction] literal user text — Project: other-project <!-- created=2026-05-08, last=2026-05-09 -->';
124
+
125
+ reconcileMarkdownFailureScopes(dbManager, [raw]);
126
+
127
+ assert.strictEqual(getMemories(dbManager, { target: 'failure', project: 'other-project' }).length, 0);
128
+ assert.strictEqual(getMemories(dbManager, { target: 'failure', project: null }).length, 1);
129
+ });
130
+
131
+ it('round-trips project correction scope through authoritative Markdown metadata', async () => {
132
+ const store = new MemoryStore({
133
+ memoryDir: tmpDir,
134
+ memoryCharLimit: 5_000,
135
+ userCharLimit: 5_000,
136
+ failureCharLimit: 5_000,
137
+ } as any);
138
+ await store.loadFromDisk();
139
+
140
+ await store.addFailure('use pnpm in this repo', {
141
+ category: 'correction',
142
+ failureReason: 'User corrected the agent',
143
+ project: 'project-a',
144
+ });
145
+ const [raw] = store.getRawEntriesForSync('failure');
146
+ reconcileMarkdownFailureScopes(dbManager, [raw]);
147
+
148
+ const entries = getMemories(dbManager, { target: 'failure', project: 'project-a' });
149
+ assert.strictEqual(entries.length, 1);
150
+ assert.strictEqual(entries[0].project, 'project-a');
151
+ assert.doesNotMatch(entries[0].content, /Project: project-a/);
152
+ });
153
+ });
154
+
155
+ describe('reconcileMarkdownMemoryScope', () => {
156
+ it('keeps explicit global MEMORY and USER scope despite embedded project metadata', () => {
157
+ const marker = 'c3Bvb2ZlZC1wcm9qZWN0';
158
+
159
+ reconcileMarkdownMemoryScope(
160
+ dbManager,
161
+ [`global memory <!-- created=2026-07-01, last=2026-07-02, project64=${marker} -->`],
162
+ 'memory',
163
+ null,
164
+ );
165
+ reconcileMarkdownMemoryScope(
166
+ dbManager,
167
+ [`global user <!-- created=2026-07-01, last=2026-07-02, project64=${marker} -->`],
168
+ 'user',
169
+ null,
170
+ );
171
+
172
+ assert.deepStrictEqual(
173
+ getMemories(dbManager).map((entry) => [entry.project, entry.target, entry.content]),
174
+ [
175
+ [null, 'memory', 'global memory'],
176
+ [null, 'user', 'global user'],
177
+ ],
178
+ );
179
+ assert.deepStrictEqual(getMemories(dbManager, { project: 'spoofed-project' }), []);
180
+ });
181
+
182
+ it('prunes only absent rows in the exact target and project scope', () => {
183
+ addMemory(dbManager, 'kept global memory', 'memory', null);
184
+ addMemory(dbManager, 'orphaned global memory', 'memory', null);
185
+ addMemory(dbManager, 'unrelated global user', 'user', null);
186
+ addMemory(dbManager, 'unrelated project memory', 'memory', 'project-a');
187
+
188
+ const first = reconcileMarkdownMemoryScope(
189
+ dbManager,
190
+ ['kept global memory <!-- created=2026-07-01, last=2026-07-02 -->'],
191
+ 'memory',
192
+ null,
193
+ );
194
+ const second = reconcileMarkdownMemoryScope(
195
+ dbManager,
196
+ ['kept global memory <!-- created=2026-07-01, last=2026-07-02 -->'],
197
+ 'memory',
198
+ null,
199
+ );
200
+
201
+ assert.strictEqual(first.removed, 1);
202
+ assert.strictEqual(second.removed, 0);
203
+ assert.deepStrictEqual(
204
+ getMemories(dbManager).map((entry) => entry.content).sort(),
205
+ ['kept global memory', 'unrelated global user', 'unrelated project memory'].sort(),
206
+ );
207
+ });
208
+
209
+ it('removes duplicate and stale-category rows by full Markdown identity', () => {
210
+ const first = addMemory(
211
+ dbManager,
212
+ '[correction] use pnpm',
213
+ 'failure',
214
+ 'project-a',
215
+ 'correction',
216
+ 'original reason',
217
+ null,
218
+ 'pnpm install',
219
+ '2026-06-01',
220
+ '2026-07-05',
221
+ );
222
+ addMemory(dbManager, '[correction] use pnpm', 'failure', 'project-a', 'correction');
223
+ addMemory(dbManager, '[correction] use pnpm', 'failure', 'project-a', 'tool-quirk');
224
+
225
+ const result = reconcileMarkdownMemoryScope(
226
+ dbManager,
227
+ ['[correction] use pnpm <!-- created=2026-07-01, last=2026-07-02, project64=cHJvamVjdC1h -->'],
228
+ 'failure',
229
+ 'project-a',
230
+ );
231
+
232
+ const rows = dbManager.getDb().prepare(`
233
+ SELECT id, category, failure_reason, corrected_to, created, last_referenced
234
+ FROM memories
235
+ WHERE project = 'project-a' AND target = 'failure'
236
+ `).all() as Array<{
237
+ id: number;
238
+ category: string | null;
239
+ failure_reason: string | null;
240
+ corrected_to: string | null;
241
+ created: string;
242
+ last_referenced: string;
243
+ }>;
244
+
245
+ assert.strictEqual(result.removed, 2);
246
+ assert.deepStrictEqual(rows, [{
247
+ id: first.id,
248
+ category: 'correction',
249
+ failure_reason: 'original reason',
250
+ corrected_to: 'pnpm install',
251
+ created: '2026-06-01',
252
+ last_referenced: '2026-07-05',
253
+ }]);
254
+ });
255
+ });
256
+
257
+ describe('replace/remove synced memories', () => {
258
+ it('escapes % and _ during replace matching', () => {
259
+ addMemory(dbManager, 'token 100%_safe value');
260
+ addMemory(dbManager, 'token 100XXsafe value');
261
+
262
+ const result = replaceSyncedMemories(dbManager, '100%_safe', {
263
+ content: 'token updated literal value',
264
+ target: 'memory',
265
+ project: null,
266
+ });
267
+
268
+ assert.strictEqual(result.matched, 1);
269
+ const all = getMemories(dbManager);
270
+ assert.ok(all.some((entry) => entry.content === 'token updated literal value'));
271
+ assert.ok(all.some((entry) => entry.content === 'token 100XXsafe value'));
272
+ });
273
+
274
+ it('escapes % and _ during remove matching', () => {
275
+ addMemory(dbManager, 'remove 50%_match literal');
276
+ addMemory(dbManager, 'remove 50AAmatch literal');
277
+
278
+ const result = removeSyncedMemories(dbManager, '50%_match', {
279
+ target: 'memory',
280
+ project: null,
281
+ });
282
+
283
+ assert.strictEqual(result.matched, 1);
284
+ const all = getMemories(dbManager);
285
+ assert.strictEqual(all.length, 1);
286
+ assert.strictEqual(all[0].content, 'remove 50AAmatch literal');
287
+ });
288
+
289
+ it('normalizes pasted memory_search lines during replace matching', () => {
290
+ addMemory(dbManager, 'prefers pnpm over npm');
291
+
292
+ const result = replaceSyncedMemories(
293
+ dbManager,
294
+ '🧠 scope=global [target=memory] prefers pnpm over npm\n Created: 2026-05-27 | Last used: 2026-05-27',
295
+ {
296
+ content: 'prefers pnpm over npm and bun when needed',
297
+ target: 'memory',
298
+ project: null,
299
+ },
300
+ );
301
+
302
+ assert.strictEqual(result.matched, 1);
303
+ const all = getMemories(dbManager);
304
+ assert.ok(all.some((entry) => entry.content === 'prefers pnpm over npm and bun when needed'));
305
+ });
306
+
307
+ it('normalizes pasted memory_search lines during remove matching', () => {
308
+ addMemory(dbManager, '[correction] use pnpm — Failed: npm rewrote the lockfile', 'failure');
309
+
310
+ const result = removeSyncedMemories(
311
+ dbManager,
312
+ '⚠️ [global] [correction] [correction] use pnpm\n Created: 2026-05-27 | Last used: 2026-05-27',
313
+ {
314
+ target: 'failure',
315
+ project: null,
316
+ },
317
+ );
318
+
319
+ assert.strictEqual(result.matched, 1);
320
+ const all = getMemories(dbManager);
321
+ assert.strictEqual(all.length, 0);
322
+ });
323
+ });
324
+
325
+ describe('searchMemories', () => {
326
+ beforeEach(() => {
327
+ addMemory(dbManager, 'prefers pnpm over npm');
328
+ addMemory(dbManager, 'uses Prisma with PostgreSQL', 'memory', 'project-a');
329
+ addMemory(dbManager, 'debugged gpu timeout issue after driver update');
330
+ addMemory(dbManager, 'memory search indexing notes');
331
+ addMemory(dbManager, 'exact phrase memory search example');
332
+ addMemory(dbManager, 'name: Chandrateja', 'user');
333
+ addMemory(dbManager, 'timezone: AEST', 'user');
334
+ });
335
+
336
+ it('should find memories by keyword', () => {
337
+ const results = searchMemories(dbManager, 'pnpm');
338
+ assert.ok(results.length > 0);
339
+ assert.ok(results.some(r => r.content.includes('pnpm')));
340
+ });
341
+
342
+ it('should find memories by partial content', () => {
343
+ const results = searchMemories(dbManager, 'Prisma');
344
+ assert.ok(results.length > 0);
345
+ assert.ok(results.some(r => r.content.includes('Prisma')));
346
+ });
347
+ it('finds pure CJK substrings with the trigram tokenizer', () => {
348
+ addMemory(dbManager, '设备清单包含 NAS 和备份策略');
349
+
350
+ const results = searchMemories(dbManager, '设备清单');
351
+
352
+ assert.ok(results.length > 0);
353
+ assert.ok(results.some((result) => result.content.includes('设备清单')));
354
+ });
355
+
356
+ it('retains English token searches in the trigram index', () => {
357
+ addMemory(dbManager, '设备清单包含 NAS 和备份策略');
358
+
359
+ const results = searchMemories(dbManager, 'NAS');
360
+
361
+ assert.ok(results.length > 0);
362
+ assert.ok(results.some((result) => result.content.includes('NAS')));
363
+ });
364
+
365
+ it('falls back to a scoped literal search for one- and two-character CJK queries', () => {
366
+ addMemory(dbManager, '设备清单包含 NAS 和备份策略');
367
+
368
+ const results = searchMemories(dbManager, '设备');
369
+
370
+ assert.ok(results.some((result) => result.content.includes('设备清单')));
371
+ });
372
+
373
+
374
+ it('should match multi-word queries without requiring an exact phrase', () => {
375
+ const results = searchMemories(dbManager, 'gpu issue');
376
+ assert.ok(results.length > 0);
377
+ assert.ok(results.some((r) => r.content.includes('gpu timeout issue')));
378
+ });
379
+
380
+ it('should ignore lowercase connector words in natural-language queries', () => {
381
+ const results = searchMemories(dbManager, 'gpu and issue');
382
+ assert.ok(results.length > 0);
383
+ assert.ok(results.some((r) => r.content.includes('gpu timeout issue')));
384
+ });
385
+ it('should fall back to broader natural-language matching when strict term matching misses', () => {
386
+ addMemory(dbManager, "user's name is Naruto", 'user');
387
+
388
+ const results = searchMemories(dbManager, 'name identity Naruto', { target: 'user' });
389
+
390
+ assert.ok(results.length > 0);
391
+ assert.ok(results.some((r) => r.content.includes("Naruto")));
392
+ });
393
+
394
+ it('should not broaden explicit operator queries', () => {
395
+ const results = searchMemories(dbManager, 'pnpm AND nonexistent');
396
+
397
+ assert.strictEqual(results.length, 0);
398
+ });
399
+
400
+ it('should preserve explicit quoted phrase searches', () => {
401
+ const results = searchMemories(dbManager, '"memory search"');
402
+ assert.ok(results.length > 0);
403
+ assert.ok(results.every((r) => r.content.includes('memory search')));
404
+ });
405
+
406
+ it('should recover natural-language queries with uppercase operator words and punctuation', () => {
407
+ addMemory(dbManager, 'Never search whole filesystem from root. Do not run find /.', 'user');
408
+
409
+ const results = searchMemories(dbManager, 'DO NOT USE FIND /', { target: 'user' });
410
+
411
+ assert.ok(results.length > 0);
412
+ assert.ok(results.some((r) => r.content.includes('find')));
413
+ });
414
+
415
+ it('should preserve valid operator queries', () => {
416
+ const results = searchMemories(dbManager, 'pnpm OR AEST');
417
+ assert.ok(results.length >= 2);
418
+ assert.ok(results.some((r) => r.content.includes('pnpm')));
419
+ assert.ok(results.some((r) => r.content.includes('AEST')));
420
+ });
421
+
422
+ it('should limit results', () => {
423
+ const results = searchMemories(dbManager, 'pnpm OR Prisma OR AEST', { limit: 2 });
424
+ assert.ok(results.length <= 2);
425
+ });
426
+
427
+ it('should filter by project', () => {
428
+ const results = searchMemories(dbManager, 'Prisma', { project: 'project-a' });
429
+ assert.ok(results.length > 0);
430
+ assert.ok(results.every(r => r.project === 'project-a'));
431
+ });
432
+
433
+ it('should filter by target', () => {
434
+ const results = searchMemories(dbManager, 'Chandrateja OR AEST', { target: 'user' });
435
+ assert.ok(results.length > 0);
436
+ assert.ok(results.every(r => r.target === 'user'));
437
+ });
438
+
439
+ it('should return empty for no matches', () => {
440
+ const results = searchMemories(dbManager, 'nonexistent-xyz');
441
+ assert.strictEqual(results.length, 0);
442
+ });
443
+
444
+ it('should return empty for blank queries', () => {
445
+ assert.deepStrictEqual(searchMemories(dbManager, ' '), []);
446
+ });
447
+
448
+ it('should not throw on unmatched quotes', () => {
449
+ assert.doesNotThrow(() => {
450
+ const results = searchMemories(dbManager, 'issue "timeout');
451
+ assert.ok(Array.isArray(results));
452
+ });
453
+ });
454
+
455
+ it('should return empty for malformed operator queries', () => {
456
+ const results = searchMemories(dbManager, 'AND OR NOT');
457
+ assert.strictEqual(results.length, 0);
458
+ });
459
+ });
460
+
461
+ describe('getMemories', () => {
462
+ beforeEach(() => {
463
+ addMemory(dbManager, 'global memory 1');
464
+ addMemory(dbManager, 'global memory 2');
465
+ addMemory(dbManager, 'project memory', 'memory', 'project-a');
466
+ addMemory(dbManager, 'user preference', 'user');
467
+ });
468
+
469
+ it('should return all memories', () => {
470
+ const results = getMemories(dbManager);
471
+ assert.strictEqual(results.length, 4);
472
+ });
473
+
474
+ it('should filter by project', () => {
475
+ const results = getMemories(dbManager, { project: 'project-a' });
476
+ assert.strictEqual(results.length, 1);
477
+ assert.strictEqual(results[0].content, 'project memory');
478
+ });
479
+
480
+ it('should filter by null project (global)', () => {
481
+ const results = getMemories(dbManager, { project: null });
482
+ assert.strictEqual(results.length, 3);
483
+ });
484
+
485
+ it('should filter by target', () => {
486
+ const results = getMemories(dbManager, { target: 'user' });
487
+ assert.strictEqual(results.length, 1);
488
+ assert.strictEqual(results[0].content, 'user preference');
489
+ });
490
+ });
491
+
492
+ describe('removeMemory', () => {
493
+ it('should remove a memory by id', () => {
494
+ const entry = addMemory(dbManager, 'to be removed');
495
+ const removed = removeMemory(dbManager, entry.id);
496
+ assert.strictEqual(removed, true);
497
+
498
+ const all = getMemories(dbManager);
499
+ assert.strictEqual(all.length, 0);
500
+ });
501
+
502
+ it('should return false for non-existent id', () => {
503
+ const removed = removeMemory(dbManager, 99999);
504
+ assert.strictEqual(removed, false);
505
+ });
506
+ });
507
+
508
+ describe('touchMemory', () => {
509
+ it('should update last_referenced date', () => {
510
+ const entry = addMemory(dbManager, 'old memory');
511
+ // Manually set an old date
512
+ const db = dbManager.getDb();
513
+ db.prepare('UPDATE memories SET last_referenced = ? WHERE id = ?').run('2020-01-01', entry.id);
514
+
515
+ touchMemory(dbManager, entry.id);
516
+
517
+ const updated = db.prepare('SELECT last_referenced FROM memories WHERE id = ?').get(entry.id) as { last_referenced: string };
518
+ const today = new Date().toISOString().split('T')[0];
519
+ assert.strictEqual(updated.last_referenced, today);
520
+ });
521
+ });
522
+
523
+ describe('getMemoryStats', () => {
524
+ it('should return zero stats for empty database', () => {
525
+ const stats = getMemoryStats(dbManager);
526
+ assert.strictEqual(stats.total, 0);
527
+ assert.deepStrictEqual(stats.byProject, []);
528
+ assert.deepStrictEqual(stats.byTarget, []);
529
+ });
530
+
531
+ it('should return correct stats', () => {
532
+ addMemory(dbManager, 'global 1');
533
+ addMemory(dbManager, 'global 2');
534
+ addMemory(dbManager, 'project memory', 'memory', 'project-a');
535
+ addMemory(dbManager, 'user pref', 'user');
536
+
537
+ const stats = getMemoryStats(dbManager);
538
+ assert.strictEqual(stats.total, 4);
539
+ assert.strictEqual(stats.byTarget.length, 2);
540
+ assert.ok(stats.byProject.length > 0);
541
+ });
542
+ });
543
+ });