@selesai/code 0.13.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 (461) hide show
  1. package/CHANGELOG.md +12 -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/ascii.txt +9 -0
  9. package/dist/extensions/package.json +1 -2
  10. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
  11. package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
  12. package/dist/extensions/pi-hermes-memory/README.md +643 -0
  13. package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
  14. package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
  15. package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
  16. package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
  17. package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
  18. package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
  19. package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
  20. package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
  21. package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
  22. package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
  23. package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
  24. package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
  25. package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
  26. package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
  27. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
  28. package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
  29. package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
  30. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
  31. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
  32. package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
  33. package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
  34. package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
  35. package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
  36. package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
  37. package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
  38. package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
  39. package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
  40. package/dist/extensions/pi-hermes-memory/package.json +66 -0
  41. package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
  42. package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
  43. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
  44. package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
  45. package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
  46. package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
  47. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
  48. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
  49. package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
  50. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
  51. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
  52. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
  53. package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
  54. package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
  55. package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
  56. package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
  57. package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
  58. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
  59. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
  60. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
  61. package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
  62. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
  63. package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
  64. package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
  65. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
  66. package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
  67. package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
  68. package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
  69. package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
  70. package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
  71. package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
  72. package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
  73. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
  74. package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
  75. package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
  76. package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
  77. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
  78. package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
  79. package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
  80. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
  82. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
  83. package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
  84. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
  85. package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
  86. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
  87. package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
  88. package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
  89. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
  90. package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
  91. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
  92. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
  93. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
  94. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
  95. package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
  96. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
  97. package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
  98. package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
  99. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
  100. package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
  101. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
  102. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
  103. package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
  104. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
  105. package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
  106. package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
  107. package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
  108. package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
  109. package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
  110. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
  111. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
  112. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
  113. package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
  114. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
  115. package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
  116. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
  117. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
  118. package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
  119. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
  120. package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
  121. package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
  122. package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
  123. package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
  124. package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
  125. package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
  126. package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
  127. package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
  128. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
  129. package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
  130. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
  131. package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
  132. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
  133. package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
  134. package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
  135. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
  136. package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
  137. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
  138. package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
  139. package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
  140. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
  141. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
  142. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
  143. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
  144. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
  145. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
  146. package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
  147. package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
  148. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
  149. package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
  150. package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
  151. package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
  152. package/dist/extensions/pi-subagents/AGENTS.md +5 -0
  153. package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
  154. package/dist/extensions/pi-subagents/README.md +12 -6
  155. package/dist/extensions/pi-subagents/VISION.md +81 -0
  156. package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
  157. package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
  158. package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
  159. package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
  160. package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
  161. package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
  162. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
  163. package/dist/extensions/pi-subagents/docs/agents.md +488 -0
  164. package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
  165. package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
  166. package/dist/extensions/pi-subagents/docs/models.md +27 -4
  167. package/dist/extensions/pi-subagents/docs/observability.md +10 -9
  168. package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
  169. package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
  170. package/dist/extensions/pi-subagents/package-lock.json +389 -2
  171. package/dist/extensions/pi-subagents/package.json +3 -1
  172. package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
  173. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
  174. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
  175. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
  176. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  177. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
  178. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
  179. package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
  180. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
  181. package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
  182. package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
  183. package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
  184. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
  185. package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
  186. package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
  187. package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
  188. package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
  189. package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
  190. package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
  191. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
  192. package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
  193. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
  194. package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
  195. package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
  196. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
  197. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
  198. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
  199. package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
  200. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -3
  201. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
  202. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
  203. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
  204. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
  205. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
  206. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
  207. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
  208. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
  209. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
  210. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
  211. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
  212. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
  213. package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
  214. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
  215. package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
  216. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
  217. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
  218. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
  219. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
  220. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
  221. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
  222. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
  223. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
  224. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
  225. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
  226. package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
  227. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
  228. package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
  229. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
  230. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
  231. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
  232. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
  233. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
  234. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
  235. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
  236. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
  237. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
  238. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
  239. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
  240. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
  241. package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
  242. package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
  243. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
  244. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
  245. package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
  246. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
  247. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
  248. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
  249. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
  250. package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
  251. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
  252. package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
  253. package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
  254. package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
  255. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
  256. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
  257. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
  258. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
  259. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
  260. package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
  261. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
  262. package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
  263. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
  264. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
  265. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
  266. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
  267. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
  268. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
  269. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
  270. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
  271. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
  272. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
  273. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
  274. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
  275. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
  276. package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
  277. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
  278. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
  279. package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
  280. package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
  281. package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
  282. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
  283. package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
  284. package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
  285. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
  286. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
  287. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
  288. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
  289. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
  290. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
  291. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
  292. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
  293. package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
  294. package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
  295. package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
  296. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
  297. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
  298. package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
  299. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
  300. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
  301. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
  302. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
  303. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
  304. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  305. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
  306. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
  307. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
  308. package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
  309. package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
  310. package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
  311. package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
  312. package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
  313. package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
  314. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
  315. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
  316. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
  317. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
  318. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
  319. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
  320. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
  321. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
  322. package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
  323. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
  324. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
  325. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
  326. package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
  327. package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
  328. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
  329. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
  330. package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
  331. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
  332. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
  333. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
  334. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
  335. package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
  336. package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
  337. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
  338. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
  339. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
  340. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
  341. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
  342. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
  343. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
  344. package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
  345. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
  346. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
  347. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
  348. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
  349. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
  350. package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
  351. package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
  352. package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
  353. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
  354. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
  355. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
  356. package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
  357. package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
  358. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
  359. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
  360. package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
  361. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
  362. package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
  363. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
  364. package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
  365. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
  366. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
  367. package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
  368. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
  369. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
  370. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
  371. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +132 -0
  372. package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
  373. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
  374. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
  375. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
  376. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
  377. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
  378. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
  379. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
  380. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
  381. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
  382. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
  383. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
  384. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
  385. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
  386. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
  387. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
  388. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
  389. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
  390. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
  391. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
  392. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
  393. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
  394. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
  395. package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
  396. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
  397. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
  398. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
  399. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
  400. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
  401. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
  402. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
  403. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
  404. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
  405. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
  406. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  407. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
  408. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
  409. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
  410. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
  411. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
  412. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
  413. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
  414. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
  415. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
  416. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
  417. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
  418. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
  419. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
  420. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
  421. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
  422. package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
  423. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
  424. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
  425. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
  426. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
  427. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
  428. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
  429. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
  430. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
  431. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
  432. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
  433. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
  434. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
  435. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
  436. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
  437. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
  438. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
  439. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
  440. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
  441. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
  442. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
  443. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
  444. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
  445. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
  446. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
  447. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
  448. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
  449. package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
  450. package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
  451. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
  452. package/dist/modes/interactive/interactive-mode.js +7 -7
  453. package/dist/skills/workflow/SKILL.md +65 -50
  454. package/package.json +112 -110
  455. package/dist/extensions/enable-readonly-tools.test.ts +0 -63
  456. package/dist/extensions/enable-readonly-tools.ts +0 -24
  457. package/dist/extensions/model-prompt-injector/config.json +0 -16
  458. package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
  459. package/dist/extensions/model-prompt-injector/index.ts +0 -148
  460. package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
  461. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
