@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
@@ -1,23 +1,15 @@
1
+ // One subject: the host-neutral part of running an arm's agent. It materializes the declared environment, fixture,
2
+ // runtime and Freeflow settings, asks the arm's host adapter (hosts/) to launch the agent, and turns what the host
3
+ // observed into the arm's run record. Everything that depends on the host program lives in its adapter.
4
+
1
5
  import { createHash } from "node:crypto";
2
- import { spawn } from "node:child_process";
3
- import { once } from "node:events";
4
- import { createWriteStream } from "node:fs";
5
6
  import { mkdir, readFile, realpath } from "node:fs/promises";
6
7
  import path from "node:path";
7
- import { fileURLToPath } from "node:url";
8
8
 
9
- import {
10
- mergeUsage,
11
- messageText,
12
- NO_PROGRESS_MS,
13
- pipeStream,
14
- processGroupExists,
15
- signalProcessTree,
16
- TERMINATION_GRACE_MS,
17
- waitForForcedKill,
18
- writeStream,
19
- } from "./process.mjs";
20
- import { runRpcBodySession, runRpcDescriptionSession } from "./rpc.mjs";
9
+ import { baseProcessEnvironment } from "./process.mjs";
10
+ import { writeFreeflowSettings } from "./freeflow.mjs";
11
+ import { runMetrics } from "./hooks.mjs";
12
+ import { hostAdapter } from "./hosts/index.mjs";
21
13
  import {
22
14
  fingerprintDirectory,
23
15
  materializeEnvironment,
@@ -26,29 +18,17 @@ import {
26
18
  snapshotWorkspace,
27
19
  verifyEnvironment,
28
20
  verifyRuntime,
21
+ WORKSPACE,
29
22
  workspaceChanges,
30
23
  } from "./sandbox.mjs";
31
24
 
32
- const guardExtension = fileURLToPath(new URL("../pi-guard.mjs", import.meta.url));
33
- const observerExtension = fileURLToPath(new URL("../pi-observer.mjs", import.meta.url));
34
- const HOST_COMMANDS = { pi: "pi", piflow: "piflow" };
35
- const BASE_PROCESS_ENVIRONMENT_KEYS = [
36
- "PATH",
37
- "HOME",
38
- "TMPDIR",
39
- "TMP",
40
- "TEMP",
41
- "LANG",
42
- "LC_ALL",
43
- "XDG_CONFIG_HOME",
44
- "XDG_DATA_HOME",
45
- "XDG_CACHE_HOME",
46
- "PIFLOW_CODING_AGENT_DIR",
47
- "PIFLOW_CODING_AGENT_SESSION_DIR",
48
- "PI_PACKAGE_DIR",
49
- "PI_OFFLINE",
50
- ];
51
25
  const TURN_WORKSPACE_KINDS = new Set(["path", "changed-paths", "file-text", "json"]);
26
+ // Tools whose commands run in the subject's container when it has one: bash, and Freeflow's background commands.
27
+ const CONTAINER_SHELL_TOOLS = new Set(["bash", "bash_background", "monitor"]);
28
+ // Freeflow's background commands save their output under the subject's temp directory and name that file to the
29
+ // model, which reads it with read or from bash; with them declared, that directory is readable (and, in a container,
30
+ // mounted read-only at its own path).
31
+ const BACKGROUND_TOOLS = new Set(["bash_background", "monitor"]);
52
32
 
53
33
  export class VariantSetupError extends Error {
54
34
  constructor(message) {
@@ -57,39 +37,91 @@ export class VariantSetupError extends Error {
57
37
  }
58
38
  }
59
39
 
60
- export async function runDescription({ group, variant, root, variantDirectory, fixture, runtime, signal }) {
61
- if (group.input.turns !== undefined) {
62
- return runPersistentDescription({ group, variant, root, variantDirectory, fixture, runtime, signal });
63
- }
64
- return runOneShotDescription({ group, variant, root, variantDirectory, fixture, runtime, signal });
40
+ export async function runDescription({
41
+ group,
42
+ variant,
43
+ root,
44
+ variantDirectory,
45
+ fixture,
46
+ runtime,
47
+ freeflow,
48
+ hostExtensions,
49
+ signal,
50
+ extendEnvironment = null,
51
+ }) {
52
+ const options = { group, variant, root, variantDirectory, fixture, runtime, freeflow, hostExtensions, signal };
53
+ options.extendEnvironment = extendEnvironment;
54
+ if (group.input.turns !== undefined) return runPersistentDescription(options);
55
+ return runOneShotDescription(options);
65
56
  }
66
57
 
67
- export async function runBody({ group, variant, root, variantDirectory, fixture, runtime, signal }) {
68
- const options = { group, variant, root, variantDirectory, fixture, runtime, signal };
58
+ export async function runBody({
59
+ group,
60
+ variant,
61
+ root,
62
+ variantDirectory,
63
+ fixture,
64
+ runtime,
65
+ freeflow,
66
+ hostExtensions,
67
+ signal,
68
+ extendEnvironment = null,
69
+ nextPrompt = null,
70
+ }) {
71
+ const options = { group, variant, root, variantDirectory, fixture, runtime, freeflow, hostExtensions, signal };
72
+ options.extendEnvironment = extendEnvironment;
69
73
  const subject = await prepareSubject(options, "rpc");
70
- const before = await fingerprintDirectory(subject.workspace);
74
+ const before = await fingerprintDirectory(subject.workspace, WORKSPACE);
71
75
  const declaredPrompts = group.input.prompt === undefined ? [...group.input.turns] : [group.input.prompt];
72
- const observation = await runRpcBodySession({
73
- command: subject.host.command,
74
- args: subject.args,
75
- cwd: subject.workspace,
76
- eventsFile: subject.eventsFile,
77
- stderrFile: subject.stderrFile,
78
- signal,
79
- prompts: declaredPrompts,
80
- targetPath: subject.environment.targetPath,
81
- environment: subject.processEnvironment,
82
- afterTurn: needsTurnWorkspaceEvidence(group)
83
- ? (turn) => snapshotWorkspace({ workspace: subject.workspace, variantDirectory, turn, before })
84
- : null,
85
- });
76
+ // A container environment runs the subject's bash and declared commands in a container of its own, removed even
77
+ // when the run is cancelled. A group with neither needs no subject container; its graders still run in the image.
78
+ const usesContainer =
79
+ group.tools.some((tool) => CONTAINER_SHELL_TOOLS.has(tool)) || (group.commands?.length ?? 0) > 0;
80
+ const declaredContainer = usesContainer ? group.variants[variant].shell?.container : undefined;
81
+ let container = null;
82
+ if (declaredContainer !== undefined) {
83
+ const { containerTarget, startContainer } = await import("./container.mjs");
84
+ // The subject's declared resources are mounted read-only at the paths it was given, so its bash can run a
85
+ // skill's scripts; the workspace is the only writable mount.
86
+ container = await startContainer({
87
+ container: declaredContainer,
88
+ workspace: subject.workspace,
89
+ resources: subject.resourceRoots,
90
+ });
91
+ subject.processEnvironment.SKILL_EVAL_CONTAINER = containerTarget(container);
92
+ }
93
+ let observation;
94
+ try {
95
+ observation = await subject.adapter.runSession({
96
+ subject,
97
+ command: subject.host.command,
98
+ settings: subject.isolation.settings,
99
+ args: subject.args,
100
+ cwd: subject.workspace,
101
+ eventsFile: subject.eventsFile,
102
+ stderrFile: subject.stderrFile,
103
+ signal,
104
+ prompts: declaredPrompts,
105
+ resumeBefore: group.input.resume_before ?? [],
106
+ targetPath: subject.environment.targetPath,
107
+ environment: subject.processEnvironment,
108
+ nextPrompt,
109
+ afterTurn: needsTurnWorkspaceEvidence(group)
110
+ ? (turn) => snapshotWorkspace({ workspace: subject.workspace, variantDirectory, turn, before })
111
+ : null,
112
+ });
113
+ } finally {
114
+ await container?.remove();
115
+ }
86
116
  const contextObservation = await readContextObservations(
87
117
  subject.contextObservationPath,
88
118
  subject.requiresContextObservation,
89
119
  );
90
120
  observation.contextObservationArtifact = contextObservation.artifact;
121
+ if (contextObservation.error) (observation.protocolErrors ??= []).push(contextObservation.error);
91
122
  await verifySubjectResources(subject, observation);
92
- const after = await fingerprintDirectory(subject.workspace);
123
+ // Links the subject made are recorded with their targets, never followed, so an installer's link cannot lose the run.
124
+ const after = await fingerprintDirectory(subject.workspace, WORKSPACE);
93
125
 
94
126
  const turns = [];
95
127
  for (const [index, turn] of observation.turns.entries()) {
@@ -106,6 +138,9 @@ export async function runBody({ group, variant, root, variantDirectory, fixture,
106
138
  assistantError: turn.assistantError,
107
139
  settled: turn.settled,
108
140
  workspace: turn.workspace ?? null,
141
+ ...(turn.resumed ? { resumed: turn.resumed } : {}),
142
+ // Runs Pi started on its own after this turn's prompt (an extension's notice), whose activity is part of it.
143
+ ...(turn.unpromptedRuns ? { unpromptedRuns: turn.unpromptedRuns } : {}),
109
144
  });
110
145
  }
111
146
 
@@ -142,7 +177,7 @@ function bodyRun(options, subject, observation, input, effects) {
142
177
  }
143
178
 
144
179
  function subjectRun({ group, variant }, subject, observation) {
145
- return {
180
+ const run = {
146
181
  schema_version: 1,
147
182
  variant,
148
183
  state: subjectRunState(observation),
@@ -150,8 +185,9 @@ function subjectRun({ group, variant }, subject, observation) {
150
185
  completedAt: new Date().toISOString(),
151
186
  workspace: subject.workspace,
152
187
  tools: [...group.tools],
188
+ commands: group.commands ?? [],
153
189
  model: {
154
- declared: group.model ?? null,
190
+ declared: group.variants[variant].model ?? null,
155
191
  observed: observation.model,
156
192
  },
157
193
  resources: {
@@ -160,9 +196,14 @@ function subjectRun({ group, variant }, subject, observation) {
160
196
  skills: subject.environment.skills,
161
197
  context: subject.environment.context,
162
198
  runtime: subject.runtime,
199
+ freeflow: subject.freeflow,
200
+ hostExtensions: subject.hostExtensions,
163
201
  contextDelivery: subject.environment.contextDelivery,
164
202
  targetPath: subject.environment.targetPath,
203
+ // Everything the subject's tools could read: the workspace first, then its declared resources.
204
+ readableRoots: [subject.workspaceRoot, ...subject.resourceRoots],
165
205
  },
206
+ isolation: subject.isolation,
166
207
  contextObservationArtifact: observation.contextObservationArtifact ?? null,
167
208
  response: observation.response,
168
209
  transcript: observation.transcript,
@@ -181,17 +222,24 @@ function subjectRun({ group, variant }, subject, observation) {
181
222
  stderr: subject.stderrFile,
182
223
  },
183
224
  };
225
+ // Run-metrics hooks derive their fields from what this run already recorded.
226
+ const metrics = runMetrics({ group, arm: variant, subject, observation, run });
227
+ if (metrics !== null) run.metrics = metrics;
228
+ return run;
184
229
  }
185
230
 
186
231
  async function runOneShotDescription(options) {
187
232
  const subject = await prepareSubject(options, "json");
188
- const observation = await runPiProcess({
233
+ const observation = await subject.adapter.runOneShot({
234
+ subject,
189
235
  command: subject.host.command,
190
236
  args: subject.args,
191
237
  cwd: subject.workspace,
192
238
  eventsFile: subject.eventsFile,
193
239
  stderrFile: subject.stderrFile,
194
240
  signal: options.signal,
241
+ // Pi takes the prompt as its last argument (`args`); a host that reads prompts from stdin takes it here.
242
+ prompts: [options.group.input.prompt],
195
243
  environment: subject.processEnvironment,
196
244
  });
197
245
  const contextObservation = await readContextObservations(
@@ -199,12 +247,14 @@ async function runOneShotDescription(options) {
199
247
  subject.requiresContextObservation,
200
248
  );
201
249
  observation.contextObservationArtifact = contextObservation.artifact;
250
+ if (contextObservation.error) (observation.protocolErrors ??= []).push(contextObservation.error);
202
251
  await verifySubjectResources(subject, observation);
203
252
  const successfulReadPaths = await canonicalReadPaths(observation.successfulReads, subject.workspace);
204
253
  const targetRead =
205
254
  subject.environment.targetPath !== null && successfulReadPaths.includes(subject.environment.targetPath);
206
255
  return descriptionRun(options, subject, observation, {
207
256
  input: { prompt: options.group.input.prompt },
257
+ toolActivity: observation.toolActivity ?? [],
208
258
  activation: {
209
259
  targetRead,
210
260
  firstReadTurn: targetRead ? 1 : null,
@@ -216,8 +266,10 @@ async function runOneShotDescription(options) {
216
266
 
217
267
  async function runPersistentDescription(options) {
218
268
  const subject = await prepareSubject(options, "rpc");
219
- const observation = await runRpcDescriptionSession({
269
+ const observation = await subject.adapter.runSession({
270
+ subject,
220
271
  command: subject.host.command,
272
+ settings: subject.isolation.settings,
221
273
  args: subject.args,
222
274
  cwd: subject.workspace,
223
275
  eventsFile: subject.eventsFile,
@@ -231,6 +283,7 @@ async function runPersistentDescription(options) {
231
283
  subject.requiresContextObservation,
232
284
  );
233
285
  observation.contextObservationArtifact = contextObservation.artifact;
286
+ if (contextObservation.error) (observation.protocolErrors ??= []).push(contextObservation.error);
234
287
  await verifySubjectResources(subject, observation);
235
288
 
236
289
  const turns = [];
@@ -264,59 +317,139 @@ async function runPersistentDescription(options) {
264
317
  });
265
318
  }
266
319
 
267
- async function prepareSubject({ group, variant, root, variantDirectory, fixture: fixtureSnapshot, runtime }, mode) {
320
+ async function prepareSubject(
321
+ {
322
+ group,
323
+ variant,
324
+ root,
325
+ variantDirectory,
326
+ fixture: fixtureSnapshot,
327
+ runtime,
328
+ freeflow = null,
329
+ hostExtensions = [],
330
+ extendEnvironment = null,
331
+ },
332
+ mode,
333
+ ) {
268
334
  const workspace = path.join(variantDirectory, "workspace");
269
335
 
270
336
  let environment;
271
337
  let fixture;
272
338
  let materializedRuntime;
339
+ let adapter;
340
+ let isolation;
273
341
  try {
274
342
  environment = await materializeEnvironment({
275
343
  environment: group.variants[variant],
276
344
  root,
277
345
  variantDirectory,
278
346
  });
347
+ // A pipeline stage adds what it declares it sees from earlier stages as further declared context.
348
+ if (extendEnvironment !== null) await extendEnvironment(environment, variantDirectory);
279
349
  materializedRuntime = await materializeRuntime({ runtime, variantDirectory });
350
+ // Runtime environment literals may differ between arms (definitions.mjs); each subject gets its arm's own.
351
+ const literal = group.variants[variant].runtimeLiteral;
352
+ if (literal !== undefined) materializedRuntime.environment = { ...materializedRuntime.environment, literal };
280
353
  fixture = await materializeFixture({ fixture: fixtureSnapshot, workspace });
354
+ // Written before the workspace's starting state is taken, so they never count as the subject's changes.
355
+ if (freeflow !== null) await writeFreeflowSettings(workspace, freeflow);
356
+ adapter = hostAdapter(materializedRuntime.host);
357
+ isolation = await adapter.prepareIsolation(variantDirectory, group.variants[variant].model?.model ?? null, {
358
+ settings: adapter.effectiveSettings(group.variants[variant].hostSettings ?? {}),
359
+ });
281
360
  } catch (error) {
282
361
  if (error instanceof VariantSetupError) throw error;
283
362
  throw new VariantSetupError(error instanceof Error ? error.message : String(error));
284
363
  }
285
364
 
286
- const host = { name: materializedRuntime.host, command: HOST_COMMANDS[materializedRuntime.host] };
365
+ const host = { name: materializedRuntime.host, command: adapter.command };
287
366
  const contextObservationPath = path.join(variantDirectory, "context-observations.jsonl");
288
367
  const requiresContextObservation = group.expectations.some((expectation) => expectation.kind === "context-text");
289
368
  const sessionDirectory = path.join(variantDirectory, "session");
290
369
  if (materializedRuntime.session) await mkdir(sessionDirectory, { recursive: true });
291
- const args = piArguments(group, environment, materializedRuntime, mode, requiresContextObservation, sessionDirectory);
292
370
  const allowedRoots = [
293
371
  await realpath(workspace),
294
372
  ...environment.skills.map((skill) => skill.path),
295
373
  ...environment.context.map((entry) => entry.path),
296
374
  ...materializedRuntime.extensions.flatMap((bundle) => bundle.resources.map((resource) => resource.path)),
375
+ // Freeflow points the subject at its own skills and references inside the package.
376
+ ...(freeflow === null ? [] : [freeflow.packageRoot]),
377
+ ...(group.tools.some((tool) => BACKGROUND_TOOLS.has(tool)) && isolation.environment.TMPDIR
378
+ ? [isolation.environment.TMPDIR]
379
+ : []),
297
380
  ];
381
+ let launch;
382
+ try {
383
+ launch = await adapter.prepareLaunch({
384
+ group,
385
+ variant,
386
+ environment,
387
+ runtime: materializedRuntime,
388
+ mode,
389
+ observeContext: requiresContextObservation,
390
+ contextObservationPath,
391
+ sessionDirectory,
392
+ model: group.variants[variant].model,
393
+ freeflowEntry: freeflow?.entry ?? null,
394
+ hostExtensions,
395
+ workspace,
396
+ variantDirectory,
397
+ allowedRoots,
398
+ isolation: isolation.evidence,
399
+ });
400
+ } catch (error) {
401
+ if (error instanceof VariantSetupError) throw error;
402
+ throw new VariantSetupError(error instanceof Error ? error.message : String(error));
403
+ }
298
404
  return {
299
- args,
405
+ adapter,
406
+ args: launch.args,
300
407
  environment,
408
+ hostExtensions,
409
+ freeflow:
410
+ freeflow === null
411
+ ? null
412
+ : {
413
+ ref: freeflow.ref,
414
+ commit: freeflow.commit,
415
+ package: freeflow.package,
416
+ tarballSha256: freeflow.tarballSha256,
417
+ metadata: freeflow.metadata,
418
+ repository: freeflow.repository,
419
+ personal: freeflow.personal,
420
+ },
421
+ // Where the built Freeflow package lies, so metrics can tell its skill reads apart; not recorded in run.json.
422
+ freeflowRoot: freeflow?.packageRoot ?? null,
301
423
  runtime: materializedRuntime,
302
424
  host,
303
425
  fixture,
304
426
  workspace,
427
+ workspaceRoot: allowedRoots[0],
428
+ // Every readable root but the workspace: the declared skills, context, runtime resources and Freeflow's package.
429
+ resourceRoots: allowedRoots.slice(1),
305
430
  contextObservationPath,
306
431
  requiresContextObservation,
307
432
  sessionDirectory,
308
433
  eventsFile: path.join(variantDirectory, "events.jsonl"),
309
434
  stderrFile: path.join(variantDirectory, "stderr.log"),
310
435
  startedAt: new Date().toISOString(),
311
- processEnvironment: createProcessEnvironment({
312
- runtime: materializedRuntime,
313
- group,
314
- workspace,
315
- allowedRoots,
316
- contextManifestPath: environment.contextDelivery.manifestPath,
317
- contextObservationPath,
318
- requiresContextObservation,
319
- }),
436
+ isolation: isolation.evidence,
437
+ processEnvironment: {
438
+ ...createProcessEnvironment({
439
+ runtime: materializedRuntime,
440
+ group,
441
+ workspace,
442
+ allowedRoots,
443
+ contextManifestPath: environment.contextDelivery.manifestPath,
444
+ contextObservationPath,
445
+ requiresContextObservation,
446
+ hostEnvironment: launch.environment,
447
+ }),
448
+ // A declared shell lets the guard allow bash; its isolation extension runs it.
449
+ ...(group.variants[variant].shell ? { SKILL_EVAL_SHELL: JSON.stringify(group.variants[variant].shell) } : {}),
450
+ // Last, so nothing inherited or declared can point the subject back at the parent's home or Pi settings.
451
+ ...isolation.environment,
452
+ },
320
453
  };
321
454
  }
322
455
 
@@ -328,21 +461,22 @@ function createProcessEnvironment({
328
461
  contextManifestPath,
329
462
  contextObservationPath,
330
463
  requiresContextObservation,
464
+ hostEnvironment,
331
465
  }) {
332
- const processEnvironment = Object.fromEntries(
333
- BASE_PROCESS_ENVIRONMENT_KEYS.flatMap((key) => (process.env[key] === undefined ? [] : [[key, process.env[key]]])),
334
- );
466
+ const processEnvironment = baseProcessEnvironment();
335
467
  Object.assign(processEnvironment, {
336
468
  PWD: workspace,
337
469
  ...runtime.environment.literal,
338
- PI_SKIP_VERSION_CHECK: "1",
339
- PI_TELEMETRY: "0",
470
+ // The host's own variables, such as Pi's version check and telemetry switches, after declared literals.
471
+ ...hostEnvironment,
340
472
  SKILL_EVAL_ALLOWED_ROOTS: JSON.stringify(allowedRoots),
341
473
  SKILL_EVAL_WRITABLE_ROOT: workspace,
342
474
  SKILL_EVAL_ALLOWED_TOOLS: JSON.stringify(group.tools),
343
475
  SKILL_EVAL_CONTEXT_MANIFEST: contextManifestPath ?? "",
344
476
  SKILL_EVAL_HOST: runtime.host,
477
+ SKILL_EVAL_PROMPT_MODE: runtime.prompt,
345
478
  });
479
+ if (group.commands !== undefined) processEnvironment.SKILL_EVAL_COMMANDS = JSON.stringify(group.commands);
346
480
  for (const key of runtime.environment.inherit) {
347
481
  if (process.env[key] === undefined) {
348
482
  throw new VariantSetupError(`inherited runtime environment variable is unavailable: ${key}`);
@@ -353,24 +487,39 @@ function createProcessEnvironment({
353
487
  return processEnvironment;
354
488
  }
355
489
 
490
+ // A missing or malformed observation fails the subject but keeps everything the process already reported:
491
+ // transcript, response, usage, and process evidence stay in run.json.
356
492
  async function readContextObservations(file, required) {
357
- const contents = await readFile(file, "utf8").catch((error) => {
358
- if (error?.code === "ENOENT") {
359
- if (required) throw new Error("context observer produced no evidence");
360
- return "";
361
- }
362
- throw error;
363
- });
493
+ let contents;
494
+ try {
495
+ contents = await readFile(file, "utf8");
496
+ } catch (error) {
497
+ if (error?.code !== "ENOENT") throw error;
498
+ if (!required) return { observations: [], artifact: null, error: null };
499
+ return {
500
+ observations: [],
501
+ artifact: null,
502
+ error: { reason: "context-observer-missing", message: "context observer produced no evidence" },
503
+ };
504
+ }
364
505
  const observations = [];
365
506
  for (const line of contents.split("\n").filter(Boolean)) {
366
507
  try {
367
508
  observations.push(JSON.parse(line));
368
509
  } catch (error) {
369
- throw new Error(`context observation is malformed: ${error instanceof Error ? error.message : String(error)}`);
510
+ return {
511
+ observations: [],
512
+ artifact: null,
513
+ error: {
514
+ reason: "context-observation-malformed",
515
+ message: `context observation is malformed: ${error instanceof Error ? error.message : String(error)}`,
516
+ },
517
+ };
370
518
  }
371
519
  }
372
520
  return {
373
521
  observations,
522
+ error: null,
374
523
  artifact:
375
524
  contents === ""
376
525
  ? null
@@ -397,11 +546,12 @@ async function verifySubjectResources(subject, observation) {
397
546
  }
398
547
  }
399
548
 
400
- function descriptionRun(options, subject, observation, { input, activation }) {
549
+ function descriptionRun(options, subject, observation, { input, activation, toolActivity }) {
401
550
  return {
402
551
  ...subjectRun(options, subject, observation),
403
552
  evaluationType: "description",
404
553
  ...input,
554
+ ...(toolActivity === undefined ? {} : { toolActivity }),
405
555
  activation,
406
556
  };
407
557
  }
@@ -420,179 +570,6 @@ function subjectRunState(observation) {
420
570
  return "infrastructure-failed";
421
571
  }
422
572
 
423
- function piArguments(group, environment, runtime, mode, observeContext, sessionDirectory) {
424
- const args = ["--mode", mode];
425
- if (mode === "json") args.push("-p");
426
- if (runtime.session) args.push("--session-dir", sessionDirectory);
427
- else args.push("--no-session");
428
- args.push("--no-extensions", "--extension", guardExtension);
429
- for (const bundle of runtime.extensions) args.push("--extension", bundle.entry);
430
- if (observeContext) args.push("--extension", observerExtension);
431
- args.push("--no-skills", "--no-prompt-templates", "--no-themes", "--no-context-files", "--no-approve");
432
- if (group.tools.length === 0) args.push("--no-tools");
433
- else args.push("--tools", group.tools.join(","));
434
- for (const skill of environment.skills) args.push("--skill", skill.path);
435
- if (group.model?.model) args.push("--model", group.model.model);
436
- if (group.model?.thinking) args.push("--thinking", group.model.thinking);
437
- if (mode === "json") args.push(group.input.prompt);
438
- return args;
439
- }
440
-
441
- async function runPiProcess({ command, args, cwd, eventsFile, stderrFile, signal, environment }) {
442
- const child = spawn(command, args, {
443
- cwd,
444
- detached: process.platform !== "win32",
445
- env: environment,
446
- shell: false,
447
- stdio: ["ignore", "pipe", "pipe"],
448
- });
449
- const events = createWriteStream(eventsFile, { encoding: "utf8" });
450
- const stderr = createWriteStream(stderrFile, { encoding: "utf8" });
451
- const transcript = [];
452
- const calls = new Map();
453
- const successfulReads = [];
454
- const parseErrors = [];
455
- const protocolErrors = [];
456
- let settled = false;
457
- let response = "";
458
- let usage = null;
459
- let assistantError = null;
460
- let observedModel = null;
461
- let buffer = "";
462
- let eventLine = 0;
463
- const processGroupId = child.pid;
464
- let watchdog;
465
- let forcedKill;
466
- /** @type {Promise<void> | null} */
467
- let forcedKillPromise = null;
468
- let terminationReason = null;
469
-
470
- const resetWatchdog = () => {
471
- clearTimeout(watchdog);
472
- watchdog = setTimeout(() => requestTermination("no-progress-watchdog"), NO_PROGRESS_MS);
473
- watchdog.unref();
474
- };
475
- const requestTermination = (reason) => {
476
- if (terminationReason !== null) return;
477
- terminationReason = reason;
478
- signalProcessTree(processGroupId, child, "SIGTERM");
479
- if (process.platform !== "win32") {
480
- forcedKillPromise = new Promise((resolve) => {
481
- forcedKill = setTimeout(() => {
482
- signalProcessTree(processGroupId, child, "SIGKILL");
483
- resolve();
484
- }, TERMINATION_GRACE_MS);
485
- });
486
- }
487
- };
488
- const onAbort = () => requestTermination("cancelled");
489
- if (signal?.aborted) onAbort();
490
- else signal?.addEventListener("abort", onAbort, { once: true });
491
- resetWatchdog();
492
-
493
- const stderrTask = pipeStream(child.stderr, stderr, resetWatchdog);
494
- const stdoutTask = (async () => {
495
- for await (const chunk of child.stdout) {
496
- resetWatchdog();
497
- buffer += chunk.toString("utf8");
498
- while (true) {
499
- const newline = buffer.indexOf("\n");
500
- if (newline === -1) break;
501
- const line = buffer.slice(0, newline);
502
- buffer = buffer.slice(newline + 1);
503
- await writeStream(events, `${line}\n`);
504
- observeLine(line.endsWith("\r") ? line.slice(0, -1) : line);
505
- }
506
- }
507
- if (buffer.length > 0) {
508
- await writeStream(events, buffer);
509
- observeLine(buffer.endsWith("\r") ? buffer.slice(0, -1) : buffer);
510
- }
511
- events.end();
512
- await once(events, "finish");
513
- })();
514
-
515
- function observeLine(line) {
516
- eventLine += 1;
517
- if (line.trim() === "") return;
518
- let event;
519
- try {
520
- event = JSON.parse(line);
521
- } catch {
522
- parseErrors.push({ line: eventLine, reason: "invalid-json" });
523
- return;
524
- }
525
- if (event.type === "extension_error") {
526
- protocolErrors.push({
527
- reason: "extension-error",
528
- extensionPath: event.extensionPath ?? null,
529
- event: event.event ?? null,
530
- error: event.error ?? null,
531
- });
532
- requestTermination("protocol-error");
533
- }
534
- if (event.type === "agent_settled") settled = true;
535
- if (event.type === "tool_execution_start") {
536
- calls.set(event.toolCallId, { toolName: event.toolName, args: event.args });
537
- }
538
- if (event.type === "tool_execution_end" && !event.isError) {
539
- const call = calls.get(event.toolCallId);
540
- if (call?.toolName === "read" && typeof call.args?.path === "string") {
541
- successfulReads.push(call.args.path);
542
- }
543
- }
544
- if (event.type === "message_end" && event.message) {
545
- transcript.push(event.message);
546
- if (event.message.role === "assistant") {
547
- response = messageText(event.message);
548
- usage = mergeUsage(usage, event.message.usage);
549
- observedModel = {
550
- provider: event.message.provider ?? null,
551
- model: event.message.model ?? null,
552
- };
553
- assistantError =
554
- event.message.stopReason === "error" || event.message.stopReason === "aborted"
555
- ? (event.message.errorMessage ?? `assistant stopped with ${event.message.stopReason}`)
556
- : null;
557
- }
558
- }
559
- }
560
-
561
- let exitCode = null;
562
- let exitSignal = null;
563
- try {
564
- const [code, closedSignal] = await once(child, "close");
565
- exitCode = code;
566
- exitSignal = closedSignal;
567
- await Promise.all([stdoutTask, stderrTask]);
568
- } catch (error) {
569
- requestTermination("process-error");
570
- throw error;
571
- } finally {
572
- clearTimeout(watchdog);
573
- if (forcedKillPromise !== null) {
574
- if (processGroupExists(processGroupId)) await waitForForcedKill(forcedKillPromise);
575
- else clearTimeout(forcedKill);
576
- }
577
- signal?.removeEventListener("abort", onAbort);
578
- }
579
-
580
- return {
581
- exitCode,
582
- signal: exitSignal,
583
- settled,
584
- assistantError,
585
- model: observedModel,
586
- terminationReason,
587
- parseErrors,
588
- protocolErrors,
589
- successfulReads,
590
- transcript,
591
- response,
592
- usage,
593
- };
594
- }
595
-
596
573
  async function canonicalReadPaths(paths, cwd) {
597
574
  const canonical = [];
598
575
  for (const rawPath of paths) {