@hassangameryt/freeflow 0.7.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (426) hide show
  1. package/.agents/plugins/marketplace.json +2 -2
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +2 -2
  4. package/.codex-plugin/plugin.json +3 -3
  5. package/.cursor-plugin/plugin.json +1 -1
  6. package/NOTICE +14 -0
  7. package/README.md +101 -159
  8. package/capabilities/cognitive-routing/SKILL.md +47 -210
  9. package/capabilities/cognitive-routing/references/coordinator.md +163 -0
  10. package/capabilities/cognitive-routing/references/worker.md +38 -0
  11. package/capabilities/compaction/SKILL.md +49 -0
  12. package/capabilities/compaction/references/summary-format.md +250 -0
  13. package/capabilities/messaging/SKILL.md +49 -0
  14. package/capabilities/task-memory/SKILL.md +87 -0
  15. package/command-surface.json +8 -52
  16. package/gemini-extension.json +1 -1
  17. package/hooks/claude/hooks.json +13 -3
  18. package/hooks/codex/hooks.json +2 -1
  19. package/hooks/shared/runtime-context.mjs +73 -83
  20. package/licenses/Apache-2.0.txt +55 -0
  21. package/package.json +42 -12
  22. package/pi-extension/README.md +41 -0
  23. package/pi-extension/dist/ask-user/ask.js +108 -0
  24. package/pi-extension/dist/ask-user/form.js +250 -0
  25. package/pi-extension/dist/ask-user/questions.js +66 -0
  26. package/pi-extension/dist/ask-user/tool.js +124 -0
  27. package/pi-extension/dist/cognitive-routing/assembler.js +417 -0
  28. package/pi-extension/dist/cognitive-routing/bootstrap.js +90 -0
  29. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/config.js +8 -6
  30. package/pi-extension/dist/cognitive-routing/economics.js +45 -0
  31. package/pi-extension/dist/cognitive-routing/event-schema.js +388 -0
  32. package/pi-extension/dist/{session-sources/events.js → cognitive-routing/event-store.js} +107 -41
  33. package/pi-extension/dist/cognitive-routing/gate.js +256 -0
  34. package/pi-extension/dist/cognitive-routing/handlers.js +901 -0
  35. package/pi-extension/dist/cognitive-routing/handoffs.js +350 -0
  36. package/pi-extension/dist/cognitive-routing/model-control.js +476 -0
  37. package/pi-extension/dist/cognitive-routing/projection.js +520 -0
  38. package/pi-extension/dist/cognitive-routing/provenance.js +83 -0
  39. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/render.js +15 -15
  40. package/pi-extension/dist/cognitive-routing/runtime.js +398 -0
  41. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/schemas.js +47 -11
  42. package/pi-extension/dist/cognitive-routing/session.js +223 -0
  43. package/pi-extension/dist/{session-sources → cognitive-routing}/sources.js +126 -87
  44. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/state.js +55 -386
  45. package/pi-extension/dist/cognitive-routing/status.js +81 -0
  46. package/pi-extension/dist/cognitive-routing/tools.js +74 -0
  47. package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/types.js +14 -11
  48. package/pi-extension/dist/compaction/carry.js +205 -0
  49. package/pi-extension/dist/compaction/config.js +24 -0
  50. package/pi-extension/dist/compaction/controller.js +494 -0
  51. package/pi-extension/dist/compaction/harness.js +93 -0
  52. package/pi-extension/dist/compaction/results.js +159 -0
  53. package/pi-extension/dist/compaction/thresholds.js +35 -0
  54. package/pi-extension/dist/compaction/tool.js +57 -0
  55. package/pi-extension/dist/host/branch.js +13 -0
  56. package/pi-extension/dist/host/canonical.js +12 -0
  57. package/pi-extension/dist/host/catalog.js +62 -0
  58. package/pi-extension/dist/host/config-validation.js +233 -0
  59. package/pi-extension/dist/host/config.js +361 -0
  60. package/pi-extension/dist/host/inbound.js +142 -0
  61. package/pi-extension/dist/host/projection-tags.js +60 -0
  62. package/pi-extension/dist/host/prompts.js +93 -0
  63. package/pi-extension/dist/{session-sources → host}/read-only-session.js +117 -1
  64. package/pi-extension/dist/{runtime → host}/request-history.js +125 -39
  65. package/pi-extension/dist/host/rows.js +25 -0
  66. package/pi-extension/dist/host/runtime-state.js +204 -0
  67. package/pi-extension/dist/host/section-keeper.js +85 -0
  68. package/pi-extension/dist/host/settings/freeflow-command.js +2323 -0
  69. package/pi-extension/dist/{settings/settings-tui.js → host/settings/settings-view.js} +205 -73
  70. package/pi-extension/dist/host/staging.js +28 -0
  71. package/pi-extension/dist/host/status.js +115 -0
  72. package/pi-extension/dist/index.js +1004 -188
  73. package/pi-extension/dist/messaging/config.js +27 -0
  74. package/pi-extension/dist/messaging/messaging.js +398 -0
  75. package/pi-extension/dist/messaging/registry.js +57 -0
  76. package/pi-extension/dist/messaging/render.js +90 -0
  77. package/pi-extension/dist/messaging/tools.js +109 -0
  78. package/pi-extension/dist/messaging/transport.js +101 -0
  79. package/pi-extension/dist/provider-support/cache/anchor.js +21 -0
  80. package/pi-extension/dist/provider-support/cache/anthropic.js +102 -0
  81. package/pi-extension/dist/provider-support/cache/health.js +73 -0
  82. package/pi-extension/dist/provider-support/cache/index.js +58 -0
  83. package/pi-extension/dist/provider-support/cache/keepalive.js +222 -0
  84. package/pi-extension/dist/provider-support/cache/monitor.js +17 -0
  85. package/pi-extension/dist/provider-support/cache/openai-responses.js +48 -0
  86. package/pi-extension/dist/provider-support/effort.js +13 -0
  87. package/pi-extension/dist/provider-support/index.js +44 -3
  88. package/pi-extension/dist/provider-support/{astra → openai}/adapter.js +46 -29
  89. package/pi-extension/dist/provider-support/{astra → openai}/history.js +10 -8
  90. package/pi-extension/dist/provider-support/{astra → openai}/index.js +8 -4
  91. package/pi-extension/dist/provider-support/{astra → openai}/session-state.js +29 -38
  92. package/pi-extension/dist/provider-support/routes.js +17 -0
  93. package/pi-extension/dist/task-memory/config.js +49 -0
  94. package/pi-extension/dist/task-memory/registry.js +119 -0
  95. package/pi-extension/dist/task-memory/render.js +107 -0
  96. package/pi-extension/dist/task-memory/runtime.js +994 -0
  97. package/pi-extension/dist/task-memory/tool.js +233 -0
  98. package/pi-extension/dist/tool-execution/apply-patch/grammar.js +23 -0
  99. package/pi-extension/dist/tool-execution/apply-patch/match.js +38 -0
  100. package/pi-extension/dist/tool-execution/apply-patch/parser.js +177 -0
  101. package/pi-extension/dist/tool-execution/apply-patch/plan.js +201 -0
  102. package/pi-extension/dist/tool-execution/apply-patch/tool.js +84 -0
  103. package/pi-extension/dist/tool-execution/background.js +430 -0
  104. package/pi-extension/dist/tool-execution/bash-guard.js +23 -0
  105. package/pi-extension/dist/tool-execution/config.js +33 -0
  106. package/pi-extension/dist/tool-execution/edit-messages.js +120 -0
  107. package/pi-extension/dist/tool-execution/file-state.js +138 -0
  108. package/pi-extension/dist/tool-execution/file-tracking.js +163 -0
  109. package/pi-extension/dist/tool-execution/guidance-notices.js +124 -0
  110. package/pi-extension/dist/tool-execution/prompt.js +54 -0
  111. package/pi-extension/dist/tool-execution/skill-reads.js +143 -0
  112. package/pi-extension/dist/tool-execution/tools.js +16 -0
  113. package/pi-extension/freeflow/README.md +9 -0
  114. package/runtime/prompts/cognitive-routing.md +4 -4
  115. package/runtime/prompts/core.md +29 -72
  116. package/runtime/prompts/interaction-contract.md +18 -8
  117. package/runtime/prompts/tool-execution.md +25 -0
  118. package/runtime/prompts/working-method.md +25 -0
  119. package/skills/deliver-work/SKILL.md +76 -0
  120. package/skills/deliver-work/references/branch-closeout.md +134 -0
  121. package/skills/deliver-work/references/commit.md +83 -0
  122. package/skills/deliver-work/references/launch.md +94 -0
  123. package/skills/deliver-work/references/release.md +85 -0
  124. package/skills/deliver-work/scripts/commit-state.mjs +139 -0
  125. package/skills/deliver-work/scripts/delivery-state.mjs +107 -0
  126. package/skills/deliver-work/scripts/lib/git-state.mjs +178 -0
  127. package/skills/deliver-work/scripts/push-route.mjs +122 -0
  128. package/skills/deliver-work/scripts/release-preflight.mjs +177 -0
  129. package/skills/discuss-work/SKILL.md +148 -0
  130. package/skills/{discuss → discuss-work}/references/discussion-continuity.md +13 -50
  131. package/skills/discuss-work/references/learning-action.md +36 -0
  132. package/skills/discuss-work/scripts/choices.mjs +101 -0
  133. package/skills/discuss-work/scripts/lib/choices.mjs +159 -0
  134. package/skills/evaluate-behavior/SKILL.md +107 -0
  135. package/skills/evaluate-behavior/references/authoring.md +381 -0
  136. package/skills/evaluate-behavior/references/coding-tasks.md +145 -0
  137. package/skills/evaluate-behavior/references/conversations-pipelines-judges.md +177 -0
  138. package/skills/evaluate-behavior/references/design-and-measurement.md +273 -0
  139. package/skills/evaluate-behavior/references/running-and-evidence.md +245 -0
  140. package/skills/evaluate-behavior/scripts/claude-guard.mjs +76 -0
  141. package/skills/evaluate-behavior/scripts/guard-rules.mjs +309 -0
  142. package/skills/evaluate-behavior/scripts/lib/agreement.mjs +90 -0
  143. package/skills/evaluate-behavior/scripts/lib/arms.mjs +55 -0
  144. package/skills/evaluate-behavior/scripts/lib/budget.mjs +87 -0
  145. package/skills/evaluate-behavior/scripts/lib/build-source.mjs +287 -0
  146. package/skills/evaluate-behavior/scripts/lib/clear.mjs +74 -0
  147. package/skills/evaluate-behavior/scripts/lib/container.mjs +395 -0
  148. package/skills/evaluate-behavior/scripts/lib/decision.mjs +418 -0
  149. package/skills/evaluate-behavior/scripts/lib/definitions.mjs +1072 -0
  150. package/skills/evaluate-behavior/scripts/lib/freeflow.mjs +103 -0
  151. package/skills/evaluate-behavior/scripts/lib/grade-command.mjs +591 -0
  152. package/skills/evaluate-behavior/scripts/lib/grade-comparison.mjs +90 -0
  153. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-interaction.mjs +19 -18
  154. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-support.mjs +32 -5
  155. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/grade-workspace.mjs +28 -12
  156. package/skills/evaluate-behavior/scripts/lib/grade.mjs +101 -0
  157. package/skills/evaluate-behavior/scripts/lib/hooks.mjs +98 -0
  158. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/confinement.mjs +196 -0
  159. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/constraints.mjs +111 -0
  160. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/index.mjs +48 -0
  161. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/isolation.mjs +74 -0
  162. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/launch.mjs +123 -0
  163. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/model-call.mjs +73 -0
  164. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/recorder.mjs +178 -0
  165. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/session.mjs +494 -0
  166. package/skills/evaluate-behavior/scripts/lib/hosts/claude-code/skills.mjs +81 -0
  167. package/skills/evaluate-behavior/scripts/lib/hosts/index.mjs +31 -0
  168. package/skills/evaluate-behavior/scripts/lib/hosts/names.mjs +3 -0
  169. package/skills/evaluate-behavior/scripts/lib/hosts/pi/confinement.mjs +173 -0
  170. package/skills/evaluate-behavior/scripts/lib/hosts/pi/host.mjs +148 -0
  171. package/skills/evaluate-behavior/scripts/lib/hosts/pi/index.mjs +70 -0
  172. package/skills/evaluate-behavior/scripts/lib/hosts/pi/isolation.mjs +81 -0
  173. package/skills/evaluate-behavior/scripts/lib/hosts/pi/model-call.mjs +79 -0
  174. package/skills/evaluate-behavior/scripts/lib/hosts/pi/process.mjs +241 -0
  175. package/skills/{evaluate-skill/scripts/lib → evaluate-behavior/scripts/lib/hosts/pi}/rpc.mjs +144 -26
  176. package/skills/evaluate-behavior/scripts/lib/identity.mjs +82 -0
  177. package/skills/evaluate-behavior/scripts/lib/judge.mjs +688 -0
  178. package/skills/evaluate-behavior/scripts/lib/metrics.mjs +332 -0
  179. package/skills/evaluate-behavior/scripts/lib/model-call.mjs +17 -0
  180. package/skills/evaluate-behavior/scripts/lib/participants.mjs +616 -0
  181. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/process.mjs +22 -0
  182. package/skills/evaluate-behavior/scripts/lib/queue.mjs +54 -0
  183. package/skills/evaluate-behavior/scripts/lib/reference.mjs +343 -0
  184. package/skills/evaluate-behavior/scripts/lib/reuse.mjs +277 -0
  185. package/skills/evaluate-behavior/scripts/lib/review.mjs +933 -0
  186. package/skills/evaluate-behavior/scripts/lib/runner.mjs +732 -0
  187. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/sandbox.mjs +121 -14
  188. package/skills/evaluate-behavior/scripts/lib/scan-shell.mjs +457 -0
  189. package/skills/evaluate-behavior/scripts/lib/scan.mjs +479 -0
  190. package/skills/evaluate-behavior/scripts/lib/seal.mjs +91 -0
  191. package/skills/evaluate-behavior/scripts/lib/shell.mjs +560 -0
  192. package/skills/evaluate-behavior/scripts/lib/source-override.mjs +64 -0
  193. package/skills/evaluate-behavior/scripts/lib/subject-file.mjs +88 -0
  194. package/skills/{evaluate-skill/scripts/lib/pi.mjs → evaluate-behavior/scripts/lib/subject.mjs} +239 -262
  195. package/skills/evaluate-behavior/scripts/lib/task-copy.mjs +124 -0
  196. package/skills/evaluate-behavior/scripts/lib/trials.mjs +524 -0
  197. package/skills/evaluate-behavior/scripts/lib/validity.mjs +68 -0
  198. package/skills/evaluate-behavior/scripts/lib/view-html.mjs +454 -0
  199. package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/view.mjs +218 -11
  200. package/skills/evaluate-behavior/scripts/pi-command-tool.mjs +159 -0
  201. package/skills/evaluate-behavior/scripts/pi-container-route.mjs +23 -0
  202. package/skills/evaluate-behavior/scripts/pi-guard.mjs +77 -0
  203. package/skills/evaluate-behavior/scripts/pi-login-refresh.mjs +31 -0
  204. package/skills/evaluate-behavior/scripts/skill-eval.mjs +586 -0
  205. package/skills/execute-work/SKILL.md +96 -72
  206. package/skills/execute-work/references/code-practices.md +27 -49
  207. package/skills/execute-work/references/design.md +271 -0
  208. package/skills/execute-work/references/diagnose.md +117 -0
  209. package/skills/execute-work/references/migration.md +108 -0
  210. package/skills/execute-work/references/simplify.md +65 -0
  211. package/skills/execute-work/scripts/self-review.mjs +422 -0
  212. package/skills/execute-work/scripts/touch-map.mjs +290 -0
  213. package/skills/review-work/SKILL.md +94 -64
  214. package/skills/review-work/references/adjudication.md +94 -0
  215. package/skills/review-work/references/artifact.md +198 -0
  216. package/skills/review-work/references/evals-and-judges.md +66 -0
  217. package/skills/review-work/references/work.md +177 -0
  218. package/skills/review-work/scripts/check-brief.mjs +128 -0
  219. package/skills/review-work/scripts/review-packet.mjs +233 -0
  220. package/skills/setup-freeflow/SKILL.md +69 -16
  221. package/skills/track-work/SKILL.md +135 -151
  222. package/skills/track-work/references/handoff.md +190 -0
  223. package/skills/track-work/references/projects.md +51 -0
  224. package/skills/track-work/references/working-record-format.md +201 -344
  225. package/skills/track-work/scripts/lib/document.mjs +79 -19
  226. package/skills/track-work/scripts/lib/format.mjs +18 -1
  227. package/skills/track-work/scripts/lib/recover.mjs +254 -0
  228. package/skills/track-work/scripts/lib/registry.mjs +656 -0
  229. package/skills/track-work/scripts/lib/search.mjs +40 -0
  230. package/skills/track-work/scripts/lib/store.mjs +53 -21
  231. package/skills/track-work/scripts/lib/transitions.mjs +79 -4
  232. package/skills/track-work/scripts/lib/views.mjs +50 -1
  233. package/skills/track-work/scripts/working-record.mjs +263 -22
  234. package/skills/verify-work/SKILL.md +64 -47
  235. package/skills/verify-work/references/feature-map.md +120 -0
  236. package/skills/verify-work/references/runtime-evidence.md +203 -0
  237. package/skills/verify-work/references/test-design.md +27 -6
  238. package/skills/verify-work/scripts/test-changes.mjs +246 -0
  239. package/skills/write-docs/SKILL.md +171 -0
  240. package/skills/write-docs/references/documentation-shapes.md +184 -0
  241. package/skills/write-docs/references/spec-and-plan-shapes.md +308 -0
  242. package/skills/write-docs/scripts/artifact-check.mjs +148 -0
  243. package/skills/write-docs/scripts/docs-check.mjs +229 -0
  244. package/skills/write-docs/scripts/plan-lint.mjs +123 -0
  245. package/skills/write-skill/SKILL.md +165 -165
  246. package/skills/write-skill/references/activation-and-wording.md +143 -0
  247. package/skills/write-skill/references/placement-and-dependencies.md +154 -0
  248. package/skills/write-skill/scripts/lib/compare.mjs +701 -0
  249. package/skills/write-skill/scripts/lib/similarity.mjs +56 -0
  250. package/skills/write-skill/scripts/lib/skill-author.mjs +197 -3
  251. package/skills/write-skill/scripts/skill-author.mjs +67 -8
  252. package/capabilities/context-virtualization/SKILL.md +0 -103
  253. package/capabilities/conversation-history/SKILL.md +0 -53
  254. package/hooks/tests/check-host-adapters.test.mjs +0 -82
  255. package/hooks/tests/check-runtime-context-hook.sh +0 -212
  256. package/pi-extension/dist/cognitive-routing-v2/projection.js +0 -330
  257. package/pi-extension/dist/cognitive-routing-v2/runtime.js +0 -2181
  258. package/pi-extension/dist/cognitive-routing-v2/tools.js +0 -60
  259. package/pi-extension/dist/context-virtualization/commands.js +0 -89
  260. package/pi-extension/dist/context-virtualization/projector.js +0 -42
  261. package/pi-extension/dist/context-virtualization/runtime.js +0 -378
  262. package/pi-extension/dist/context-virtualization/state.js +0 -57
  263. package/pi-extension/dist/context-virtualization/types.js +0 -10
  264. package/pi-extension/dist/conversation-history/passages.js +0 -66
  265. package/pi-extension/dist/conversation-history/ranking.js +0 -105
  266. package/pi-extension/dist/conversation-history/runtime.js +0 -226
  267. package/pi-extension/dist/conversation-history/search.js +0 -56
  268. package/pi-extension/dist/conversation-history/types.js +0 -1
  269. package/pi-extension/dist/freeflow-context/resolver.js +0 -120
  270. package/pi-extension/dist/freeflow-context/runtime.js +0 -80
  271. package/pi-extension/dist/freeflow-context/source-projector.js +0 -95
  272. package/pi-extension/dist/freeflow-context/tool.js +0 -314
  273. package/pi-extension/dist/freeflow-context/types.js +0 -12
  274. package/pi-extension/dist/freeflow-context/visibility.js +0 -28
  275. package/pi-extension/dist/integrations/mcp-config.js +0 -29
  276. package/pi-extension/dist/runtime/runtime-context.js +0 -754
  277. package/pi-extension/dist/runtime/runtime-identity.js +0 -5
  278. package/pi-extension/dist/session-sources/provenance.js +0 -32
  279. package/pi-extension/dist/settings/settings-ui.js +0 -1360
  280. package/pi-extension/dist/ui/text-component.js +0 -57
  281. package/pi-extension/src/cognitive-routing-v2/budget.ts +0 -42
  282. package/pi-extension/src/cognitive-routing-v2/config.ts +0 -173
  283. package/pi-extension/src/cognitive-routing-v2/projection.ts +0 -375
  284. package/pi-extension/src/cognitive-routing-v2/render.ts +0 -277
  285. package/pi-extension/src/cognitive-routing-v2/runtime.ts +0 -2241
  286. package/pi-extension/src/cognitive-routing-v2/schemas.ts +0 -180
  287. package/pi-extension/src/cognitive-routing-v2/state.ts +0 -839
  288. package/pi-extension/src/cognitive-routing-v2/tools.ts +0 -62
  289. package/pi-extension/src/cognitive-routing-v2/types.ts +0 -254
  290. package/pi-extension/src/context-virtualization/commands.ts +0 -111
  291. package/pi-extension/src/context-virtualization/projector.ts +0 -62
  292. package/pi-extension/src/context-virtualization/runtime.ts +0 -428
  293. package/pi-extension/src/context-virtualization/state.ts +0 -79
  294. package/pi-extension/src/context-virtualization/types.ts +0 -92
  295. package/pi-extension/src/conversation-history/passages.ts +0 -81
  296. package/pi-extension/src/conversation-history/ranking.ts +0 -155
  297. package/pi-extension/src/conversation-history/runtime.ts +0 -250
  298. package/pi-extension/src/conversation-history/search.ts +0 -79
  299. package/pi-extension/src/conversation-history/types.ts +0 -31
  300. package/pi-extension/src/freeflow-context/resolver.ts +0 -139
  301. package/pi-extension/src/freeflow-context/runtime.ts +0 -100
  302. package/pi-extension/src/freeflow-context/source-projector.ts +0 -106
  303. package/pi-extension/src/freeflow-context/tool.ts +0 -366
  304. package/pi-extension/src/freeflow-context/types.ts +0 -70
  305. package/pi-extension/src/freeflow-context/visibility.ts +0 -53
  306. package/pi-extension/src/index.ts +0 -390
  307. package/pi-extension/src/integrations/mcp-config.ts +0 -32
  308. package/pi-extension/src/provider-support/astra/adapter.ts +0 -108
  309. package/pi-extension/src/provider-support/astra/history.ts +0 -145
  310. package/pi-extension/src/provider-support/astra/index.ts +0 -12
  311. package/pi-extension/src/provider-support/astra/session-state.ts +0 -113
  312. package/pi-extension/src/provider-support/index.ts +0 -5
  313. package/pi-extension/src/runtime/request-history.ts +0 -243
  314. package/pi-extension/src/runtime/runtime-context.ts +0 -860
  315. package/pi-extension/src/runtime/runtime-identity.ts +0 -8
  316. package/pi-extension/src/session-sources/events.ts +0 -230
  317. package/pi-extension/src/session-sources/provenance.ts +0 -39
  318. package/pi-extension/src/session-sources/read-only-session.ts +0 -170
  319. package/pi-extension/src/session-sources/sources.ts +0 -334
  320. package/pi-extension/src/settings/settings-tui.ts +0 -501
  321. package/pi-extension/src/settings/settings-ui.ts +0 -1652
  322. package/pi-extension/src/ui/text-component.ts +0 -66
  323. package/pi-extension/tests/cache-reuse/history.test.js +0 -117
  324. package/pi-extension/tests/cache-reuse/native.test.js +0 -91
  325. package/pi-extension/tests/cache-reuse/settings.test.js +0 -211
  326. package/pi-extension/tests/cognitive-routing-v2/communication.test.js +0 -577
  327. package/pi-extension/tests/cognitive-routing-v2/compaction-input.test.js +0 -183
  328. package/pi-extension/tests/cognitive-routing-v2/delegation.test.js +0 -557
  329. package/pi-extension/tests/cognitive-routing-v2/native.test.js +0 -474
  330. package/pi-extension/tests/cognitive-routing-v2/performance.test.js +0 -87
  331. package/pi-extension/tests/cognitive-routing-v2/persistence.test.js +0 -300
  332. package/pi-extension/tests/cognitive-routing-v2/projection.test.js +0 -241
  333. package/pi-extension/tests/cognitive-routing-v2/recovery.test.js +0 -1034
  334. package/pi-extension/tests/cognitive-routing-v2/render.test.js +0 -244
  335. package/pi-extension/tests/cognitive-routing-v2/runtime.test.js +0 -423
  336. package/pi-extension/tests/cognitive-routing-v2/stabilization.test.js +0 -521
  337. package/pi-extension/tests/cognitive-routing-v2/state.test.js +0 -586
  338. package/pi-extension/tests/context-virtualization/extension.test.js +0 -775
  339. package/pi-extension/tests/context-virtualization/projector.test.js +0 -110
  340. package/pi-extension/tests/context-virtualization/runtime.test.js +0 -230
  341. package/pi-extension/tests/conversation-history/runtime.test.js +0 -98
  342. package/pi-extension/tests/conversation-history/search.test.js +0 -97
  343. package/pi-extension/tests/fixtures/pi-host.js +0 -4
  344. package/pi-extension/tests/fixtures/routing-native.js +0 -191
  345. package/pi-extension/tests/integration/mode-free-core.test.js +0 -220
  346. package/pi-extension/tests/integration/pi-extension.test.js +0 -1447
  347. package/pi-extension/tests/integration/prompt-architecture.test.js +0 -447
  348. package/pi-extension/tests/integration/unaffected-regressions.test.js +0 -478
  349. package/pi-extension/tests/provider-support/astra-boundaries.test.js +0 -75
  350. package/pi-extension/tests/provider-support/astra.test.js +0 -306
  351. package/pi-extension/tests/provider-support/cli.test.js +0 -92
  352. package/pi-extension/tests/provider-support/native.test.js +0 -183
  353. package/pi-extension/tests/settings/settings-tui.test.js +0 -243
  354. package/pi-extension/tsconfig.json +0 -16
  355. package/plugin.json +0 -33
  356. package/runtime/prompts/context-virtualization.md +0 -3
  357. package/runtime/prompts/conversation-history.md +0 -3
  358. package/skills/action-selection/SKILL.md +0 -100
  359. package/skills/action-selection/references/trajectory-stalls.md +0 -71
  360. package/skills/bypass/SKILL.md +0 -153
  361. package/skills/commit-work/SKILL.md +0 -145
  362. package/skills/commit-work/references/git-state-edges.md +0 -94
  363. package/skills/commit-work/references/simple-push.md +0 -92
  364. package/skills/commit-work/references/staging-decisions.md +0 -106
  365. package/skills/decision-gate/SKILL.md +0 -106
  366. package/skills/design-for-depth/SKILL.md +0 -117
  367. package/skills/design-for-depth/references/design-pressure-signals.md +0 -182
  368. package/skills/design-for-depth/references/implementation-decisions.md +0 -76
  369. package/skills/design-for-depth/references/interface-design-loop.md +0 -136
  370. package/skills/design-for-depth/references/module-and-dependency-design.md +0 -147
  371. package/skills/design-for-depth/references/software-design-philosophy.md +0 -202
  372. package/skills/design-for-depth/references/state-and-failure-boundaries.md +0 -136
  373. package/skills/diagnose-failure/SKILL.md +0 -125
  374. package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +0 -48
  375. package/skills/diagnose-failure/references/flaky-and-performance-diagnosis.md +0 -51
  376. package/skills/discuss/SKILL.md +0 -116
  377. package/skills/evaluate-skill/SKILL.md +0 -219
  378. package/skills/evaluate-skill/references/evaluation-definition-schema.md +0 -385
  379. package/skills/evaluate-skill/references/evaluation-design.md +0 -112
  380. package/skills/evaluate-skill/references/execution-and-evidence.md +0 -90
  381. package/skills/evaluate-skill/references/review-and-revision.md +0 -92
  382. package/skills/evaluate-skill/scripts/lib/definitions.mjs +0 -407
  383. package/skills/evaluate-skill/scripts/lib/grade-comparison.mjs +0 -60
  384. package/skills/evaluate-skill/scripts/lib/grade.mjs +0 -64
  385. package/skills/evaluate-skill/scripts/lib/runner.mjs +0 -368
  386. package/skills/evaluate-skill/scripts/pi-guard.mjs +0 -164
  387. package/skills/evaluate-skill/scripts/skill-eval.mjs +0 -102
  388. package/skills/execute-work/references/execute-work-edges.md +0 -68
  389. package/skills/finish-branch/SKILL.md +0 -117
  390. package/skills/finish-branch/references/integration-options.md +0 -80
  391. package/skills/handoff/SKILL.md +0 -82
  392. package/skills/handoff/references/handoff-templates.md +0 -150
  393. package/skills/launch-work/SKILL.md +0 -116
  394. package/skills/launch-work/references/launch-readiness.md +0 -85
  395. package/skills/migration-work/SKILL.md +0 -115
  396. package/skills/migration-work/references/migration-lifecycle.md +0 -82
  397. package/skills/release-work/SKILL.md +0 -118
  398. package/skills/release-work/references/release-evidence.md +0 -78
  399. package/skills/review-artifact/SKILL.md +0 -142
  400. package/skills/review-artifact/references/adjudicate-artifact-review.md +0 -101
  401. package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +0 -159
  402. package/skills/review-work/references/adjudicate-work-review.md +0 -97
  403. package/skills/review-work/references/independent-work-reviewer-contract.md +0 -139
  404. package/skills/review-work/references/security-risk-lens.md +0 -69
  405. package/skills/setup-freeflow/references/activation-contract.md +0 -109
  406. package/skills/setup-freeflow/references/host-setup.md +0 -67
  407. package/skills/simplify-code/SKILL.md +0 -85
  408. package/skills/simplify-code/references/simplification-patterns.md +0 -70
  409. package/skills/verify-work/references/browser-runtime-evidence.md +0 -55
  410. package/skills/verify-work/references/integration-evidence.md +0 -47
  411. package/skills/verify-work/references/performance-evidence.md +0 -57
  412. package/skills/workflow/SKILL.md +0 -127
  413. package/skills/workflow/references/domain-skill-composition.md +0 -43
  414. package/skills/write-plan/SKILL.md +0 -92
  415. package/skills/write-plan/references/plan-shapes.md +0 -156
  416. package/skills/write-skill/references/activation-boundaries.md +0 -104
  417. package/skills/write-skill/references/agent-first-instructions.md +0 -121
  418. package/skills/write-skill/references/progressive-disclosure.md +0 -127
  419. package/skills/write-skill/references/skill-dependency-graphs.md +0 -190
  420. package/skills/write-spec/SKILL.md +0 -92
  421. package/skills/write-spec/references/artifact-standards.md +0 -86
  422. package/skills/write-spec/references/decision-records.md +0 -78
  423. package/skills/write-spec/references/spec-shapes.md +0 -143
  424. /package/pi-extension/dist/{cognitive-routing-v2 → cognitive-routing}/budget.js +0 -0
  425. /package/skills/{evaluate-skill → evaluate-behavior}/scripts/lib/evidence.mjs +0 -0
  426. /package/skills/{evaluate-skill → evaluate-behavior}/scripts/pi-observer.mjs +0 -0