@@ -20,14 +20,30 @@ type RecordModelFailureOptions = ModelExclusionTarget & {
20
20
 
21
21
  let exclusions: ModelExclusion[] = [];
22
22
  let loaded = false;
23
- let defaultTTLMs = 24 * 60 * 60_000; // 24 hours, overridable via setDefaultTTL
23
+ /** Default duration for a new model exclusion when no per-record TTL is supplied. */
24
+ export const DEFAULT_MODEL_EXCLUSION_TTL_MS = 24 * 60 * 60_000;
25
+ /** Keeps a new expiry safely below JavaScript's maximum Date timestamp. */
26
+ export const MAX_MODEL_EXCLUSION_TTL_MS = 8_000_000_000_000_000;
27
+ const MAX_DATE_TIMESTAMP_MS = 8_640_000_000_000_000;
28
+ let defaultTTLMs = DEFAULT_MODEL_EXCLUSION_TTL_MS;
29
+ let loadedTTLCeilingMs: number | undefined;
24
30
  let persistTimer: ReturnType<typeof setTimeout> | null = null;
25
31
  let persistSeq = 0;
26
32
 
27
- /** Override the default exclusion TTL. */
28
- export function setDefaultTTL(ms: number): void {
29
- if (!Number.isFinite(ms) || ms <= 0) throw new Error("Default model exclusion TTL must be a finite positive number.");
33
+ /**
34
+ * Override the default TTL applied to newly recorded model exclusions.
35
+ *
36
+ * @param ms Duration in milliseconds. Must be finite and positive.
37
+ * @returns Nothing.
38
+ */
39
+ // TEST:test/unit/model-exclusions.test.ts[model exclusions — TTL expiry]
40
+ export function setDefaultTTL(ms: number, options?: { shortenExisting?: boolean }): void {
41
+ if (!Number.isFinite(ms) || ms <= 0 || ms > MAX_MODEL_EXCLUSION_TTL_MS) {
42
+ throw new Error(`Default model exclusion TTL must be a finite positive number no greater than ${MAX_MODEL_EXCLUSION_TTL_MS}.`);
43
+ }
30
44
  defaultTTLMs = ms;
45
+ loadedTTLCeilingMs = options?.shortenExisting ? ms : undefined;
46
+ if (loaded && loadedTTLCeilingMs !== undefined && shortenExclusionsToTTL(exclusions, loadedTTLCeilingMs, Date.now())) schedulePersist();
31
47
  }
32
48
 
33
49
  /**
@@ -78,9 +94,23 @@ function ensureLoaded(): void {
78
94
  const raw = fs.readFileSync(getExclusionsFilePath(), "utf-8");
79
95
  const data = JSON.parse(raw);
80
96
  if (data.version === 1) {
97
+ if (!Array.isArray(data.exclusions)) throw new Error("Model exclusion store version 1 must contain an exclusions array.");
98
+ for (let index = 0; index < data.exclusions.length; index++) {
99
+ const entry = data.exclusions[index];
100
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) throw new Error(`Model exclusion store entry ${index} must be an object.`);
101
+ if (entry.reason !== undefined && typeof entry.reason !== "string") throw new Error(`Model exclusion store entry ${index} has an invalid reason.`);
102
+ for (const field of ["recordedAt", "expiresAt"] as const) {
103
+ const timestamp = entry[field];
104
+ if (typeof timestamp !== "number" || !Number.isFinite(timestamp) || timestamp <= 0 || timestamp > MAX_DATE_TIMESTAMP_MS) {
105
+ throw new Error(`Model exclusion store entry ${index} has an invalid ${field}.`);
106
+ }
107
+ }
108
+ }
81
109
  const now = Date.now();
82
110
  exclusions = (data.exclusions ?? []).filter((e: ModelExclusion) => e.expiresAt > now);
111
+ const shortened = loadedTTLCeilingMs !== undefined && shortenExclusionsToTTL(exclusions, loadedTTLCeilingMs, now);
83
112
  exclusions = deduplicate(exclusions);
113
+ if (shortened) schedulePersist();
84
114
  }
85
115
  } catch (error) {
86
116
  if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
@@ -175,6 +205,18 @@ export function isExcluded(modelId: string, provider: string): boolean {
175
205
  return exclusions.some((entry) => entryMatches(entry, modelId, provider, Date.now()));
176
206
  }
177
207
 
208
+ /**
209
+ * Return the active exclusion matching a full model id, if any.
210
+ *
211
+ * The caller uses this for hard-fail diagnostics; fallback filtering should
212
+ * continue to use {@link filterFallbackCandidates}.
213
+ */
214
+ export function findModelExclusion(fullId: string, now = Date.now()): Readonly<ModelExclusion> | undefined {
215
+ ensureLoaded();
216
+ const { provider, modelId } = parseModelKey(fullId);
217
+ return exclusions.find((entry) => entryMatches(entry, modelId, provider, now));
218
+ }
219
+
178
220
  /**
179
221
  * Number of live (non-expired) exclusions.
180
222
  */
@@ -205,7 +247,10 @@ export function parseModelKey(fullId: string): { provider?: string; modelId: str
205
247
  * Filter a list of candidate fullIds, removing excluded models/providers and
206
248
  * duplicates while preserving order.
207
249
  */
208
- export function filterFallbackCandidates(candidates: string[], opts?: { now?: number }): string[] {
250
+ export function filterFallbackCandidates(candidates: string[], opts?: {
251
+ now?: number;
252
+ onExcluded?: (candidate: string, exclusion: Readonly<ModelExclusion>) => void;
253
+ }): string[] {
209
254
  ensureLoaded();
210
255
  const timestamp = opts?.now ?? Date.now();
211
256
  const seen = new Set<string>();
@@ -213,8 +258,11 @@ export function filterFallbackCandidates(candidates: string[], opts?: { now?: nu
213
258
  for (const raw of candidates) {
214
259
  if (!raw || seen.has(raw)) continue;
215
260
  const { provider: candidateProvider, modelId: candidateModelId } = parseModelKey(raw);
216
- const excluded = exclusions.some((entry) => entryMatches(entry, candidateModelId, candidateProvider, timestamp));
217
- if (excluded) continue;
261
+ const exclusion = exclusions.find((entry) => entryMatches(entry, candidateModelId, candidateProvider, timestamp));
262
+ if (exclusion) {
263
+ opts?.onExcluded?.(raw, exclusion);
264
+ continue;
265
+ }
218
266
  seen.add(raw);
219
267
  filtered.push(raw);
220
268
  }
@@ -241,3 +289,17 @@ function prune(items: ModelExclusion[], now: number): void {
241
289
  }
242
290
  items.length = write;
243
291
  }
292
+
293
+ function shortenExclusionsToTTL(items: ModelExclusion[], ttlMs: number, now: number): boolean {
294
+ let changed = false;
295
+ for (const entry of items) {
296
+ const configuredExpiry = entry.recordedAt + ttlMs;
297
+ if (entry.expiresAt > configuredExpiry) {
298
+ entry.expiresAt = configuredExpiry;
299
+ changed = true;
300
+ }
301
+ }
302
+ const previousLength = items.length;
303
+ prune(items, now);
304
+ return changed || items.length !== previousLength;
305
+ }
@@ -1,7 +1,8 @@
1
1
  import { splitKnownThinkingSuffix, type ModelInfo as AvailableModelInfo } from "../../shared/model-info.ts";
2
2
  import type { Usage } from "../../shared/types.ts";
3
- import { filterFallbackCandidates, parseModelKey, recordModelFailure } from "./model-exclusions.ts";
3
+ import { filterFallbackCandidates, findModelExclusion, parseModelKey, recordModelFailure } from "./model-exclusions.ts";
4
4
  import { checkModelScope, type ModelScopeCheckRule, type ModelScopeViolation, type ModelSource } from "./model-scope.ts";
5
+ import { redactSecretValues } from "./permissions.ts";
5
6
 
6
7
  export type { AvailableModelInfo };
7
8
 
@@ -23,7 +24,12 @@ export function formatSubagentModelVerificationError(expectedModel: string, obse
23
24
  const observedBase = splitThinkingSuffix(observedModel).baseModel;
24
25
  if (expectedBase === observedBase) return undefined;
25
26
  const expectedEntry = availableModels.find((entry) => entry.fullId === expectedBase);
26
- if (expectedEntry && expectedEntry.id === observedBase) return undefined;
27
+ if (expectedEntry) {
28
+ if (expectedEntry.id === observedBase) return undefined;
29
+ const expectedIdLeaf = expectedEntry.id.slice(expectedEntry.id.lastIndexOf("/") + 1);
30
+ const expectedFullIdLeaf = expectedEntry.fullId.slice(expectedEntry.fullId.lastIndexOf("/") + 1);
31
+ if (expectedIdLeaf === observedBase || expectedFullIdLeaf === observedBase) return undefined;
32
+ }
27
33
  return `model_verification_failed: child reported a different model than the launch candidate. Expected '${expectedModel}' but observed '${observedModel}'.`;
28
34
  }
29
35
 
@@ -278,6 +284,14 @@ function enforceModelScopes(
278
284
  for (const violation of violations) (onWarn ?? defaultScopeWarn)(violation);
279
285
  }
280
286
 
287
+ function throwForExplicitModelExclusion(model: string): void {
288
+ const exclusion = findModelExclusion(model);
289
+ if (!exclusion) return;
290
+ const reason = redactSecretValues((exclusion.reason ?? "runtime-failure").replace(/[\u0000-\u001f\u007f]+/g, " ")).slice(0, 240);
291
+ const expiry = Number.isFinite(exclusion.expiresAt) ? `; expires: ${new Date(exclusion.expiresAt).toISOString()}` : "";
292
+ throw new Error(`Requested subagent model '${model}' is excluded and cannot be replaced by a fallback (reason: ${reason}${expiry}).`);
293
+ }
294
+
281
295
  /**
282
296
  * Resolve the `--model` override passed to a spawned subagent.
283
297
  *
@@ -312,6 +326,9 @@ export function resolveSubagentModelOverride(
312
326
  } else {
313
327
  resolved = resolveRequiredSubagentModelCandidate(explicit, availableModels, preferredProvider);
314
328
  }
329
+ if (resolved && explicit !== undefined && options?.source === "explicit") {
330
+ throwForExplicitModelExclusion(resolved);
331
+ }
315
332
  if (resolved && options?.scope) {
316
333
  const source: ModelSource = explicit === undefined ? "inherited" : (options.source ?? "inherited");
317
334
  enforceModelScopes(resolved, options.scope, source, options.onWarn);
@@ -325,14 +342,15 @@ export function resolveEffectiveSubagentModel(
325
342
  parentModel: ParentModel | undefined,
326
343
  availableModels: AvailableModelInfo[] | undefined,
327
344
  preferredProvider?: string,
328
- options?: Omit<ResolveSubagentModelOverrideOptions, "source">,
345
+ options?: ResolveSubagentModelOverrideOptions,
329
346
  ): string | undefined {
347
+ const source = options?.source ?? (explicitModel !== undefined ? "explicit" : "inherited");
330
348
  const resolved = resolveSubagentModelOverride(
331
349
  explicitModel ?? agentModel,
332
350
  parentModel,
333
351
  availableModels,
334
352
  preferredProvider,
335
- { ...options, source: explicitModel !== undefined ? "explicit" : "inherited" },
353
+ { ...options, source },
336
354
  );
337
355
  if (resolved || explicitModel === undefined) return resolved;
338
356
  return resolveSubagentModelOverride(
@@ -340,7 +358,7 @@ export function resolveEffectiveSubagentModel(
340
358
  parentModel,
341
359
  availableModels,
342
360
  preferredProvider,
343
- { ...options, source: "inherited" },
361
+ { ...options, source: options?.source ?? "inherited" },
344
362
  );
345
363
  }
346
364
 
@@ -394,7 +412,12 @@ export function buildModelCandidates(
394
412
  seen.add(normalized);
395
413
  candidates.push(normalized);
396
414
  }
397
- return filterFallbackCandidates(candidates);
415
+ return filterFallbackCandidates(candidates, {
416
+ onExcluded(candidate, exclusion) {
417
+ const reason = redactSecretValues((exclusion.reason ?? "runtime-failure").replace(/[\u0000-\u001f\u007f]+/g, " ")).slice(0, 240);
418
+ console.warn(`[pi-subagents] Skipping model '${candidate}' due to a cached exclusion (reason: ${reason}; expires: ${new Date(exclusion.expiresAt).toISOString()}).`);
419
+ },
420
+ });
398
421
  }
399
422
 
400
423
  const RETRYABLE_MODEL_FAILURE_PATTERNS = [
@@ -419,6 +442,7 @@ const RETRYABLE_MODEL_FAILURE_PATTERNS = [
419
442
  /overloaded/i,
420
443
  /service unavailable/i,
421
444
  /temporar(?:ily)? unavailable/i,
445
+ /connection\s+(?:error|reset|closed|aborted)/i,
422
446
  /connection refused/i,
423
447
  /fetch failed/i,
424
448
  /network error/i,
@@ -427,9 +451,11 @@ const RETRYABLE_MODEL_FAILURE_PATTERNS = [
427
451
  /upstream/i,
428
452
  /timed? out/i,
429
453
  /timeout/i,
454
+ /\b500\b/,
430
455
  /\b502\b/,
431
456
  /\b503\b/,
432
457
  /\b504\b/,
458
+ /internal server error/i,
433
459
  /cold.?start/i,
434
460
  /empty response/i,
435
461
  /no output/i,
@@ -451,6 +477,21 @@ export function isRetryableModelFailure(error: string | undefined): boolean {
451
477
  return RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(error));
452
478
  }
453
479
 
480
+ function messageError(message: unknown): string | undefined {
481
+ if (!message || typeof message !== "object") return undefined;
482
+ const value = (message as { errorMessage?: unknown }).errorMessage;
483
+ return typeof value === "string" ? value : undefined;
484
+ }
485
+
486
+ export function isRetryableModelFailureAttempt(input: { error: string | undefined; messages?: readonly unknown[]; toolCount?: number }): boolean {
487
+ if (!isRetryableModelFailure(input.error)) return false;
488
+ if ((input.toolCount ?? 0) > 0) return false;
489
+ if (input.error === "Subagent produced no output (possible model cold-start or empty response)." || /^Subagent produced no output after terminal assistant stopReason "[^"]+"\.$/.test(input.error ?? "")) return true;
490
+ if ((input.toolCount ?? 0) === 0 && (input.messages?.length ?? 0) === 0) return true;
491
+ const error = input.error?.trim();
492
+ return Boolean(error && input.messages?.some((message) => messageError(message)?.trim() === error));
493
+ }
494
+
454
495
  export function recordRetryableModelFailure(model: string | undefined, error: string | undefined): void {
455
496
  if (!model || !isRetryableModelFailure(error)) return;
456
497
  const { provider, modelId } = parseModelKey(model);
@@ -9,8 +9,13 @@ const MAX_TRACKED_PATHS = 500;
9
9
  const MAX_HASH_BYTES = 1024 * 1024;
10
10
  const MAX_TIMEOUT_FILES = 20;
11
11
 
12
+ function gitArguments(args: string[]): string[] {
13
+ // Mutation evidence must not block child startup on a stale fsmonitor daemon.
14
+ return ["-c", "core.fsmonitor=false", ...args];
15
+ }
16
+
12
17
  function gitOutput(cwd: string, args: string[], maxBuffer = MAX_HASH_BYTES): string {
13
- return execFileSync("git", args, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], maxBuffer });
18
+ return execFileSync("git", gitArguments(args), { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], maxBuffer });
14
19
  }
15
20
 
16
21
  function splitNul(output: string): string[] {
@@ -21,7 +26,7 @@ function hashLargeDiff(cwd: string, relativePath: string): string {
21
26
  const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tracked-diff-"));
22
27
  const diffPath = path.join(tempDir, "diff.patch");
23
28
  try {
24
- execFileSync("git", ["diff", "--no-ext-diff", "--binary", `--output=${diffPath}`, "HEAD", "--", relativePath], { cwd, stdio: "ignore" });
29
+ execFileSync("git", gitArguments(["diff", "--no-ext-diff", "--binary", `--output=${diffPath}`, "HEAD", "--", relativePath]), { cwd, stdio: "ignore" });
25
30
  const hash = createHash("sha256");
26
31
  const buffer = Buffer.allocUnsafe(64 * 1024);
27
32
  const fd = fs.openSync(diffPath, "r");
@@ -199,8 +199,10 @@ function sanitizeTokenUsage(value: unknown): NestedRunSummary["totalTokens"] | u
199
199
  const input = clampNumber(raw.input);
200
200
  const output = clampNumber(raw.output);
201
201
  const total = clampNumber(raw.total);
202
+ const window = clampNumber(raw.window);
203
+ const windowPeak = clampNumber(raw.windowPeak);
202
204
  return input !== undefined && output !== undefined && total !== undefined
203
- ? { input, output, total }
205
+ ? { input, output, total, ...(window !== undefined ? { window } : {}), ...(windowPeak !== undefined ? { windowPeak } : {}) }
204
206
  : undefined;
205
207
  }
206
208
 
@@ -284,7 +286,7 @@ function sanitizeTurnBudget(value: unknown): TurnBudgetState | undefined {
284
286
  }
285
287
 
286
288
  function sanitizeState(value: unknown, fallback: NestedRunState): NestedRunState {
287
- return value === "queued" || value === "running" || value === "complete" || value === "failed" || value === "paused" || value === "stopped"
289
+ return value === "queued" || value === "running" || value === "complete" || value === "failed" || value === "partial" || value === "paused" || value === "stopped"
288
290
  ? value
289
291
  : fallback;
290
292
  }
@@ -304,6 +306,7 @@ function sanitizeStep(input: unknown, depth: number): NestedStepSummary | undefi
304
306
  status,
305
307
  ...(model ? { model } : {}),
306
308
  ...(thinking ? { thinking } : {}),
309
+ ...(stringValue(raw.sessionName, 256) ? { sessionName: stringValue(raw.sessionName, 256) } : {}),
307
310
  ...(stringValue(raw.sessionFile, 2048) ? { sessionFile: stringValue(raw.sessionFile, 2048) } : {}),
308
311
  ...(raw.activityState === "active_long_running" || raw.activityState === "needs_attention" ? { activityState: raw.activityState } : {}),
309
312
  ...(clampNumber(raw.lastActivityAt) !== undefined ? { lastActivityAt: clampNumber(raw.lastActivityAt) } : {}),
@@ -344,6 +347,7 @@ export function sanitizeSummary(input: unknown, depth = 0): NestedRunSummary | u
344
347
  depth: Math.min(Math.max(0, clampNumber(raw.depth) ?? 0), MAX_DEPTH),
345
348
  path: pathParts,
346
349
  state: sanitizeState(raw.state, "running"),
350
+ ...(stringValue(raw.sessionName, 256) ? { sessionName: stringValue(raw.sessionName, 256) } : {}),
347
351
  ...(stringValue(raw.model) ? { model: stringValue(raw.model) } : {}),
348
352
  ...(THINKING_LEVELS.find((level) => level === raw.thinking) ? { thinking: THINKING_LEVELS.find((level) => level === raw.thinking) } : {}),
349
353
  ...(stringValue(raw.asyncDir, 2048) ? { asyncDir: stringValue(raw.asyncDir, 2048) } : {}),
@@ -434,7 +438,7 @@ export function parseNestedEventRecords(content: string, route: NestedRoute): Ne
434
438
  }
435
439
 
436
440
  function terminal(state: NestedRunState): boolean {
437
- return state === "complete" || state === "failed" || state === "paused" || state === "stopped";
441
+ return state === "complete" || state === "failed" || state === "partial" || state === "paused" || state === "stopped";
438
442
  }
439
443
 
440
444
  function mergeBoundedChildren(existing: NestedRunSummary[] | undefined, incoming: NestedRunSummary[] | undefined): NestedRunSummary[] | undefined {
@@ -1003,6 +1007,7 @@ export function nestedSummaryFromAsyncStatus(status: AsyncStatus, asyncDir: stri
1003
1007
  mode: status.mode ?? fallback.mode,
1004
1008
  ...(status.steps?.length === 1 && status.steps[0]?.model ? { model: status.steps[0].model } : {}),
1005
1009
  ...(status.steps?.length === 1 && status.steps[0]?.thinking ? { thinking: status.steps[0].thinking } : {}),
1010
+ ...(status.steps?.length === 1 && status.steps[0]?.sessionName ? { sessionName: status.steps[0].sessionName } : {}),
1006
1011
  ...(status.processTerminal ? { processTerminal: sanitizeProcessTerminal(status.processTerminal, { runId: status.runId || fallback.id, runnerProcessInstanceId: status.processTerminal.runnerProcessInstanceId }, `${asyncDir}/status.json`) } : {}),
1007
1012
  ...(status.launchResolvedExtensions ? { launchResolvedExtensions: status.launchResolvedExtensions } : {}),
1008
1013
  ...runtimeAcknowledgedEntry(status.runtimeAcknowledgedExtensions),
@@ -1033,6 +1038,7 @@ export function nestedSummaryFromAsyncStatus(status: AsyncStatus, asyncDir: stri
1033
1038
  ...(status.sessionFile ? { sessionFile: status.sessionFile } : {}),
1034
1039
  ...(status.steps?.length ? { steps: status.steps.map((step, index) => ({
1035
1040
  agent: step.agent,
1041
+ ...(step.sessionName ? { sessionName: step.sessionName } : {}),
1036
1042
  status: step.status,
1037
1043
  ...(step.model ? { model: step.model } : {}),
1038
1044
  ...(step.thinking ? { thinking: step.thinking } : {}),
@@ -1,6 +1,6 @@
1
- import { formatDuration, formatModelThinking, formatTokens, shortenPath } from "../../shared/formatters.ts";
1
+ import { formatDuration, formatModelThinking, formatTokenUsage, shortenPath } from "../../shared/formatters.ts";
2
2
  import { formatActivityLabel } from "../../shared/status-format.ts";
3
- import type { ActivityState, NestedRunSummary, NestedStepSummary } from "../../shared/types.ts";
3
+ import type { ActivityState, NestedRunSummary } from "../../shared/types.ts";
4
4
 
5
5
  export interface NestedRunCounts {
6
6
  total: number;
@@ -8,13 +8,14 @@ export interface NestedRunCounts {
8
8
  paused: number;
9
9
  complete: number;
10
10
  failed: number;
11
+ partial: number;
11
12
  rejected: number;
12
13
  stopped: number;
13
14
  queued: number;
14
15
  }
15
16
 
16
17
  export function countNestedRuns(children: NestedRunSummary[] | undefined): NestedRunCounts {
17
- const counts: NestedRunCounts = { total: 0, running: 0, paused: 0, complete: 0, failed: 0, rejected: 0, stopped: 0, queued: 0 };
18
+ const counts: NestedRunCounts = { total: 0, running: 0, paused: 0, complete: 0, failed: 0, partial: 0, rejected: 0, stopped: 0, queued: 0 };
18
19
  for (const child of children ?? []) {
19
20
  counts.total++;
20
21
  counts[child.state]++;
@@ -24,6 +25,7 @@ export function countNestedRuns(children: NestedRunSummary[] | undefined): Neste
24
25
  counts.paused += nested.paused;
25
26
  counts.complete += nested.complete;
26
27
  counts.failed += nested.failed;
28
+ counts.partial += nested.partial;
27
29
  counts.rejected += nested.rejected;
28
30
  counts.stopped += nested.stopped;
29
31
  counts.queued += nested.queued;
@@ -38,6 +40,7 @@ export function formatNestedAggregate(children: NestedRunSummary[] | undefined):
38
40
  counts.running > 0 ? `${counts.running} running` : "",
39
41
  counts.paused > 0 ? `${counts.paused} paused` : "",
40
42
  counts.failed > 0 ? `${counts.failed} failed` : "",
43
+ counts.partial > 0 ? `${counts.partial} partial` : "",
41
44
  counts.rejected > 0 ? `${counts.rejected} rejected` : "",
42
45
  counts.stopped > 0 ? `${counts.stopped} stopped` : "",
43
46
  counts.complete > 0 ? `${counts.complete} complete` : "",
@@ -47,6 +50,7 @@ export function formatNestedAggregate(children: NestedRunSummary[] | undefined):
47
50
  }
48
51
 
49
52
  function nestedRunLabel(run: NestedRunSummary): string {
53
+ if (run.sessionName?.trim()) return run.sessionName.trim();
50
54
  if (run.agent) return run.agent;
51
55
  if (run.agents?.length) return run.agents.length === 1 ? run.agents[0]! : `${run.agents.slice(0, 2).join(", ")}${run.agents.length > 2 ? ` +${run.agents.length - 2}` : ""}`;
52
56
  return run.id;
@@ -68,7 +72,7 @@ function formatNestedActivity(input: {
68
72
  if (input.currentPath) facts.push(shortenPath(input.currentPath));
69
73
  if (input.turnCount !== undefined) facts.push(`${input.turnCount} turns`);
70
74
  if (input.toolCount !== undefined) facts.push(`${input.toolCount} tools`);
71
- if (input.totalTokens) facts.push(`${formatTokens(input.totalTokens.total)} tok`);
75
+ if (input.totalTokens) facts.push(formatTokenUsage(input.totalTokens));
72
76
  const activity = formatActivityLabel(input.lastActivityAt, input.activityState as ActivityState | undefined);
73
77
  return activity || facts.length ? [activity, ...facts].filter(Boolean).join(" | ") : undefined;
74
78
  }
@@ -103,7 +107,7 @@ function formatNestedRunLines(children: NestedRunSummary[] | undefined, options:
103
107
  if (lines.length >= options.maxLines) return;
104
108
  const stepActivity = step.status === "running" ? formatNestedActivity(step) : undefined;
105
109
  const stepModelThinking = formatModelThinking(step.model, step.thinking);
106
- lines.push(`${indent} ${stepIndex + 1}. ${step.agent} ${step.status}${stepModelThinking ? ` | ${stepModelThinking}` : ""}${stepActivity ? ` | ${stepActivity}` : ""}${step.error ? ` | error: ${step.error}` : ""}`);
110
+ lines.push(`${indent} ${stepIndex + 1}. ${step.sessionName?.trim() || step.agent} ${step.status}${stepModelThinking ? ` | ${stepModelThinking}` : ""}${stepActivity ? ` | ${stepActivity}` : ""}${step.error ? ` | error: ${step.error}` : ""}`);
107
111
  append(step.children, depth + 1, `${indent} `);
108
112
  }
109
113
  append(child.children, depth + 1, `${indent} `);