@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
@@ -0,0 +1,121 @@
1
+ import type { AsyncStatus, WorkflowChildSummaryV1 } from "../shared/types.ts";
2
+ import type { WorkflowScriptChildResult, WorkflowScriptTraceEntry } from "./scripted-workflow.ts";
3
+
4
+ const KEY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
5
+ const TERMINAL_STATES = new Set(["completed", "failed", "paused", "stopped", "rejected", "detached"]);
6
+ const MAX_REQUIRED_ID_BYTES = 4_096;
7
+
8
+ function bounded(value: unknown, maxBytes: number): string | undefined {
9
+ if (typeof value !== "string" || !value.trim() || Buffer.byteLength(value, "utf8") > maxBytes) return undefined;
10
+ return value;
11
+ }
12
+
13
+ function requiredId(value: string, label: string): string {
14
+ const id = bounded(value, MAX_REQUIRED_ID_BYTES);
15
+ if (!id) throw new Error(`${label} must be a non-empty identifier of at most ${MAX_REQUIRED_ID_BYTES} UTF-8 bytes.`);
16
+ return id;
17
+ }
18
+
19
+ export function workflowChildSummary(input: {
20
+ parentToolCallId: string;
21
+ workflowRunId: string;
22
+ workflowState: WorkflowChildSummaryV1["workflowState"];
23
+ inventoryComplete: boolean;
24
+ trace?: WorkflowScriptTraceEntry[];
25
+ children?: WorkflowScriptChildResult[];
26
+ steps?: NonNullable<AsyncStatus["steps"]>;
27
+ }): WorkflowChildSummaryV1 {
28
+ const rows = new Map<string, WorkflowChildSummaryV1["children"][number]>();
29
+ for (const entry of input.trace ?? []) {
30
+ if (entry.operation !== "run" || !KEY_PATTERN.test(entry.key)) continue;
31
+ const previous = rows.get(entry.key);
32
+ const state = entry.state === "completed" ? "completed"
33
+ : entry.state === "failed" ? "failed"
34
+ : entry.state === "stopped" ? "stopped"
35
+ : entry.state === "detached" ? "detached"
36
+ : previous?.state ?? "running";
37
+ rows.set(entry.key, {
38
+ childId: entry.key,
39
+ state,
40
+ ...(bounded(entry.runId, 256) ? { runId: bounded(entry.runId, 256) } : {}),
41
+ ...(previous?.agent ? { agent: previous.agent } : {}),
42
+ ...(previous?.sessionName ? { sessionName: previous.sessionName } : {}),
43
+ ...(previous?.model ? { model: previous.model } : {}),
44
+ ...(previous?.thinking ? { thinking: previous.thinking } : {}),
45
+ });
46
+ }
47
+ for (const step of input.steps ?? []) {
48
+ const key = step.workflowKey;
49
+ if (!key || !KEY_PATTERN.test(key)) continue;
50
+ const state = step.status === "complete" || step.status === "completed" ? "completed"
51
+ : step.status === "failed" ? "failed"
52
+ : step.status === "paused" ? "paused"
53
+ : step.status === "stopped" ? "stopped"
54
+ : step.status === "rejected" ? "rejected"
55
+ : step.status === "pending" ? "pending" : "running";
56
+ const launchResolved = step.async !== undefined || step.sessionFile !== undefined || step.runId !== undefined || step.model !== undefined;
57
+ rows.set(key, {
58
+ childId: key,
59
+ state,
60
+ ...(bounded(step.runId, 256) ? { runId: bounded(step.runId, 256) } : {}),
61
+ ...(launchResolved && bounded(step.agent, 256) ? { agent: bounded(step.agent, 256) } : {}),
62
+ ...(bounded(step.sessionName, 256) ? { sessionName: bounded(step.sessionName, 256) } : {}),
63
+ ...(bounded(step.model, 256) ? { model: bounded(step.model, 256) } : {}),
64
+ ...(bounded(step.thinking, 32) ? { thinking: bounded(step.thinking, 32) } : {}),
65
+ });
66
+ }
67
+ for (const child of input.children ?? []) {
68
+ if (!KEY_PATTERN.test(child.key)) continue;
69
+ const result = Array.isArray(child.results) ? child.results.find((value) => value && typeof value === "object") as Record<string, unknown> | undefined : undefined;
70
+ const state = child.detached ? "detached" : child.stopped ? "stopped" : child.interrupted ? "paused" : child.ok ? "completed" : result?.acceptance && typeof result.acceptance === "object" && (result.acceptance as { status?: unknown }).status === "rejected" ? "rejected" : "failed";
71
+ rows.set(child.key, {
72
+ childId: child.key,
73
+ state,
74
+ ...(bounded(child.runId, 256) ? { runId: bounded(child.runId, 256) } : {}),
75
+ ...(bounded(child.agent, 256) ? { agent: bounded(child.agent, 256) } : {}),
76
+ ...(bounded(result?.sessionName, 256) ? { sessionName: bounded(result?.sessionName, 256) } : {}),
77
+ ...(bounded(result?.model, 256) ? { model: bounded(result?.model, 256) } : {}),
78
+ ...(bounded(result?.thinking, 32) ? { thinking: bounded(result?.thinking, 32) } : {}),
79
+ });
80
+ }
81
+ if (input.inventoryComplete) {
82
+ for (const [key, row] of rows) {
83
+ if (!TERMINAL_STATES.has(row.state)) rows.set(key, { ...row, state: input.workflowState === "stopped" ? "stopped" : "failed" });
84
+ }
85
+ }
86
+ return {
87
+ version: 1,
88
+ parentToolCallId: requiredId(input.parentToolCallId, "parentToolCallId"),
89
+ workflowRunId: requiredId(input.workflowRunId, "workflowRunId"),
90
+ inventoryComplete: input.inventoryComplete,
91
+ workflowState: input.workflowState,
92
+ children: [...rows.values()],
93
+ };
94
+ }
95
+
96
+ export function parseWorkflowChildSummary(value: unknown): WorkflowChildSummaryV1 | undefined {
97
+ if (value === undefined) return undefined;
98
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("workflowChildren must be an object.");
99
+ const input = value as Record<string, unknown>;
100
+ const allowed = new Set(["version", "parentToolCallId", "workflowRunId", "inventoryComplete", "workflowState", "children"]);
101
+ if (Object.keys(input).some((key) => !allowed.has(key))) throw new Error("workflowChildren has unsupported fields.");
102
+ if (input.version !== 1 || typeof input.inventoryComplete !== "boolean" || !Array.isArray(input.children)) throw new Error("workflowChildren is invalid.");
103
+ const workflowState = input.workflowState;
104
+ if (workflowState !== "queued" && workflowState !== "running" && workflowState !== "completed" && workflowState !== "failed" && workflowState !== "paused" && workflowState !== "stopped") throw new Error("workflowChildren.workflowState is invalid.");
105
+ const children = input.children.map((row): WorkflowChildSummaryV1["children"][number] => {
106
+ if (!row || typeof row !== "object" || Array.isArray(row)) throw new Error("workflowChildren child row is invalid.");
107
+ const child = row as Record<string, unknown>;
108
+ if (Object.keys(child).some((key) => !["childId", "runId", "agent", "sessionName", "model", "thinking", "state"].includes(key))) throw new Error("workflowChildren child row has unsupported fields.");
109
+ if (typeof child.childId !== "string" || !KEY_PATTERN.test(child.childId)) throw new Error("workflowChildren childId is invalid.");
110
+ const state = child.state;
111
+ if (state !== "pending" && state !== "running" && state !== "completed" && state !== "failed" && state !== "paused" && state !== "stopped" && state !== "rejected" && state !== "detached") throw new Error("workflowChildren child state is invalid.");
112
+ for (const [field, maxBytes] of [["runId", 256], ["agent", 256], ["sessionName", 256], ["model", 256], ["thinking", 32]] as const) {
113
+ if (child[field] !== undefined && bounded(child[field], maxBytes) === undefined) throw new Error(`workflowChildren child ${field} is invalid.`);
114
+ }
115
+ return { childId: child.childId, state, ...(child.runId ? { runId: child.runId as string } : {}), ...(child.agent ? { agent: child.agent as string } : {}), ...(child.sessionName ? { sessionName: child.sessionName as string } : {}), ...(child.model ? { model: child.model as string } : {}), ...(child.thinking ? { thinking: child.thinking as string } : {}) };
116
+ });
117
+ if (new Set(children.map((child) => child.childId)).size !== children.length) throw new Error("workflowChildren has duplicate childId values.");
118
+ if (typeof input.parentToolCallId !== "string") throw new Error("workflowChildren.parentToolCallId is invalid.");
119
+ if (typeof input.workflowRunId !== "string") throw new Error("workflowChildren.workflowRunId is invalid.");
120
+ return { version: 1, parentToolCallId: requiredId(input.parentToolCallId, "parentToolCallId"), workflowRunId: requiredId(input.workflowRunId, "workflowRunId"), inventoryComplete: input.inventoryComplete, workflowState, children };
121
+ }
@@ -0,0 +1,270 @@
1
+ import type { WorkflowPreflightLaneV1, WorkflowPreflightV1 } from "../shared/types.ts";
2
+
3
+ export const WORKFLOW_PREFLIGHT_VERSION = 1 as const;
4
+ export const WORKFLOW_PREFLIGHT_MAX_LANES = 64;
5
+ export const WORKFLOW_PREFLIGHT_MAX_STRING_LENGTH = 256;
6
+ export const WORKFLOW_PREFLIGHT_MAX_CLAIMS = 16;
7
+ export const WORKFLOW_PREFLIGHT_MAX_DEPTH = 3;
8
+ export const WORKFLOW_PREFLIGHT_MAX_BYTES = 16 * 1024;
9
+ export const WORKFLOW_PREFLIGHT_MAX_WARNINGS = 16;
10
+
11
+ const WORKFLOW_KEY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
12
+ const PREFLIGHT_FIELDS = new Set(["version", "coverage", "lanes"]);
13
+ const LANE_FIELDS = new Set(["key", "mode", "decision", "claims", "expectedOutput", "independence"]);
14
+ const PREFLIGHT_MODES = new Set<WorkflowPreflightLaneV1["mode"]>(["mutation", "review", "scout", "gate"]);
15
+
16
+ type WorkflowTraceLike = {
17
+ operation: string;
18
+ key: string;
19
+ phase?: string;
20
+ generatedLaneKey?: string;
21
+ warning?: string;
22
+ };
23
+
24
+ export interface WorkflowPreflightValidationResult {
25
+ ok: boolean;
26
+ preflight?: WorkflowPreflightV1;
27
+ error?: string;
28
+ }
29
+
30
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
31
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
32
+ const prototype = Object.getPrototypeOf(value);
33
+ return prototype === Object.prototype || prototype === null;
34
+ }
35
+
36
+ function assertPlainObject(value: unknown, path: string): asserts value is Record<string, unknown> {
37
+ if (!isPlainObject(value)) throw new Error(`${path} must be a plain JSON object.`);
38
+ if (Object.getOwnPropertySymbols(value).length > 0) throw new Error(`${path} must not contain symbol keys.`);
39
+ for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
40
+ if (!descriptor.enumerable || !("value" in descriptor)) throw new Error(`${path}.${key} must be an enumerable data property.`);
41
+ }
42
+ }
43
+
44
+ function assertKnownFields(value: Record<string, unknown>, allowed: ReadonlySet<string>, path: string): void {
45
+ for (const key of Object.keys(value)) {
46
+ if (!allowed.has(key)) throw new Error(`${path} contains unsupported field '${key}'.`);
47
+ }
48
+ }
49
+
50
+ function normalizeDisplayString(value: unknown, path: string): string {
51
+ if (typeof value !== "string") throw new Error(`${path} must be a string.`);
52
+ const normalized = value
53
+ .replace(/[\u0000-\u001f\u007f]/g, " ")
54
+ .replace(/\s+/g, " ")
55
+ .trim();
56
+ if (!normalized) throw new Error(`${path} must be a non-empty string.`);
57
+ if (normalized.length > WORKFLOW_PREFLIGHT_MAX_STRING_LENGTH) {
58
+ throw new Error(`${path} exceeds the maximum length of ${WORKFLOW_PREFLIGHT_MAX_STRING_LENGTH}.`);
59
+ }
60
+ return normalized;
61
+ }
62
+
63
+ function normalizeLane(value: unknown, index: number): WorkflowPreflightLaneV1 {
64
+ const path = `preflight.lanes[${index}]`;
65
+ assertPlainObject(value, path);
66
+ assertKnownFields(value, LANE_FIELDS, path);
67
+ const key = normalizeDisplayString(value.key, `${path}.key`);
68
+ if (!WORKFLOW_KEY_PATTERN.test(key)) throw new Error(`${path}.key must be 1-128 characters using letters, numbers, '.', '_' or '-', and start with a letter or number.`);
69
+ let mode: WorkflowPreflightLaneV1["mode"];
70
+ if (value.mode !== undefined) {
71
+ if (typeof value.mode !== "string" || !PREFLIGHT_MODES.has(value.mode as WorkflowPreflightLaneV1["mode"])) {
72
+ throw new Error(`${path}.mode must be one of: mutation, review, scout, gate.`);
73
+ }
74
+ mode = value.mode as WorkflowPreflightLaneV1["mode"];
75
+ }
76
+ let claims: string[] | undefined;
77
+ if (value.claims !== undefined) {
78
+ if (!Array.isArray(value.claims)) throw new Error(`${path}.claims must be an array of strings.`);
79
+ if (value.claims.length > WORKFLOW_PREFLIGHT_MAX_CLAIMS) throw new Error(`${path}.claims supports at most ${WORKFLOW_PREFLIGHT_MAX_CLAIMS} entries.`);
80
+ claims = value.claims.map((claim, claimIndex) => normalizeDisplayString(claim, `${path}.claims[${claimIndex}]`));
81
+ for (let claimIndex = 0; claimIndex < value.claims.length; claimIndex += 1) {
82
+ if (!Object.prototype.hasOwnProperty.call(value.claims, claimIndex)) throw new Error(`${path}.claims must not contain sparse arrays.`);
83
+ }
84
+ }
85
+ return {
86
+ key,
87
+ ...(mode ? { mode } : {}),
88
+ ...(value.decision !== undefined ? { decision: normalizeDisplayString(value.decision, `${path}.decision`) } : {}),
89
+ ...(claims ? { claims } : {}),
90
+ ...(value.expectedOutput !== undefined ? { expectedOutput: normalizeDisplayString(value.expectedOutput, `${path}.expectedOutput`) } : {}),
91
+ ...(value.independence !== undefined ? { independence: normalizeDisplayString(value.independence, `${path}.independence`) } : {}),
92
+ };
93
+ }
94
+
95
+ /**
96
+ * Validate and canonicalize the explicit preflight input. This is intentionally
97
+ * independent of workflowScript parsing: callers may describe dynamic fanout
98
+ * without making the metadata a second execution graph.
99
+ */
100
+ export function normalizeWorkflowPreflight(input: unknown): WorkflowPreflightV1 | undefined {
101
+ if (input === undefined) return undefined;
102
+ assertPlainObject(input, "preflight");
103
+ assertKnownFields(input, PREFLIGHT_FIELDS, "preflight");
104
+ if (input.version !== WORKFLOW_PREFLIGHT_VERSION) throw new Error(`preflight.version must be ${WORKFLOW_PREFLIGHT_VERSION}.`);
105
+ const coverage = input.coverage === undefined ? "partial" : input.coverage;
106
+ if (coverage !== "complete" && coverage !== "partial") throw new Error("preflight.coverage must be 'complete' or 'partial'.");
107
+ if (!Array.isArray(input.lanes)) throw new Error("preflight.lanes must be an array.");
108
+ if (input.lanes.length > WORKFLOW_PREFLIGHT_MAX_LANES) throw new Error(`preflight.lanes supports at most ${WORKFLOW_PREFLIGHT_MAX_LANES} lanes.`);
109
+ for (let index = 0; index < input.lanes.length; index += 1) {
110
+ if (!Object.prototype.hasOwnProperty.call(input.lanes, index)) throw new Error("preflight.lanes must not contain sparse arrays.");
111
+ }
112
+ const lanes = input.lanes.map(normalizeLane);
113
+ const seenKeys = new Set<string>();
114
+ for (const lane of lanes) {
115
+ if (seenKeys.has(lane.key)) throw new Error(`preflight.lanes contains duplicate key '${lane.key}'.`);
116
+ seenKeys.add(lane.key);
117
+ }
118
+ const normalized = { version: WORKFLOW_PREFLIGHT_VERSION, coverage, lanes } satisfies WorkflowPreflightV1;
119
+ const depth = 1 + (lanes.length > 0 ? 1 : 0) + (lanes.some((lane) => lane.claims !== undefined) ? 1 : 0);
120
+ if (depth > WORKFLOW_PREFLIGHT_MAX_DEPTH) throw new Error(`preflight exceeds the maximum nesting depth of ${WORKFLOW_PREFLIGHT_MAX_DEPTH}.`);
121
+ const bytes = Buffer.byteLength(JSON.stringify(normalized), "utf8");
122
+ if (bytes > WORKFLOW_PREFLIGHT_MAX_BYTES) throw new Error(`preflight canonical JSON is ${bytes} bytes; maximum is ${WORKFLOW_PREFLIGHT_MAX_BYTES}.`);
123
+ return normalized;
124
+ }
125
+
126
+ export function validateWorkflowPreflight(input: unknown): WorkflowPreflightValidationResult {
127
+ try {
128
+ const preflight = normalizeWorkflowPreflight(input);
129
+ return { ok: true, ...(preflight ? { preflight } : {}) };
130
+ } catch (error) {
131
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
132
+ }
133
+ }
134
+
135
+ function warningLimit(messages: string[]): string[] {
136
+ if (messages.length <= WORKFLOW_PREFLIGHT_MAX_WARNINGS) return messages;
137
+ const omitted = messages.length - WORKFLOW_PREFLIGHT_MAX_WARNINGS + 1;
138
+ return [...messages.slice(0, WORKFLOW_PREFLIGHT_MAX_WARNINGS - 1), `Preflight advisory: ${omitted} additional mismatch warning(s) omitted.`];
139
+ }
140
+
141
+ function declaredKeys(preflight: WorkflowPreflightV1): Set<string> {
142
+ return new Set(preflight.lanes.map((lane) => lane.key));
143
+ }
144
+
145
+ /**
146
+ * Treat declared lane keys as plan roots: `lane` is the lane itself and
147
+ * `lane.stage` is a stage by convention, even without generated provenance.
148
+ */
149
+ function declaredLaneCoversWorkflowKey(entry: WorkflowTraceLike, laneKey: string): boolean {
150
+ return entry.key === laneKey || entry.key.startsWith(`${laneKey}.`);
151
+ }
152
+
153
+ function keyCoveredByDeclaredLane(entry: WorkflowTraceLike, declared: ReadonlySet<string>): boolean {
154
+ for (const laneKey of declared) if (declaredLaneCoversWorkflowKey(entry, laneKey)) return true;
155
+ return false;
156
+ }
157
+
158
+ function launchedEntries(trace: readonly WorkflowTraceLike[]): WorkflowTraceLike[] {
159
+ const entries: WorkflowTraceLike[] = [];
160
+ const seen = new Set<string>();
161
+ for (const entry of trace) {
162
+ if (entry.operation !== "run" || entry.phase === "auto-resume" || seen.has(entry.key)) continue;
163
+ seen.add(entry.key);
164
+ entries.push(entry);
165
+ }
166
+ return entries;
167
+ }
168
+
169
+ function undeclaredWarning(key: string): string {
170
+ return `Preflight advisory: workflow key '${key}' launched without a declared lane.`;
171
+ }
172
+
173
+ function unlaunchedWarning(key: string): string {
174
+ return `Preflight advisory: declared lane '${key}' was not launched.`;
175
+ }
176
+
177
+ /** Return bounded advisory mismatch warnings; these never reject a child launch. */
178
+ export function workflowPreflightWarnings(
179
+ preflight: WorkflowPreflightV1 | undefined,
180
+ trace: readonly WorkflowTraceLike[],
181
+ options: { settled?: boolean } = {},
182
+ ): string[] {
183
+ if (!preflight) return [];
184
+ const declared = declaredKeys(preflight);
185
+ const launched = launchedEntries(trace);
186
+ const messages = launched.filter((entry) => !keyCoveredByDeclaredLane(entry, declared)).map((entry) => undeclaredWarning(entry.key));
187
+ if (options.settled === true) {
188
+ for (const lane of preflight.lanes) if (!launched.some((entry) => declaredLaneCoversWorkflowKey(entry, lane.key))) messages.push(unlaunchedWarning(lane.key));
189
+ }
190
+ return warningLimit(messages);
191
+ }
192
+
193
+ /** Attach the first undeclared-key warning to its first trace row for status/debug views. */
194
+ export function annotateWorkflowPreflightTrace<T extends WorkflowTraceLike>(trace: readonly T[], preflight: WorkflowPreflightV1 | undefined): T[] {
195
+ if (!preflight) return [...trace];
196
+ const declared = declaredKeys(preflight);
197
+ const warned = new Set<string>();
198
+ return trace.map((entry) => {
199
+ if (entry.operation !== "run" || entry.phase === "auto-resume" || keyCoveredByDeclaredLane(entry, declared) || warned.has(entry.key)) return entry;
200
+ warned.add(entry.key);
201
+ return { ...entry, warning: entry.warning ?? undeclaredWarning(entry.key) };
202
+ });
203
+ }
204
+
205
+ function laneCell(value: string | undefined): string {
206
+ return value ?? "—";
207
+ }
208
+
209
+ const WORKFLOW_PREFLIGHT_PLAN_LABEL_LENGTH = 96;
210
+
211
+ function planLaneLabel(lane: WorkflowPreflightLaneV1): string {
212
+ const value = lane.decision?.trim() || lane.key;
213
+ if (value.length <= WORKFLOW_PREFLIGHT_PLAN_LABEL_LENGTH) return value;
214
+ return `${value.slice(0, WORKFLOW_PREFLIGHT_PLAN_LABEL_LENGTH - 1).trimEnd()}…`;
215
+ }
216
+
217
+ /** Render the detailed bounded table reserved for tool output and expanded/debug views. */
218
+ export function formatWorkflowPreflight(preflight: WorkflowPreflightV1 | undefined, options: { indent?: string } = {}): string {
219
+ if (!preflight) return "";
220
+ const indent = options.indent ?? "";
221
+ const count = preflight.lanes.length;
222
+ const lines = [
223
+ `${indent}Preflight: v${preflight.version} · ${preflight.coverage} · ${count} lane${count === 1 ? "" : "s"}`,
224
+ `${indent} key | mode | decision | claims | expected output | independence`,
225
+ ];
226
+ for (const lane of preflight.lanes) {
227
+ lines.push(`${indent} ${[
228
+ lane.key,
229
+ laneCell(lane.mode),
230
+ laneCell(lane.decision),
231
+ lane.claims?.join(", ") ?? "—",
232
+ laneCell(lane.expectedOutput),
233
+ laneCell(lane.independence),
234
+ ].join(" | ")}`);
235
+ }
236
+ return lines.join("\n");
237
+ }
238
+
239
+ export function formatWorkflowPreflightSummary(preflight: WorkflowPreflightV1 | undefined): string {
240
+ if (!preflight) return "";
241
+ const keys = preflight.lanes.slice(0, 4).map((lane) => lane.key).join(", ");
242
+ const remainder = preflight.lanes.length > 4 ? `, +${preflight.lanes.length - 4}` : "";
243
+ return `preflight · ${preflight.coverage} · ${preflight.lanes.length} lane${preflight.lanes.length === 1 ? "" : "s"}${keys ? `: ${keys}${remainder}` : ""}`;
244
+ }
245
+
246
+ /** Render the operator-facing one-line plan shown in routine status views. */
247
+ export function formatWorkflowPreflightPlanSummary(preflight: WorkflowPreflightV1 | undefined, options: { indent?: string } = {}): string {
248
+ if (!preflight) return "";
249
+ const indent = options.indent ?? "";
250
+ const count = preflight.lanes.length;
251
+ const labels = count === 1
252
+ ? planLaneLabel(preflight.lanes[0]!)
253
+ : preflight.lanes.slice(0, 4).map((lane) => lane.key).join(", ") + (count > 4 ? `, +${count - 4}` : "");
254
+ return `${indent}Plan: ${count} lane${count === 1 ? "" : "s"}${labels ? ` · ${labels}` : ""}`;
255
+ }
256
+
257
+ /** Render a bounded, non-alarming warning for routine status views. */
258
+ export function formatWorkflowPreflightWarningSummary(warnings: readonly string[] | undefined, options: { indent?: string; hint?: string } = {}): string {
259
+ if (!warnings?.length) return "";
260
+ const indent = options.indent ?? "";
261
+ const hint = options.hint ?? "details available for debug";
262
+ const count = warnings.length;
263
+ return `${indent}Plan note: ${count} preflight mismatch${count === 1 ? "" : "es"} · ${hint}.`;
264
+ }
265
+
266
+ export function formatWorkflowPreflightWarnings(warnings: readonly string[] | undefined, options: { indent?: string } = {}): string {
267
+ if (!warnings?.length) return "";
268
+ const indent = options.indent ?? "";
269
+ return [`${indent}Preflight warnings:`, ...warnings.map((warning) => `${indent} - ${warning.replace(/\s+/g, " ").trim()}`)].join("\n");
270
+ }