@@ -0,0 +1,901 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { changeSelection, representationProblems } from "./projection.js";
3
+ import { bodyHash, isTaskEvidence } from "./sources.js";
4
+ import { RoutingError, canonical, emptySelection, idFor, isWorkerProfile, requireCondition as check } from "./types.js";
5
+ import { cachedBranch } from "../host/branch.js";
6
+ /**
7
+ * Runs the routing tools (delegate_work, return_work, select_evidence, routing_unit) one at a time on the
8
+ * session's queue. Each accepted call is recorded once under its operation id, so a repeated call returns the saved
9
+ * result instead of acting again; a refused call returns a blocked result that names what to reconcile.
10
+ */
11
+ export class ToolHandlers {
12
+ session;
13
+ models;
14
+ gate;
15
+ assembler;
16
+ status;
17
+ constructor(session, models, gate, assembler, status) {
18
+ this.session = session;
19
+ this.models = models;
20
+ this.gate = gate;
21
+ this.assembler = assembler;
22
+ this.status = status;
23
+ }
24
+ resultGrants;
25
+ effectFence;
26
+ setResultGrantPort(port) {
27
+ this.resultGrants = port;
28
+ }
29
+ setEffectFencePort(port) {
30
+ this.effectFence = port;
31
+ }
32
+ callOperation(callId, name) {
33
+ check(this.session.turn && this.session.store, "execution_missing");
34
+ this.gate.batch(callId, name);
35
+ return JSON.stringify([this.session.store.reader.getSessionId(), this.session.turn.id, callId, name]);
36
+ }
37
+ result(value) {
38
+ return { content: [{ type: "text", text: JSON.stringify(value) }], details: value };
39
+ }
40
+ async invoke(name, callId, input, signal, ctx) {
41
+ return this.session.enqueue(async () => {
42
+ this.session.ctx = ctx;
43
+ try {
44
+ check(!signal?.aborted, "cancelled");
45
+ if (name === "routing_unit" && input.operation === "inspect") {
46
+ check(this.session.supported(), "routing_unavailable");
47
+ return this.result(this.inspectUnit(input));
48
+ }
49
+ const state = this.session.stateData();
50
+ const expected =
51
+ name === "delegate_work" || name === "routing_unit" ? "coordinator" : this.session.assignedWorker(state);
52
+ this.session.assertAvailable(expected);
53
+ const op = this.callOperation(callId, name);
54
+ const cached = this.session.receipts.get(op);
55
+ if (cached) {
56
+ check(cached.input === canonical(input), "operation_conflict");
57
+ return this.result(structuredClone(cached.value));
58
+ }
59
+ const value =
60
+ name === "delegate_work"
61
+ ? this.delegate(input, callId, op)
62
+ : name === "return_work"
63
+ ? this.returnReport(input, callId, op)
64
+ : name === "select_evidence"
65
+ ? this.project(input, op)
66
+ : name === "routing_unit"
67
+ ? await this.unit(input, callId, op)
68
+ : undefined;
69
+ if (value !== undefined) {
70
+ this.session.receipts.set(op, { input: canonical(input), value: structuredClone(value) });
71
+ return this.result(value);
72
+ }
73
+ throw new RoutingError("unknown_tool", name);
74
+ } catch (error) {
75
+ return this.result({
76
+ status: "blocked",
77
+ code: error instanceof RoutingError ? error.code : "operation_failed",
78
+ message: error instanceof Error ? error.message : String(error),
79
+ problems: error instanceof RoutingError ? error.problems : [],
80
+ observed: this.session.observed(),
81
+ expectedProfile:
82
+ name === "routing_unit" && input.operation === "inspect"
83
+ ? undefined
84
+ : name === "delegate_work" || name === "routing_unit"
85
+ ? "coordinator"
86
+ : (() => {
87
+ try {
88
+ return this.session.assignedWorker(this.session.stateData());
89
+ } catch {
90
+ return undefined;
91
+ }
92
+ })(),
93
+ recoveryAction:
94
+ error instanceof RoutingError &&
95
+ [
96
+ "cursor_expired",
97
+ "invalid_cursor",
98
+ "work_ref_required",
99
+ "invalid_work_ref",
100
+ "work_unavailable",
101
+ "invalid_inspection",
102
+ ].includes(error.code)
103
+ ? "Inspect again without a cursor and use a returned work ref. Lookup recovery does not require a new assignment."
104
+ : "Preserve saved work. Use routing_unit inspect; reconcile current input/control before retrying the named operation.",
105
+ });
106
+ }
107
+ });
108
+ }
109
+ duplicate(op) {
110
+ return [...this.session.stateData().events.values()].find(
111
+ (e) =>
112
+ e.operationId === op &&
113
+ [
114
+ "delegate-accepted",
115
+ "return-accepted",
116
+ "recovery-request-accepted",
117
+ "recovery-supplement-accepted",
118
+ "recovery-cancelled",
119
+ "handoff-retry-requested",
120
+ ].includes(e.data.type),
121
+ );
122
+ }
123
+ delegate(input, callId, op) {
124
+ const prior = this.duplicate(op);
125
+ if (prior) {
126
+ check(
127
+ prior.data.type === "delegate-accepted" &&
128
+ prior.data.assignment.contract === input.contract &&
129
+ (input.worker === undefined || prior.data.handoff.to === input.worker),
130
+ "operation_conflict",
131
+ );
132
+ return { status: "accepted", handoff: prior.data.handoff.id, unchanged: true };
133
+ }
134
+ const state = this.session.stateData();
135
+ const enabled = this.session.enabledWorkers();
136
+ let worker;
137
+ if (input.worker === undefined) {
138
+ check(enabled.length === 1, "worker_required", "Delegation mode 'both' requires choosing helper or executor.");
139
+ worker = enabled[0];
140
+ } else {
141
+ check(isWorkerProfile(input.worker), "invalid_worker");
142
+ worker = input.worker;
143
+ }
144
+ check(enabled.includes(worker), "worker_disabled", `${worker} is not enabled by delegation mode.`);
145
+ const unit = state.unitId
146
+ ? state.units.get(state.unitId)
147
+ : { id: randomUUID(), objective: input.contract, state: "open", assignmentIds: [] };
148
+ const old = state.assignmentId ? state.assignments.get(state.assignmentId) : undefined;
149
+ if (input.operation === "replace")
150
+ check(old?.state === "outstanding" && !this.models.applying, "no_quiescent_assignment");
151
+ else
152
+ check(
153
+ input.operation === "assign" && old?.state !== "outstanding" && !state.pendingId && !state.recoveryId,
154
+ "assignment_outstanding",
155
+ );
156
+ const assignmentId = randomUUID(),
157
+ id = randomUUID();
158
+ const assignment = {
159
+ id: assignmentId,
160
+ unitId: unit.id,
161
+ contract: input.contract,
162
+ state: "outstanding",
163
+ delegateHandoffId: id,
164
+ basisUserEntryId: this.session.turn.basisUserEntryId,
165
+ };
166
+ const h = {
167
+ id,
168
+ kind: "delegate",
169
+ assignmentId,
170
+ text: input.contract,
171
+ from: "coordinator",
172
+ to: worker,
173
+ executionId: this.session.turn.id,
174
+ toolCallId: callId,
175
+ basisUserEntryId: this.session.turn.basisUserEntryId,
176
+ state: "pending",
177
+ reportRevision: 0,
178
+ limitations: [],
179
+ };
180
+ this.session.append(
181
+ {
182
+ type: "delegate-accepted",
183
+ unit: { ...unit, assignmentIds: [...unit.assignmentIds, assignmentId] },
184
+ assignment,
185
+ handoff: h,
186
+ ...(input.operation === "replace"
187
+ ? {
188
+ replacement: {
189
+ assignmentId: old.id,
190
+ reason: input.reason,
191
+ ...(state.pendingId ? { supersededHandoffId: state.pendingId } : {}),
192
+ },
193
+ }
194
+ : {}),
195
+ },
196
+ op,
197
+ );
198
+ return {
199
+ status: "accepted",
200
+ unit: unit.id,
201
+ assignment: assignmentId,
202
+ worker,
203
+ handoff: id,
204
+ transition: "pending",
205
+ createdUnit: !state.unitId,
206
+ ...(old && input.operation === "replace"
207
+ ? {
208
+ replacedAssignment: old.id,
209
+ continuity:
210
+ "Prior effects and evidence remain on native history. Reconcile uncertain effects before dependent work.",
211
+ }
212
+ : {}),
213
+ };
214
+ }
215
+ returnReport(input, callId, op) {
216
+ const state = this.session.stateData(),
217
+ a = state.assignmentId ? state.assignments.get(state.assignmentId) : undefined;
218
+ check(a, "assignment_missing");
219
+ const worker = this.session.assignedWorker(state, a.id);
220
+ const recovery = state.recoveryId ? state.recoveries.get(state.recoveryId) : undefined;
221
+ const original = a.returnHandoffId ? state.handoffs.get(a.returnHandoffId) : undefined;
222
+ const supplement = recovery?.supplementHandoffId ? state.handoffs.get(recovery.supplementHandoffId) : undefined;
223
+ const retryingSupplement = input.operation === "retry" && recovery?.state === "returning";
224
+ const saved = retryingSupplement || input.operation === "supplement" ? supplement : original;
225
+ const selection = state.selections.get(a.id) ?? emptySelection();
226
+ const duplicate = this.duplicate(op);
227
+ if (duplicate) {
228
+ if (input.operation === "retry") check(duplicate.data.type === "handoff-retry-requested", "operation_conflict");
229
+ else {
230
+ const expected = input.operation === "supplement" ? "recovery-supplement-accepted" : "return-accepted";
231
+ check(
232
+ duplicate.data.type === expected &&
233
+ duplicate.data.handoff.text === input.report &&
234
+ duplicate.data.handoff.outcome === input.outcome &&
235
+ canonical(duplicate.data.handoff.limitations) === canonical(input.limitations ?? []),
236
+ "operation_conflict",
237
+ );
238
+ }
239
+ const handoff = duplicate.data.handoffId ?? duplicate.data.handoff.id;
240
+ return { ...this.returnReadiness(handoff), unchanged: true };
241
+ }
242
+ if (input.operation === "retry") {
243
+ check(saved && ["blocked", "pending"].includes(saved.state), "saved_return_missing");
244
+ this.session.append(
245
+ {
246
+ type: "handoff-retry-requested",
247
+ handoffId: saved.id,
248
+ attemptId: randomUUID(),
249
+ executionId: this.session.turn.id,
250
+ toolCallId: callId,
251
+ reportRevision: saved.reportRevision,
252
+ selectionRevision: selection.revision,
253
+ },
254
+ op,
255
+ );
256
+ return {
257
+ ...this.returnReadiness(saved.id),
258
+ reportUnchanged: true,
259
+ supplementUnchanged: saved.kind === "recovery-return",
260
+ };
261
+ }
262
+ if (input.operation === "supplement") {
263
+ check(
264
+ recovery &&
265
+ ["reading", "returning"].includes(recovery.state) &&
266
+ (!supplement || ["pending", "blocked"].includes(supplement.state)),
267
+ "recovery_not_returnable",
268
+ );
269
+ const h = {
270
+ id: supplement?.id ?? randomUUID(),
271
+ kind: "recovery-return",
272
+ assignmentId: a.id,
273
+ text: input.report,
274
+ from: worker,
275
+ to: "coordinator",
276
+ executionId: this.session.turn.id,
277
+ toolCallId: callId,
278
+ basisUserEntryId: this.session.turn.basisUserEntryId,
279
+ state: "pending",
280
+ reportRevision: (supplement?.reportRevision ?? 0) + 1,
281
+ outcome: input.outcome,
282
+ limitations: input.limitations ?? [],
283
+ };
284
+ this.session.append({ type: "recovery-supplement-accepted", recoveryId: recovery.id, handoff: h }, op);
285
+ return this.returnReadiness(h.id);
286
+ }
287
+ check(input.operation === "submit", "invalid_return_operation");
288
+ check(
289
+ input.outcome !== "completed" || !this.effectFence?.status().unresolvedEffects,
290
+ "unresolved_effect",
291
+ "A clean completed return is unavailable while a live effect requires reconciliation.",
292
+ );
293
+ check(
294
+ a.state === "outstanding" ||
295
+ (a.state === "returned" && original && ["pending", "blocked"].includes(original.state)),
296
+ "assignment_task_ended",
297
+ );
298
+ const h = {
299
+ id: original?.id ?? randomUUID(),
300
+ kind: "return",
301
+ assignmentId: a.id,
302
+ text: input.report,
303
+ from: worker,
304
+ to: "coordinator",
305
+ executionId: this.session.turn.id,
306
+ toolCallId: callId,
307
+ basisUserEntryId: this.session.turn.basisUserEntryId,
308
+ state: "pending",
309
+ reportRevision: (original?.reportRevision ?? 0) + 1,
310
+ outcome: input.outcome,
311
+ limitations: input.limitations ?? [],
312
+ };
313
+ this.session.append({ type: "return-accepted", handoff: h }, op);
314
+ return this.returnReadiness(h.id);
315
+ }
316
+ returnReadiness(id) {
317
+ const state = this.session.stateData();
318
+ const h = state.handoffs.get(id);
319
+ const prepared = this.assembler.prepared("coordinator", this.session.messages, id);
320
+ const isSupplement = h.kind === "recovery-return";
321
+ const recovery = isSupplement
322
+ ? [...state.recoveries.values()].find((candidate) => candidate.supplementHandoffId === h.id)
323
+ : undefined;
324
+ return {
325
+ status: "accepted",
326
+ reportSaved: !isSupplement,
327
+ supplementSaved: isSupplement,
328
+ handoff: id,
329
+ ...(recovery ? { recovery: recovery.id } : {}),
330
+ ...(isSupplement ? { supplementRevision: h.reportRevision } : { reportRevision: h.reportRevision }),
331
+ assignmentRef: `assignment:${h.assignmentId}`,
332
+ ...(isSupplement
333
+ ? { supplementRef: `supplement:${recovery?.id ?? "unknown"}:${h.reportRevision}` }
334
+ : { reportRef: `report:${h.id}:${h.reportRevision}` }),
335
+ producer: h.from,
336
+ outcome: h.outcome,
337
+ limitations: h.limitations,
338
+ ready: prepared.ready,
339
+ transition: prepared.ready ? "pending" : "blocked",
340
+ problems: prepared.problems,
341
+ warnings: prepared.warnings,
342
+ stage: "completed-input preparation",
343
+ finalExchangePending: true,
344
+ // The Coordinator reads this receipt too, after delivery; it must not read as "the evidence was not delivered".
345
+ provisional: prepared.ready
346
+ ? "Saved. When this turn ends, Freeflow checks the handoff and delivers the report to Coordinator; selected evidence stays in place in the worker's run, where Coordinator sees it."
347
+ : "Saved, but blocked: Coordinator receives nothing until the problems below are fixed. Fix the selection with select_evidence, then call return_work with operation retry.",
348
+ // The text is already in the call arguments; the hash identifies it without a second copy.
349
+ ...(isSupplement ? { supplementSha256: bodyHash(h.text) } : { reportSha256: bodyHash(h.text) }),
350
+ evidence: this.assembler.evidenceFacts(state),
351
+ };
352
+ }
353
+ project(input, op) {
354
+ check(this.session.projectionEnabled, "projection_disabled");
355
+ const state = this.session.stateData(),
356
+ a = state.assignmentId ? state.assignments.get(state.assignmentId) : undefined;
357
+ check(a, "assignment_missing");
358
+ const sources = this.session.sources(state);
359
+ sources.associate(this.session.messages);
360
+ const selection = state.selections.get(a.id) ?? emptySelection();
361
+ let next = selection;
362
+ if (input.operation !== "inspect") {
363
+ check(["add", "remove"].includes(input.operation), "invalid_projection_operation");
364
+ next = changeSelection(selection, input, sources, state);
365
+ if (next !== selection)
366
+ this.session.append({ type: "selection-changed", assignmentId: a.id, selection: next }, op);
367
+ }
368
+ const prepared = this.assembler.prepared("coordinator", this.session.messages, a.returnHandoffId);
369
+ const scope = input.scope ?? "assignment";
370
+ let page;
371
+ if (input.operation === "inspect") {
372
+ const model = this.models.model("coordinator");
373
+ const checksFor = (s) => {
374
+ const eligibility = sources.selectionProblem(s.ref, state);
375
+ const limitations = [
376
+ ...(eligibility ? [eligibility] : []),
377
+ ...representationProblems(s, model),
378
+ ...sources.exchange(s).problems,
379
+ ];
380
+ return { eligible: !eligibility, targetReady: !limitations.length, limitations };
381
+ };
382
+ const rows = () =>
383
+ [...sources.byRef.values()]
384
+ .filter(
385
+ (s) =>
386
+ isWorkerProfile(s.producer) &&
387
+ (isTaskEvidence(s) || (scope === "selected" && next.selected.includes(s.ref))) &&
388
+ (scope === "selected"
389
+ ? next.selected.includes(s.ref)
390
+ : scope === "assignment"
391
+ ? s.assignmentId === a.id
392
+ : scope === "active"
393
+ ? s.active
394
+ : true),
395
+ )
396
+ .map((s) => {
397
+ const locator = sources.locator(s.ref);
398
+ return {
399
+ ref: s.ref,
400
+ kind: s.message.role,
401
+ producer: s.producer,
402
+ assignment: s.assignmentId,
403
+ toolName: s.message.toolName,
404
+ ...(locator ? { locator } : {}),
405
+ active: s.active,
406
+ selected: next.selected.includes(s.ref),
407
+ retainedSelection: next.selected.includes(s.ref) && !isTaskEvidence(s),
408
+ ...checksFor(s),
409
+ };
410
+ })
411
+ // Discovery offers usable candidates. Saved selections must remain
412
+ // inspectable even when a later source or target check fails.
413
+ .filter((row) => scope === "selected" || row.targetReady);
414
+ page = this.page(
415
+ `evidence:${scope}`,
416
+ rows,
417
+ input.cursor,
418
+ 30,
419
+ scope === "assignment" || scope === "selected" ? a.id : undefined,
420
+ scope === "active",
421
+ (rows) => ({
422
+ scopeCounts: {
423
+ candidates: rows.length,
424
+ eligible: rows.filter((r) => r.eligible).length,
425
+ targetReady: rows.filter((r) => r.targetReady).length,
426
+ },
427
+ otherAssignments: [...sources.byRef.values()].filter(
428
+ (s) =>
429
+ isWorkerProfile(s.producer) && s.assignmentId !== a.id && isTaskEvidence(s) && checksFor(s).targetReady,
430
+ ).length,
431
+ }),
432
+ );
433
+ }
434
+ return {
435
+ status: input.operation === "inspect" || next === selection ? "unchanged" : "saved",
436
+ ...(page
437
+ ? {
438
+ scope,
439
+ count: page.count,
440
+ returned: page.items.length,
441
+ candidates: page.items,
442
+ nextCursor: page.nextCursor,
443
+ ...page.summary,
444
+ pageCounts: {
445
+ candidates: page.items.length,
446
+ eligible: page.items.filter((r) => r.eligible).length,
447
+ targetReady: page.items.filter((r) => r.targetReady).length,
448
+ },
449
+ countsBasis:
450
+ "Inspection snapshot; page counts describe returned candidates, scope counts describe all candidates in this scope.",
451
+ historyHint: page.summary.otherAssignments
452
+ ? "Previously exposed task evidence exists in other assignments; inspect scope history when needed."
453
+ : undefined,
454
+ }
455
+ : {}),
456
+ revision: next.revision,
457
+ selected: next.selected,
458
+ selectedCount: next.selected.length,
459
+ unresolved: next.unresolved,
460
+ ready: !next.unresolved.length && prepared.ready,
461
+ problems: prepared.problems,
462
+ warnings: prepared.warnings,
463
+ evidence: this.assembler.evidenceFacts(this.session.stateData()),
464
+ items: (input.refs ? [...new Set(input.refs)] : []).map((ref) => ({
465
+ ref,
466
+ status: next.unresolved.some((p) => p.ref === ref)
467
+ ? "rejected"
468
+ : input.operation === "remove"
469
+ ? selection.selected.includes(ref)
470
+ ? "removed"
471
+ : selection.unresolved.some((p) => p.ref === ref)
472
+ ? "withdrawn"
473
+ : "unchanged"
474
+ : selection.selected.includes(ref)
475
+ ? "already_selected"
476
+ : "added",
477
+ })),
478
+ estimate: { tokens: prepared.estimatedTokens, method: prepared.estimateMethod },
479
+ };
480
+ }
481
+ async unit(input, callId, op) {
482
+ const state = this.session.stateData();
483
+ const prior = [...state.events.values()].find((e) => e.operationId === op);
484
+ if (prior) {
485
+ if (input.operation === "recover") {
486
+ check(
487
+ prior.data.type === "recovery-request-accepted" &&
488
+ prior.data.recovery.request === input.request &&
489
+ canonical(prior.data.recovery.requestedPaths) === canonical([...new Set(input.paths ?? [])]) &&
490
+ canonical(prior.data.recovery.requestedResults ?? []) === canonical(input.results ?? []),
491
+ "operation_conflict",
492
+ );
493
+ const { recovery, handoff } = prior.data;
494
+ return {
495
+ status: "accepted",
496
+ unchanged: true,
497
+ recovery: recovery.id,
498
+ handoff: handoff.id,
499
+ assignmentRef: `assignment:${recovery.assignmentId}`,
500
+ reportRef: `report:${recovery.assessmentHandoffId}:${recovery.baseReportRevision}`,
501
+ paths: recovery.paths,
502
+ results: recovery.results ?? [],
503
+ transition: handoff.state,
504
+ };
505
+ }
506
+ if (input.operation === "cancel-recovery") {
507
+ check(prior.data.type === "recovery-cancelled" && prior.data.reason === input.reason, "operation_conflict");
508
+ return {
509
+ status: "cancelled",
510
+ unchanged: true,
511
+ recovery: prior.data.recoveryId,
512
+ reason: prior.data.reason,
513
+ assessment: state.assessment?.handoffId,
514
+ };
515
+ }
516
+ check(
517
+ (input.operation === "assess" && prior.data.type === "assessment-resumed") ||
518
+ (input.operation === "close" &&
519
+ prior.data.type === "unit-closed" &&
520
+ prior.data.outcome === input.outcome &&
521
+ prior.data.assessment === input.assessment),
522
+ "operation_conflict",
523
+ );
524
+ return { status: "unchanged", operation: input.operation };
525
+ }
526
+ if (input.operation === "recover") {
527
+ const a = state.assignmentId ? state.assignments.get(state.assignmentId) : undefined;
528
+ const base = a?.returnHandoffId ? state.handoffs.get(a.returnHandoffId) : undefined;
529
+ check(
530
+ state.unitId &&
531
+ a?.state === "returned" &&
532
+ base?.kind === "return" &&
533
+ base.state === "configured" &&
534
+ state.assessment?.handoffId === base.id &&
535
+ !state.pendingId &&
536
+ !state.recoveryId &&
537
+ !this.models.applying,
538
+ "recovery_not_available",
539
+ );
540
+ const worker = this.session.assignedWorker(state, a.id);
541
+ const id = randomUUID(),
542
+ handoffId = randomUUID();
543
+ const paths = [...new Set((input.paths ?? []).map((path) => this.gate.canonicalRecoveryPath(path)))];
544
+ const requestedResults = [...(input.results ?? [])];
545
+ check(new Set(requestedResults).size === requestedResults.length, "duplicate_result_grant");
546
+ const results = [];
547
+ for (const resultId of requestedResults) {
548
+ // A context ref is evidence the worker selects, not a captured result the Coordinator grants.
549
+ check(
550
+ !idFor(resultId),
551
+ "result_unavailable",
552
+ `${resultId} is a context ref, not a captured result id: name it in the request instead, and the worker selects it as evidence with select_evidence.`,
553
+ );
554
+ const grant = await this.resultGrants?.resolve(resultId, this.session.ctx);
555
+ check(grant?.id === resultId, "result_unavailable", `Captured result is unavailable: ${resultId}`);
556
+ results.push(grant);
557
+ }
558
+ const recovery = {
559
+ id,
560
+ assignmentId: a.id,
561
+ assessmentHandoffId: base.id,
562
+ baseReportRevision: base.reportRevision,
563
+ request: input.request,
564
+ requestedPaths: [...new Set(input.paths ?? [])],
565
+ paths,
566
+ requestedResults,
567
+ results,
568
+ state: "requested",
569
+ requestHandoffId: handoffId,
570
+ supplementRevision: 0,
571
+ };
572
+ const handoff = {
573
+ id: handoffId,
574
+ kind: "recovery-request",
575
+ assignmentId: a.id,
576
+ text: input.request,
577
+ from: "coordinator",
578
+ to: worker,
579
+ executionId: this.session.turn.id,
580
+ toolCallId: callId,
581
+ basisUserEntryId: this.session.turn.basisUserEntryId,
582
+ state: "pending",
583
+ reportRevision: 0,
584
+ limitations: [],
585
+ };
586
+ this.session.append({ type: "recovery-request-accepted", recovery, handoff }, op);
587
+ return {
588
+ status: "accepted",
589
+ recovery: id,
590
+ handoff: handoffId,
591
+ assignmentRef: `assignment:${a.id}`,
592
+ reportRef: `report:${base.id}:${base.reportRevision}`,
593
+ paths,
594
+ results,
595
+ transition: "pending",
596
+ };
597
+ }
598
+ if (input.operation === "cancel-recovery") {
599
+ check(state.recoveryId && !this.models.applying, "recovery_not_cancellable");
600
+ check(
601
+ ![...state.executions.values()].some(
602
+ (execution) =>
603
+ execution.recoveryId === state.recoveryId &&
604
+ isWorkerProfile(execution.profile) &&
605
+ !execution.assistantEntryId &&
606
+ !execution.interrupted,
607
+ ),
608
+ "recovery_not_cancellable",
609
+ );
610
+ this.session.append({ type: "recovery-cancelled", recoveryId: state.recoveryId, reason: input.reason }, op);
611
+ return {
612
+ status: "cancelled",
613
+ recovery: state.recoveryId,
614
+ reason: input.reason,
615
+ assessment: state.assessment?.handoffId,
616
+ };
617
+ }
618
+ if (input.operation === "assess") {
619
+ check(state.assessment, "assessment_missing");
620
+ check(!state.recoveryId, "recovery_outstanding");
621
+ if (state.assessment.view === "active") return { status: "unchanged", ready: true };
622
+ const prepared = this.assembler.prepared("coordinator", this.session.messages, state.assessment.handoffId, true);
623
+ if (!prepared.ready) return { status: "suspended", ready: false, problems: prepared.problems };
624
+ if (this.session.projectionEnabled) check(prepared.reservation, "reservation_missing");
625
+ this.session.append(
626
+ {
627
+ type: "assessment-resumed",
628
+ handoffId: state.assessment.handoffId,
629
+ basisUserEntryId: this.session.turn.basisUserEntryId,
630
+ ...(prepared.reservation ? { reservation: prepared.reservation } : {}),
631
+ },
632
+ op,
633
+ );
634
+ this.session.projectionError = undefined;
635
+ return {
636
+ status: "resumed",
637
+ ready: true,
638
+ stage: "prepared assessment; next request revalidated",
639
+ evidence: this.assembler.evidenceFacts(this.session.stateData()),
640
+ };
641
+ }
642
+ check(input.operation === "close" && state.unitId, "unit_missing");
643
+ const a = state.assignmentId ? state.assignments.get(state.assignmentId) : undefined;
644
+ check(!this.models.applying, "not_quiescent");
645
+ check(
646
+ input.outcome !== "accepted" || !this.effectFence?.status().unresolvedEffects,
647
+ "unresolved_effect",
648
+ "Accepted closure is unavailable while a live effect requires reconciliation.",
649
+ );
650
+ if (state.recoveryId) {
651
+ check(input.outcome !== "accepted", "unfinished_work");
652
+ check(
653
+ ![...state.executions.values()].some(
654
+ (execution) =>
655
+ execution.recoveryId === state.recoveryId &&
656
+ isWorkerProfile(execution.profile) &&
657
+ !execution.assistantEntryId &&
658
+ !execution.interrupted,
659
+ ),
660
+ "not_quiescent",
661
+ );
662
+ }
663
+ this.session.append(
664
+ {
665
+ type: "unit-closed",
666
+ unitId: state.unitId,
667
+ outcome: input.outcome,
668
+ assessment: input.assessment,
669
+ ...(a?.state === "outstanding" && input.outcome !== "accepted" ? { supersededAssignmentId: a.id } : {}),
670
+ },
671
+ op,
672
+ );
673
+ return { status: "closed", unit: state.unitId, outcome: input.outcome, assessment: input.assessment };
674
+ }
675
+ page(scope, rows, cursor, size = 30, assignment, active = false, summarize) {
676
+ const branch = cachedBranch(this.session.ctx.sessionManager);
677
+ const compaction = branch.filter((e) => e.type === "compaction").at(-1)?.id;
678
+ let key,
679
+ offset = 0;
680
+ if (cursor) {
681
+ const match = /^([a-f0-9-]+):([0-9]+)$/.exec(cursor);
682
+ check(match, "invalid_cursor", "Use the returned cursor unchanged.");
683
+ key = match[1];
684
+ offset = Number(match[2]);
685
+ const page = this.session.pages.get(key);
686
+ check(
687
+ page &&
688
+ page.scope === scope &&
689
+ page.assignment === assignment &&
690
+ (!page.basis || branch.some((e) => e.id === page.basis)) &&
691
+ (!active || page.compaction === compaction),
692
+ "cursor_expired",
693
+ "History or scope changed. Inspect again without a cursor.",
694
+ );
695
+ check(
696
+ Number.isSafeInteger(offset) && offset >= 0 && offset < page.rows.length && offset % page.size === 0,
697
+ "invalid_cursor",
698
+ );
699
+ } else {
700
+ key = randomUUID();
701
+ if (this.session.pages.size >= 8) this.session.pages.delete(this.session.pages.keys().next().value);
702
+ const items = typeof rows === "function" ? rows() : rows;
703
+ this.session.pages.set(key, {
704
+ scope,
705
+ basis: branch.at(-1)?.id ?? null,
706
+ assignment,
707
+ compaction,
708
+ rows: items,
709
+ size,
710
+ summary: summarize?.(items),
711
+ });
712
+ }
713
+ const page = this.session.pages.get(key);
714
+ return {
715
+ scope,
716
+ count: page.rows.length,
717
+ offset,
718
+ summary: page.summary,
719
+ items: page.rows.slice(offset, offset + page.size),
720
+ nextCursor: offset + page.size < page.rows.length ? `${key}:${offset + page.size}` : undefined,
721
+ };
722
+ }
723
+ inspectUnit(input) {
724
+ const state = this.session.stateData(),
725
+ view = input.view ?? "current";
726
+ check(view === "detail" || !input.ref, "invalid_inspection", "A work ref belongs to view detail.");
727
+ check(
728
+ view === "history" || (!input.cursor && !input.limit),
729
+ "invalid_inspection",
730
+ "Pagination belongs to view history.",
731
+ );
732
+ if (view === "current")
733
+ return {
734
+ ...this.status.detail(),
735
+ status: "inspected",
736
+ view,
737
+ currentRef: state.assignmentId ? `assignment:${state.assignmentId}` : undefined,
738
+ };
739
+ if (view === "history") {
740
+ const numbers = new Map([...state.units.keys()].map((id, i) => [id, i + 1]));
741
+ const rows = () =>
742
+ [...state.assignments.values()].reverse().map((a) => {
743
+ const u = state.units.get(a.unitId),
744
+ h = a.returnHandoffId ? state.handoffs.get(a.returnHandoffId) : undefined;
745
+ const delegate = state.handoffs.get(a.delegateHandoffId);
746
+ return {
747
+ ref: `assignment:${a.id}`,
748
+ unitRef: `unit:${a.unitId}`,
749
+ unitNumber: numbers.get(a.unitId),
750
+ assignmentNumber: (u?.assignmentIds.indexOf(a.id) ?? 0) + 1,
751
+ state: a.state,
752
+ unitState: u?.state,
753
+ disposition: u?.disposition,
754
+ summary: a.contract.slice(0, 160),
755
+ reportAvailable: !!h,
756
+ outcome: h?.outcome,
757
+ from: delegate?.from,
758
+ to: delegate?.to,
759
+ };
760
+ });
761
+ const page = this.page("work-history", rows, input.cursor, input.limit ?? 20);
762
+ return {
763
+ status: "inspected",
764
+ view,
765
+ history: page.items,
766
+ count: page.count,
767
+ returned: page.items.length,
768
+ nextCursor: page.nextCursor,
769
+ };
770
+ }
771
+ check(
772
+ view === "detail" && typeof input.ref === "string",
773
+ "work_ref_required",
774
+ "Use a ref returned by history inspection.",
775
+ );
776
+ check(
777
+ /^(?:(?:unit|assignment|recovery):[^:\s]+|(?:report|supplement):[^:\s]+:[1-9][0-9]*)$/.test(input.ref),
778
+ "invalid_work_ref",
779
+ "Use assignment, report, recovery, or supplement refs returned by a receipt or inspection, unchanged. A bare handoff ID is not a work ref.",
780
+ );
781
+ if (input.ref.startsWith("unit:")) {
782
+ const u = state.units.get(input.ref.slice(5));
783
+ check(u, "work_unavailable", "Unit is not on current ancestry.");
784
+ return {
785
+ status: "inspected",
786
+ view,
787
+ ref: input.ref,
788
+ unit: {
789
+ id: u.id,
790
+ state: u.state,
791
+ objective: u.objective,
792
+ disposition: u.disposition,
793
+ assessment: u.assessment,
794
+ },
795
+ assignmentCount: u.assignmentIds.length,
796
+ assignmentRefs: u.assignmentIds.slice(0, 30).map((id) => `assignment:${id}`),
797
+ remaining: Math.max(0, u.assignmentIds.length - 30),
798
+ historyHint: "Use paginated history inspection for all assignment refs.",
799
+ historical: true,
800
+ };
801
+ }
802
+ if (input.ref.startsWith("recovery:")) {
803
+ const recovery = state.recoveries.get(input.ref.slice(9));
804
+ check(recovery, "work_unavailable", "Recovery is not on current ancestry.");
805
+ const request = state.handoffs.get(recovery.requestHandoffId);
806
+ const supplement = recovery.supplementHandoffId ? state.handoffs.get(recovery.supplementHandoffId) : undefined;
807
+ return {
808
+ status: "inspected",
809
+ view,
810
+ ref: input.ref,
811
+ historical: recovery.id !== state.recoveryId,
812
+ recovery: {
813
+ id: recovery.id,
814
+ state: recovery.state,
815
+ assignmentId: recovery.assignmentId,
816
+ assessmentHandoffId: recovery.assessmentHandoffId,
817
+ baseReportRevision: recovery.baseReportRevision,
818
+ request: recovery.request,
819
+ paths: recovery.paths,
820
+ results: recovery.results ?? [],
821
+ requestHandoffState: request?.state,
822
+ supplementRevision: recovery.supplementRevision,
823
+ cancellationReason: recovery.cancellationReason,
824
+ },
825
+ supplementRef: supplement ? `supplement:${recovery.id}:${supplement.reportRevision}` : undefined,
826
+ sourceBoundary: "Saved recovery on current ancestry; historical content grants no current permission.",
827
+ };
828
+ }
829
+ if (input.ref.startsWith("supplement:")) {
830
+ const match = /^supplement:([^:]+):([0-9]+)$/.exec(input.ref);
831
+ check(match, "work_unavailable", "Use a supplement ref returned by a receipt or recovery inspection.");
832
+ const recovery = state.recoveries.get(match[1]);
833
+ let supplement;
834
+ for (const event of state.events.values())
835
+ if (
836
+ event.data.type === "recovery-supplement-accepted" &&
837
+ event.data.recoveryId === match[1] &&
838
+ event.data.handoff.reportRevision === Number(match[2])
839
+ )
840
+ supplement = event.data.handoff;
841
+ check(recovery && supplement, "work_unavailable", "Supplement revision is not on current ancestry.");
842
+ const base = state.handoffs.get(recovery.assessmentHandoffId);
843
+ return {
844
+ status: "inspected",
845
+ view,
846
+ ref: input.ref,
847
+ historical: true,
848
+ recoveryRef: `recovery:${recovery.id}`,
849
+ assignment: { id: recovery.assignmentId, state: state.assignments.get(recovery.assignmentId)?.state },
850
+ reportRef: `report:${recovery.assessmentHandoffId}:${recovery.baseReportRevision}`,
851
+ report: base?.text,
852
+ supplement: supplement.text,
853
+ supplementRevision: supplement.reportRevision,
854
+ outcome: supplement.outcome,
855
+ limitations: supplement.limitations,
856
+ sourceBoundary:
857
+ "Saved supplement revision and original report linkage on current ancestry; historical content grants no current permission.",
858
+ };
859
+ }
860
+ let savedRevision;
861
+ if (input.ref.startsWith("report:")) {
862
+ const match = /^report:([^:]+):([0-9]+)$/.exec(input.ref);
863
+ check(match, "work_unavailable", "Use a report ref returned by detail inspection.");
864
+ for (const event of state.events.values())
865
+ if (
866
+ event.data.type === "return-accepted" &&
867
+ event.data.handoff.id === match[1] &&
868
+ event.data.handoff.reportRevision === Number(match[2])
869
+ )
870
+ savedRevision = event.data.handoff;
871
+ check(savedRevision, "work_unavailable", "Report revision is not on current ancestry.");
872
+ }
873
+ const a = savedRevision
874
+ ? state.assignments.get(savedRevision.assignmentId)
875
+ : input.ref.startsWith("assignment:")
876
+ ? state.assignments.get(input.ref.slice(11))
877
+ : undefined;
878
+ check(a, "work_unavailable", "Assignment is not on current ancestry.");
879
+ const latest = a.returnHandoffId ? state.handoffs.get(a.returnHandoffId) : undefined;
880
+ const h = savedRevision ?? latest;
881
+ return {
882
+ status: "inspected",
883
+ view,
884
+ ref: input.ref,
885
+ historical: a.id !== state.assignmentId || a.state !== "outstanding",
886
+ assignment: { id: a.id, unitId: a.unitId, state: a.state },
887
+ contract: a.contract,
888
+ report: h?.text,
889
+ reportRevision: h?.reportRevision,
890
+ latestReportRevision: latest?.reportRevision,
891
+ reportRef: h ? `report:${h.id}:${h.reportRevision}` : undefined,
892
+ previousReportRef: h && h.reportRevision > 1 ? `report:${h.id}:${h.reportRevision - 1}` : undefined,
893
+ outcome: h?.outcome,
894
+ limitations: h?.limitations,
895
+ handoff: h?.id,
896
+ currentSelection: state.selections.get(a.id) ?? emptySelection(),
897
+ sourceBoundary:
898
+ "Accepted report revision on current ancestry; assignment/selection show current recorded state. Historical content grants no current permission.",
899
+ };
900
+ }
901
+ }