@hassangameryt/freeflow 0.2.0 → 0.3.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 (639) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude-plugin/marketplace.json +2 -2
  3. package/{plugins/freeflow/.claude-plugin → .claude-plugin}/plugin.json +1 -1
  4. package/{plugins/freeflow/.codex-plugin → .codex-plugin}/plugin.json +1 -1
  5. package/README.md +19 -14
  6. package/assets/freeflow-plugin-icon.png +0 -0
  7. package/{plugins/freeflow/command-surface.json → command-surface.json} +10 -2
  8. package/evals/README.md +32 -0
  9. package/evals/fixtures/copy-conventions.md +31 -0
  10. package/evals/fixtures/output-router/README.md +12 -0
  11. package/evals/fixtures/output-router/failed-command-output.txt +9 -0
  12. package/evals/fixtures/output-router/large-router-manual.md +63 -0
  13. package/evals/fixtures/output-router/native-large-output.txt +40 -0
  14. package/evals/fixtures/output-router/noisy-test-output.txt +30 -0
  15. package/evals/fixtures/output-router/verification-output.txt +8 -0
  16. package/evals/fixtures/tiny-artifact-review-app/README.md +5 -0
  17. package/evals/fixtures/tiny-artifact-review-app/docs/billing-policy.md +10 -0
  18. package/evals/fixtures/tiny-artifact-review-app/docs/specs/billing-webhook-api-draft.md +21 -0
  19. package/evals/fixtures/tiny-artifact-review-app/docs/specs/failed-payment-grace-period.md +24 -0
  20. package/evals/fixtures/tiny-artifact-review-app/docs/specs/immediate-downgrade.md +17 -0
  21. package/evals/fixtures/tiny-artifact-review-app/tests/billing.test.md +8 -0
  22. package/evals/fixtures/tiny-commit-ambiguous-app/.freeflow-eval-setup.sh +15 -0
  23. package/evals/fixtures/tiny-commit-ambiguous-app/README.md +3 -0
  24. package/evals/fixtures/tiny-commit-ambiguous-app/src/billing.ts +5 -0
  25. package/evals/fixtures/tiny-commit-ambiguous-app/src/settings-page.ts +1 -0
  26. package/evals/fixtures/tiny-commit-ambiguous-app/tests/settings.test.md +5 -0
  27. package/evals/fixtures/tiny-commit-app/.freeflow-eval-setup.sh +14 -0
  28. package/evals/fixtures/tiny-commit-app/README.md +3 -0
  29. package/evals/fixtures/tiny-commit-app/docs/specs/settings-title.md +5 -0
  30. package/evals/fixtures/tiny-commit-app/src/billing.ts +5 -0
  31. package/evals/fixtures/tiny-commit-app/src/settings-page.ts +1 -0
  32. package/evals/fixtures/tiny-commit-app/tests/settings.test.md +5 -0
  33. package/evals/fixtures/tiny-commit-everything-app/.freeflow-eval-setup.sh +15 -0
  34. package/evals/fixtures/tiny-commit-everything-app/README.md +3 -0
  35. package/evals/fixtures/tiny-commit-everything-app/docs/specs/settings-title.md +5 -0
  36. package/evals/fixtures/tiny-commit-everything-app/src/billing.ts +5 -0
  37. package/evals/fixtures/tiny-commit-everything-app/src/settings-page.ts +1 -0
  38. package/evals/fixtures/tiny-commit-everything-app/tests/settings.test.md +5 -0
  39. package/evals/fixtures/tiny-commit-staged-app/.freeflow-eval-setup.sh +15 -0
  40. package/evals/fixtures/tiny-commit-staged-app/README.md +3 -0
  41. package/evals/fixtures/tiny-commit-staged-app/docs/specs/settings-title.md +5 -0
  42. package/evals/fixtures/tiny-commit-staged-app/src/billing.ts +5 -0
  43. package/evals/fixtures/tiny-commit-staged-app/src/settings-page.ts +1 -0
  44. package/evals/fixtures/tiny-commit-staged-app/tests/settings.test.md +5 -0
  45. package/evals/fixtures/tiny-commit-staged-mixed-app/.freeflow-eval-setup.sh +15 -0
  46. package/evals/fixtures/tiny-commit-staged-mixed-app/README.md +3 -0
  47. package/evals/fixtures/tiny-commit-staged-mixed-app/docs/billing-policy.md +3 -0
  48. package/evals/fixtures/tiny-commit-staged-mixed-app/docs/release-notes.md +3 -0
  49. package/evals/fixtures/tiny-commit-staged-mixed-app/src/billing.ts +5 -0
  50. package/evals/fixtures/tiny-dashboard-stale-app/README.md +11 -0
  51. package/evals/fixtures/tiny-dashboard-stale-app/src/api-client.ts +13 -0
  52. package/evals/fixtures/tiny-dashboard-stale-app/src/dashboard-data.ts +19 -0
  53. package/evals/fixtures/tiny-dashboard-stale-app/tests/dashboard-data.test.md +9 -0
  54. package/evals/fixtures/tiny-decision-destination-app/README.md +6 -0
  55. package/evals/fixtures/tiny-decision-destination-app/src/risk.ts +8 -0
  56. package/evals/fixtures/tiny-decision-destination-app/tests/risk.test.md +4 -0
  57. package/evals/fixtures/tiny-design-depth-app/README.md +15 -0
  58. package/evals/fixtures/tiny-design-depth-app/src/routes.ts +25 -0
  59. package/evals/fixtures/tiny-design-depth-app/src/sendEmail.ts +3 -0
  60. package/evals/fixtures/tiny-design-depth-app/src/sendSms.ts +3 -0
  61. package/evals/fixtures/tiny-design-depth-app/src/telemetry.ts +3 -0
  62. package/evals/fixtures/tiny-design-depth-app/tests/routes.test.md +12 -0
  63. package/evals/fixtures/tiny-eval-method-app/README.md +8 -0
  64. package/evals/fixtures/tiny-eval-method-app/evals/reports/review-pr-eval-result.md +5 -0
  65. package/evals/fixtures/tiny-eval-method-app/evals/reports/triage-question-failure.md +17 -0
  66. package/evals/fixtures/tiny-eval-method-app/evals/runs/review-pr-with-skill-output.diff +11 -0
  67. package/evals/fixtures/tiny-eval-method-app/evals/runs/review-pr-with-skill-output.md +3 -0
  68. package/evals/fixtures/tiny-eval-method-app/skills/review-pr/SKILL.md +10 -0
  69. package/evals/fixtures/tiny-eval-method-app/skills/triage-question/SKILL.md +10 -0
  70. package/evals/fixtures/tiny-execute-plan-app/README.md +5 -0
  71. package/evals/fixtures/tiny-execute-plan-app/checks/settings-and-billing-check.sh +5 -0
  72. package/evals/fixtures/tiny-execute-plan-app/docs/billing-policy.md +10 -0
  73. package/evals/fixtures/tiny-execute-plan-app/docs/plans/immediate-downgrade-plan.md +11 -0
  74. package/evals/fixtures/tiny-execute-plan-app/docs/plans/settings-title-plan.md +12 -0
  75. package/evals/fixtures/tiny-execute-plan-app/docs/plans/settings-title-with-bad-check.md +15 -0
  76. package/evals/fixtures/tiny-execute-plan-app/docs/plans/unverified-billing-plan.md +9 -0
  77. package/evals/fixtures/tiny-execute-plan-app/docs/specs/failed-payment-grace-period.md +9 -0
  78. package/evals/fixtures/tiny-execute-plan-app/docs/specs/settings-title.md +9 -0
  79. package/evals/fixtures/tiny-execute-plan-app/src/billing.ts +7 -0
  80. package/evals/fixtures/tiny-execute-plan-app/src/settings-page.ts +1 -0
  81. package/evals/fixtures/tiny-execute-plan-app/tests/billing.test.md +7 -0
  82. package/evals/fixtures/tiny-execute-plan-app/tests/settings.test.md +5 -0
  83. package/evals/fixtures/tiny-execute-review-loop-app/README.md +5 -0
  84. package/evals/fixtures/tiny-execute-review-loop-app/docs/billing-policy.md +9 -0
  85. package/evals/fixtures/tiny-execute-review-loop-app/docs/plans/settings-title-plan.md +12 -0
  86. package/evals/fixtures/tiny-execute-review-loop-app/docs/review/previous-agent-summary.md +15 -0
  87. package/evals/fixtures/tiny-execute-review-loop-app/docs/review/review-pass-1-non-pass.md +11 -0
  88. package/evals/fixtures/tiny-execute-review-loop-app/docs/specs/settings-title.md +9 -0
  89. package/evals/fixtures/tiny-execute-review-loop-app/src/billing.ts +7 -0
  90. package/evals/fixtures/tiny-execute-review-loop-app/src/settings-page.ts +1 -0
  91. package/evals/fixtures/tiny-execute-review-loop-app/tests/billing.test.md +7 -0
  92. package/evals/fixtures/tiny-execute-review-loop-app/tests/settings.test.md +5 -0
  93. package/evals/fixtures/tiny-flaky-session-app/README.md +10 -0
  94. package/evals/fixtures/tiny-flaky-session-app/src/session-timeout.ts +13 -0
  95. package/evals/fixtures/tiny-flaky-session-app/tests/session-timeout.test.md +8 -0
  96. package/evals/fixtures/tiny-handoff-app/README.md +5 -0
  97. package/evals/fixtures/tiny-handoff-app/docs/billing-policy.md +10 -0
  98. package/evals/fixtures/tiny-handoff-app/docs/handoffs/old-agent-handoff.md +8 -0
  99. package/evals/fixtures/tiny-handoff-app/docs/plans/billing-retry-plan.md +11 -0
  100. package/evals/fixtures/tiny-handoff-app/src/billing.ts +7 -0
  101. package/evals/fixtures/tiny-handoff-report-app/README.md +3 -0
  102. package/evals/fixtures/tiny-handoff-report-app/evals/runs/handoff-3/hof-003/with-skill-output.diff +1 -0
  103. package/evals/fixtures/tiny-handoff-report-app/evals/runs/handoff-3/hof-003/with-skill-output.md +1 -0
  104. package/evals/fixtures/tiny-handoff-report-app/evals/scores/hof-003-score.txt +4 -0
  105. package/evals/fixtures/tiny-plan-app/README.md +5 -0
  106. package/evals/fixtures/tiny-plan-app/docs/billing-policy.md +10 -0
  107. package/evals/fixtures/tiny-plan-app/docs/specs/failed-payment-grace-period.md +25 -0
  108. package/evals/fixtures/tiny-plan-app/src/billing.ts +17 -0
  109. package/evals/fixtures/tiny-plan-app/src/settings-page.ts +1 -0
  110. package/evals/fixtures/tiny-plan-app/tests/billing.test.md +8 -0
  111. package/evals/fixtures/tiny-plan-app/tests/settings.test.md +5 -0
  112. package/evals/fixtures/tiny-plan-strict-api-app/README.md +3 -0
  113. package/evals/fixtures/tiny-plan-strict-api-app/docs/billing-policy.md +5 -0
  114. package/evals/fixtures/tiny-plan-strict-api-app/docs/specs/billing-webhook-api.md +25 -0
  115. package/evals/fixtures/tiny-plan-strict-api-app/src/billing.ts +5 -0
  116. package/evals/fixtures/tiny-plan-strict-api-app/src/webhooks.ts +3 -0
  117. package/evals/fixtures/tiny-plan-strict-api-app/tests/billing-webhook.test.md +8 -0
  118. package/evals/fixtures/tiny-post-setup-invalid-config-app/.freeflow/config.json +3 -0
  119. package/evals/fixtures/tiny-post-setup-invalid-config-app/AGENTS.md +15 -0
  120. package/evals/fixtures/tiny-post-setup-invalid-config-app/README.md +16 -0
  121. package/evals/fixtures/tiny-post-setup-invalid-config-app/docs/auth-review.md +15 -0
  122. package/evals/fixtures/tiny-post-setup-invalid-config-app/docs/billing-policy.md +10 -0
  123. package/evals/fixtures/tiny-post-setup-invalid-config-app/docs/copy-conventions.md +15 -0
  124. package/evals/fixtures/tiny-post-setup-invalid-config-app/src/auth-middleware.ts +12 -0
  125. package/evals/fixtures/tiny-post-setup-invalid-config-app/src/billing.ts +20 -0
  126. package/evals/fixtures/tiny-post-setup-invalid-config-app/src/login-copy.ts +1 -0
  127. package/evals/fixtures/tiny-post-setup-invalid-config-app/src/settings-page.ts +1 -0
  128. package/evals/fixtures/tiny-post-setup-invalid-config-app/tests/auth-middleware.test.md +8 -0
  129. package/evals/fixtures/tiny-post-setup-invalid-config-app/tests/billing.test.md +8 -0
  130. package/evals/fixtures/tiny-post-setup-invalid-config-app/tests/copy.test.md +7 -0
  131. package/evals/fixtures/tiny-post-setup-missing-config-app/AGENTS.md +15 -0
  132. package/evals/fixtures/tiny-post-setup-missing-config-app/README.md +16 -0
  133. package/evals/fixtures/tiny-post-setup-missing-config-app/docs/auth-review.md +15 -0
  134. package/evals/fixtures/tiny-post-setup-missing-config-app/docs/billing-policy.md +10 -0
  135. package/evals/fixtures/tiny-post-setup-missing-config-app/docs/copy-conventions.md +15 -0
  136. package/evals/fixtures/tiny-post-setup-missing-config-app/src/auth-middleware.ts +12 -0
  137. package/evals/fixtures/tiny-post-setup-missing-config-app/src/billing.ts +20 -0
  138. package/evals/fixtures/tiny-post-setup-missing-config-app/src/login-copy.ts +1 -0
  139. package/evals/fixtures/tiny-post-setup-missing-config-app/src/settings-page.ts +1 -0
  140. package/evals/fixtures/tiny-post-setup-missing-config-app/tests/auth-middleware.test.md +8 -0
  141. package/evals/fixtures/tiny-post-setup-missing-config-app/tests/billing.test.md +8 -0
  142. package/evals/fixtures/tiny-post-setup-missing-config-app/tests/copy.test.md +7 -0
  143. package/evals/fixtures/tiny-post-setup-source-conflict-app/.freeflow/config.json +3 -0
  144. package/evals/fixtures/tiny-post-setup-source-conflict-app/AGENTS.md +15 -0
  145. package/evals/fixtures/tiny-post-setup-source-conflict-app/README.md +16 -0
  146. package/evals/fixtures/tiny-post-setup-source-conflict-app/docs/auth-review.md +15 -0
  147. package/evals/fixtures/tiny-post-setup-source-conflict-app/docs/billing-policy.md +10 -0
  148. package/evals/fixtures/tiny-post-setup-source-conflict-app/docs/copy-conventions.md +15 -0
  149. package/evals/fixtures/tiny-post-setup-source-conflict-app/src/auth-middleware.ts +12 -0
  150. package/evals/fixtures/tiny-post-setup-source-conflict-app/src/billing.ts +20 -0
  151. package/evals/fixtures/tiny-post-setup-source-conflict-app/src/login-copy.ts +1 -0
  152. package/evals/fixtures/tiny-post-setup-source-conflict-app/src/settings-page.ts +1 -0
  153. package/evals/fixtures/tiny-post-setup-source-conflict-app/tests/auth-middleware.test.md +8 -0
  154. package/evals/fixtures/tiny-post-setup-source-conflict-app/tests/billing.test.md +8 -0
  155. package/evals/fixtures/tiny-post-setup-source-conflict-app/tests/copy.test.md +7 -0
  156. package/evals/fixtures/tiny-report-performance-app/README.md +11 -0
  157. package/evals/fixtures/tiny-report-performance-app/docs/performance.md +10 -0
  158. package/evals/fixtures/tiny-report-performance-app/src/report-summary.ts +29 -0
  159. package/evals/fixtures/tiny-report-performance-app/tests/report-performance.test.md +8 -0
  160. package/evals/fixtures/tiny-review-request-app/README.md +3 -0
  161. package/evals/fixtures/tiny-review-request-app/docs/billing-policy.md +5 -0
  162. package/evals/fixtures/tiny-review-request-app/docs/plans/billing-webhook-api.md +19 -0
  163. package/evals/fixtures/tiny-review-request-app/docs/review/previous-agent-summary.md +20 -0
  164. package/evals/fixtures/tiny-review-request-app/docs/specs/billing-webhook-api.md +25 -0
  165. package/evals/fixtures/tiny-review-request-app/src/billing.ts +11 -0
  166. package/evals/fixtures/tiny-review-request-app/src/webhooks.ts +19 -0
  167. package/evals/fixtures/tiny-review-request-app/tests/billing-webhook.test.md +8 -0
  168. package/evals/fixtures/tiny-review-work-app/README.md +5 -0
  169. package/evals/fixtures/tiny-review-work-app/docs/billing-policy.md +9 -0
  170. package/evals/fixtures/tiny-review-work-app/docs/plans/settings-title-plan.md +12 -0
  171. package/evals/fixtures/tiny-review-work-app/docs/review/previous-agent-summary.md +15 -0
  172. package/evals/fixtures/tiny-review-work-app/docs/specs/settings-title.md +9 -0
  173. package/evals/fixtures/tiny-review-work-app/src/billing.ts +7 -0
  174. package/evals/fixtures/tiny-review-work-app/src/settings-page.ts +1 -0
  175. package/evals/fixtures/tiny-review-work-app/tests/billing.test.md +7 -0
  176. package/evals/fixtures/tiny-review-work-app/tests/settings.test.md +5 -0
  177. package/evals/fixtures/tiny-saas-app/README.md +16 -0
  178. package/evals/fixtures/tiny-saas-app/docs/auth-review.md +15 -0
  179. package/evals/fixtures/tiny-saas-app/docs/billing-policy.md +10 -0
  180. package/evals/fixtures/tiny-saas-app/docs/copy-conventions.md +15 -0
  181. package/evals/fixtures/tiny-saas-app/docs/specs/settings-title.md +13 -0
  182. package/evals/fixtures/tiny-saas-app/src/auth-middleware.ts +12 -0
  183. package/evals/fixtures/tiny-saas-app/src/billing.ts +20 -0
  184. package/evals/fixtures/tiny-saas-app/src/login-copy.ts +1 -0
  185. package/evals/fixtures/tiny-saas-app/src/settings-page.ts +1 -0
  186. package/evals/fixtures/tiny-saas-app/tests/auth-middleware.test.md +8 -0
  187. package/evals/fixtures/tiny-saas-app/tests/billing.test.md +8 -0
  188. package/evals/fixtures/tiny-saas-app/tests/copy.test.md +7 -0
  189. package/evals/fixtures/tiny-setup-agents-app/AGENTS.md +6 -0
  190. package/evals/fixtures/tiny-setup-both-app/AGENTS.md +5 -0
  191. package/evals/fixtures/tiny-setup-both-app/CLAUDE.md +5 -0
  192. package/evals/fixtures/tiny-setup-claude-app/CLAUDE.md +6 -0
  193. package/evals/fixtures/tiny-setup-codex-rules-app/.codex/rules/shell.rules +5 -0
  194. package/evals/fixtures/tiny-setup-codex-rules-app/AGENTS.md +6 -0
  195. package/evals/fixtures/tiny-setup-conflict-app/AGENTS.md +6 -0
  196. package/evals/fixtures/tiny-setup-existing-block-app/AGENTS.md +14 -0
  197. package/evals/fixtures/tiny-setup-four-rules-app/CLAUDE.md +6 -0
  198. package/evals/fixtures/tiny-skill-dev-app/README.md +10 -0
  199. package/evals/fixtures/tiny-skill-dev-app/evals/prompts/review-pr-001.txt +8 -0
  200. package/evals/fixtures/tiny-skill-dev-app/evals/reports/review-pr-failure.md +17 -0
  201. package/evals/fixtures/tiny-skill-dev-app/skills/review-pr/SKILL.md +13 -0
  202. package/evals/fixtures/tiny-team-app/README.md +5 -0
  203. package/evals/fixtures/tiny-team-app/docs/product.md +6 -0
  204. package/evals/fixtures/tiny-team-app/src/teams.ts +9 -0
  205. package/evals/fixtures/tiny-team-app/src/users.ts +5 -0
  206. package/evals/fixtures/tiny-team-app/tests/teams.test.md +7 -0
  207. package/evals/fixtures/tiny-verify-app/README.md +5 -0
  208. package/evals/fixtures/tiny-verify-app/src/settings-nav.ts +1 -0
  209. package/evals/fixtures/tiny-verify-app/src/settings-page.ts +1 -0
  210. package/evals/fixtures/tiny-verify-app/tests/settings.test.md +7 -0
  211. package/evals/prompts/aon-001.txt +2 -0
  212. package/evals/prompts/byp-001.txt +2 -0
  213. package/evals/prompts/byp-002.txt +2 -0
  214. package/evals/prompts/cap-001.txt +3 -0
  215. package/evals/prompts/cap-002.txt +3 -0
  216. package/evals/prompts/cmd-001.txt +3 -0
  217. package/evals/prompts/cmd-002.txt +3 -0
  218. package/evals/prompts/cmd-003.txt +6 -0
  219. package/evals/prompts/cmd-004.txt +5 -0
  220. package/evals/prompts/cmd-005.txt +5 -0
  221. package/evals/prompts/cmd-006.txt +5 -0
  222. package/evals/prompts/cmd-007.txt +5 -0
  223. package/evals/prompts/cmd-008.txt +5 -0
  224. package/evals/prompts/cmd-009.txt +8 -0
  225. package/evals/prompts/cmd-010.txt +5 -0
  226. package/evals/prompts/cmd-011.txt +5 -0
  227. package/evals/prompts/cmd-012.txt +5 -0
  228. package/evals/prompts/cmd-013.txt +5 -0
  229. package/evals/prompts/cmd-014.txt +7 -0
  230. package/evals/prompts/cmd-015.txt +7 -0
  231. package/evals/prompts/cmd-016.txt +5 -0
  232. package/evals/prompts/cmt-001.txt +1 -0
  233. package/evals/prompts/cmt-002.txt +1 -0
  234. package/evals/prompts/cmt-003.txt +1 -0
  235. package/evals/prompts/cmt-004.txt +1 -0
  236. package/evals/prompts/cmt-005.txt +1 -0
  237. package/evals/prompts/dfd-001.txt +3 -0
  238. package/evals/prompts/dia-001.txt +3 -0
  239. package/evals/prompts/dia-002.txt +3 -0
  240. package/evals/prompts/dia-003.txt +3 -0
  241. package/evals/prompts/dis-001.txt +5 -0
  242. package/evals/prompts/dis-002.txt +5 -0
  243. package/evals/prompts/esk-001.txt +5 -0
  244. package/evals/prompts/esk-002.txt +5 -0
  245. package/evals/prompts/esk-003.txt +5 -0
  246. package/evals/prompts/grc-001.txt +3 -0
  247. package/evals/prompts/hof-001.txt +3 -0
  248. package/evals/prompts/hof-002.txt +1 -0
  249. package/evals/prompts/hof-003.txt +1 -0
  250. package/evals/prompts/hof-004.txt +1 -0
  251. package/evals/prompts/hof-005.txt +1 -0
  252. package/evals/prompts/ivg-001.txt +1 -0
  253. package/evals/prompts/ivg-002.txt +11 -0
  254. package/evals/prompts/ivg-003.txt +1 -0
  255. package/evals/prompts/ivg-004.txt +1 -0
  256. package/evals/prompts/mode-001.txt +3 -0
  257. package/evals/prompts/mode-002.txt +1 -0
  258. package/evals/prompts/mode-003.txt +3 -0
  259. package/evals/prompts/mode-004.txt +3 -0
  260. package/evals/prompts/mode-005.txt +3 -0
  261. package/evals/prompts/mode-006.txt +3 -0
  262. package/evals/prompts/mode-007.txt +3 -0
  263. package/evals/prompts/otr-001.txt +3 -0
  264. package/evals/prompts/otr-002.txt +3 -0
  265. package/evals/prompts/rar-001.txt +5 -0
  266. package/evals/prompts/rar-002.txt +3 -0
  267. package/evals/prompts/rar-003.txt +6 -0
  268. package/evals/prompts/rar-004.txt +15 -0
  269. package/evals/prompts/rar-005.txt +10 -0
  270. package/evals/prompts/rbr-001.txt +3 -0
  271. package/evals/prompts/rbr-002.txt +3 -0
  272. package/evals/prompts/rbr-003.txt +7 -0
  273. package/evals/prompts/rev-001.txt +3 -0
  274. package/evals/prompts/rev-002.txt +5 -0
  275. package/evals/prompts/rev-003.txt +6 -0
  276. package/evals/prompts/rev-004.txt +1 -0
  277. package/evals/prompts/rev-005.txt +15 -0
  278. package/evals/prompts/rev-006.txt +5 -0
  279. package/evals/prompts/stp-001.txt +1 -0
  280. package/evals/prompts/stp-002.txt +1 -0
  281. package/evals/prompts/stp-003.txt +1 -0
  282. package/evals/prompts/stp-004.txt +1 -0
  283. package/evals/prompts/stp-005.txt +1 -0
  284. package/evals/prompts/stp-006.txt +1 -0
  285. package/evals/prompts/stp-007.txt +1 -0
  286. package/evals/prompts/stp-008.txt +1 -0
  287. package/evals/prompts/stp-009.txt +1 -0
  288. package/evals/prompts/stp-010.txt +1 -0
  289. package/evals/prompts/stp-011.txt +1 -0
  290. package/evals/prompts/vfy-003.txt +1 -0
  291. package/evals/prompts/wpl-001.txt +3 -0
  292. package/evals/prompts/wpl-002.txt +5 -0
  293. package/evals/prompts/wpl-003.txt +3 -0
  294. package/evals/prompts/wpl-004.txt +5 -0
  295. package/evals/prompts/wpl-005.txt +1 -0
  296. package/evals/prompts/wrc-001.txt +10 -0
  297. package/evals/prompts/wrc-002.txt +3 -0
  298. package/evals/prompts/wsk-001.txt +6 -0
  299. package/evals/prompts/wsp-001.txt +5 -0
  300. package/evals/prompts/wsp-002.txt +15 -0
  301. package/evals/prompts/wsp-003.txt +3 -0
  302. package/evals/prompts/wsp-004.txt +15 -0
  303. package/evals/prompts/wsp-005.txt +5 -0
  304. package/evals/prompts/wsp-006.txt +12 -0
  305. package/evals/prompts/wsp-007.txt +9 -0
  306. package/evals/prompts/wsp-008.txt +13 -0
  307. package/evals/prompts/xpl-001.txt +1 -0
  308. package/evals/prompts/xpl-002.txt +3 -0
  309. package/evals/prompts/xpl-003.txt +3 -0
  310. package/evals/prompts/xpl-004.txt +3 -0
  311. package/evals/prompts/xpl-005.txt +5 -0
  312. package/evals/prompts/xpl-006.txt +3 -0
  313. package/evals/registries/adversarial-evals.json +39 -0
  314. package/evals/registries/fixture-evals.json +2513 -0
  315. package/evals/registries/handoff-evals.json +74 -0
  316. package/evals/registries/legacy-evals.json +147 -0
  317. package/evals/registries/skill-evidence.json +193 -0
  318. package/evals/registries/verify-work-evals.json +46 -0
  319. package/evals/reports/acceptance/v0.1-acceptance-report.md +130 -0
  320. package/evals/reports/by-command-surface/command-surface-1-report.md +45 -0
  321. package/evals/reports/by-command-surface/command-surface-10-report.md +76 -0
  322. package/evals/reports/by-command-surface/command-surface-11-report.md +77 -0
  323. package/evals/reports/by-command-surface/command-surface-12-report.md +91 -0
  324. package/evals/reports/by-command-surface/command-surface-13-report.md +64 -0
  325. package/evals/reports/by-command-surface/command-surface-14-report.md +66 -0
  326. package/evals/reports/by-command-surface/command-surface-15-report.md +124 -0
  327. package/evals/reports/by-command-surface/command-surface-16-report.md +39 -0
  328. package/evals/reports/by-command-surface/command-surface-2-report.md +80 -0
  329. package/evals/reports/by-command-surface/command-surface-3-report.md +86 -0
  330. package/evals/reports/by-command-surface/command-surface-4-report.md +76 -0
  331. package/evals/reports/by-command-surface/command-surface-5-report.md +80 -0
  332. package/evals/reports/by-command-surface/command-surface-6-report.md +74 -0
  333. package/evals/reports/by-command-surface/command-surface-7-report.md +84 -0
  334. package/evals/reports/by-command-surface/command-surface-8-report.md +79 -0
  335. package/evals/reports/by-command-surface/command-surface-9-report.md +79 -0
  336. package/evals/reports/by-command-surface/command-surface-matrix.md +91 -0
  337. package/evals/reports/by-skill/bypass-1-report.md +124 -0
  338. package/evals/reports/by-skill/capture-decisions-1-report.md +99 -0
  339. package/evals/reports/by-skill/capture-decisions-2-report.md +102 -0
  340. package/evals/reports/by-skill/commit-work-1-report.md +165 -0
  341. package/evals/reports/by-skill/commit-work-2-report.md +109 -0
  342. package/evals/reports/by-skill/design-for-depth-1-report.md +95 -0
  343. package/evals/reports/by-skill/diagnose-failure-1-report.md +91 -0
  344. package/evals/reports/by-skill/diagnose-failure-2-report.md +94 -0
  345. package/evals/reports/by-skill/discover-1-report.md +118 -0
  346. package/evals/reports/by-skill/evaluate-skill-2-report.md +71 -0
  347. package/evals/reports/by-skill/execute-plan-1-report.md +103 -0
  348. package/evals/reports/by-skill/execute-plan-2-report.md +112 -0
  349. package/evals/reports/by-skill/execute-plan-3-report.md +87 -0
  350. package/evals/reports/by-skill/grill-context-1-report.md +103 -0
  351. package/evals/reports/by-skill/handoff-1-report.md +123 -0
  352. package/evals/reports/by-skill/handoff-2-report.md +105 -0
  353. package/evals/reports/by-skill/handoff-3-report.md +100 -0
  354. package/evals/reports/by-skill/handoff-7-report.md +77 -0
  355. package/evals/reports/by-skill/interview-gate-1-report.md +63 -0
  356. package/evals/reports/by-skill/interview-gate-2-report.md +105 -0
  357. package/evals/reports/by-skill/mode-contract-1-report.md +74 -0
  358. package/evals/reports/by-skill/mode-contract-2-report.md +87 -0
  359. package/evals/reports/by-skill/mode-contract-3-report.md +65 -0
  360. package/evals/reports/by-skill/mode-contract-4-report.md +71 -0
  361. package/evals/reports/by-skill/mode-contract-5-report.md +70 -0
  362. package/evals/reports/by-skill/output-router-1-report.md +76 -0
  363. package/evals/reports/by-skill/output-router-2-report.md +65 -0
  364. package/evals/reports/by-skill/research-1-report.md +144 -0
  365. package/evals/reports/by-skill/research-brief-1-report.md +94 -0
  366. package/evals/reports/by-skill/research-brief-2-report.md +75 -0
  367. package/evals/reports/by-skill/review-artifact-1-report.md +91 -0
  368. package/evals/reports/by-skill/review-artifact-2-report.md +79 -0
  369. package/evals/reports/by-skill/review-artifact-3-report.md +120 -0
  370. package/evals/reports/by-skill/review-artifact-4-report.md +89 -0
  371. package/evals/reports/by-skill/review-artifact-5-report.md +66 -0
  372. package/evals/reports/by-skill/review-work-1-report.md +85 -0
  373. package/evals/reports/by-skill/review-work-2-report.md +87 -0
  374. package/evals/reports/by-skill/review-work-3-report.md +104 -0
  375. package/evals/reports/by-skill/review-work-4-report.md +108 -0
  376. package/evals/reports/by-skill/review-work-5-report.md +73 -0
  377. package/evals/reports/by-skill/review-work-6-report.md +66 -0
  378. package/evals/reports/by-skill/setup-freeflow-1-report.md +199 -0
  379. package/evals/reports/by-skill/setup-freeflow-2-report.md +105 -0
  380. package/evals/reports/by-skill/setup-freeflow-3-report.md +105 -0
  381. package/evals/reports/by-skill/setup-freeflow-4-report.md +88 -0
  382. package/evals/reports/by-skill/setup-freeflow-5-report.md +115 -0
  383. package/evals/reports/by-skill/skill-authoring-1-report.md +81 -0
  384. package/evals/reports/by-skill/verify-work-1-report.md +111 -0
  385. package/evals/reports/by-skill/verify-work-2-report.md +120 -0
  386. package/evals/reports/by-skill/workflow-1-report.md +65 -0
  387. package/evals/reports/by-skill/write-plan-1-report.md +123 -0
  388. package/evals/reports/by-skill/write-plan-2-report.md +98 -0
  389. package/evals/reports/by-skill/write-plan-3-report.md +110 -0
  390. package/evals/reports/by-skill/write-spec-1-report.md +88 -0
  391. package/evals/reports/by-skill/write-spec-2-report.md +89 -0
  392. package/evals/reports/by-skill/write-spec-3-report.md +90 -0
  393. package/evals/reports/by-skill/write-spec-4-report.md +167 -0
  394. package/evals/reports/harness/claude-harness-1-report.md +103 -0
  395. package/evals/reports/harness/eval-harness-1-report.md +91 -0
  396. package/evals/reports/iterations/iteration-1-report.md +71 -0
  397. package/evals/reports/iterations/iteration-2-report.md +78 -0
  398. package/evals/reports/iterations/iteration-3-report.md +118 -0
  399. package/evals/reports/iterations/iteration-4-report.md +131 -0
  400. package/evals/reports/iterations/iteration-5-report.md +149 -0
  401. package/evals/reports/iterations/iteration-6-report.md +136 -0
  402. package/evals/reports/runtime/always-on-runtime-1-report.md +107 -0
  403. package/evals/reports/runtime/context-mode-normalized-benchmark-1-report.md +52 -0
  404. package/evals/reports/runtime/context-mode-real-deep-baseline-1-report.md +410 -0
  405. package/evals/reports/runtime/context-mode-real-deep-final-slice-11-report.md +203 -0
  406. package/evals/reports/runtime/context-mode-real-deep-final-slice-11-review.md +51 -0
  407. package/evals/reports/runtime/context-saving-native-tools-baseline-1-report.md +99 -0
  408. package/evals/reports/runtime/eryx-python-compatibility-reprobe-1-report.md +166 -0
  409. package/evals/reports/runtime/eryx-python-proof-spike-1-report.md +96 -0
  410. package/evals/reports/runtime/eryx-python-proof-spike-2-report.md +151 -0
  411. package/evals/reports/runtime/eryx-python-script-derive-execution-1-report.md +233 -0
  412. package/evals/reports/runtime/jq-script-derive-execution-1-report.md +215 -0
  413. package/evals/reports/runtime/jq-wasm-proof-spike-1-report.md +67 -0
  414. package/evals/reports/runtime/output-router-benchmark-1-report.md +81 -0
  415. package/evals/reports/runtime/output-router-capture-derive-provider-eval-1-report.md +35 -0
  416. package/evals/reports/runtime/output-router-codex-large-index-sqlite-adhoc-report.md +150 -0
  417. package/evals/reports/runtime/output-router-codex-qa-benchmark-1-report.md +46 -0
  418. package/evals/reports/runtime/output-router-command-benchmark-1-report.md +62 -0
  419. package/evals/reports/runtime/output-router-index-benchmark-1-report.md +64 -0
  420. package/evals/reports/runtime/output-router-regression-1-report.md +81 -0
  421. package/evals/reports/runtime/output-router-transform-eval-1-report.md +28 -0
  422. package/evals/reports/runtime/pi-observed-routing-eval-1-report.md +44 -0
  423. package/evals/reports/runtime/quickjs-script-derive-execution-1-report.md +159 -0
  424. package/evals/reports/runtime/quickjs-wasi-proof-spike-1-report.md +55 -0
  425. package/evals/reports/runtime/render-format-row-protocol-1-report.md +58 -0
  426. package/evals/reports/runtime/script-sandbox-adapter-selection-review-1-report.md +84 -0
  427. package/evals/reports/runtime/script-sandbox-probe-resource-hardening-1-report.md +51 -0
  428. package/evals/reports/runtime/storage-policy-benchmark-1-report.md +176 -0
  429. package/evals/reports/runtime/vault-index-storage-spike-1-report.md +39 -0
  430. package/evals/reports/runtime/workflow-context-hook-1-report.md +82 -0
  431. package/evals/runbooks/adversarial-eval-runbook.md +28 -0
  432. package/evals/runbooks/fixture-eval-runbook.md +137 -0
  433. package/evals/runbooks/handoff-eval-runbook.md +22 -0
  434. package/evals/runbooks/verify-work-eval-runbook.md +27 -0
  435. package/evals/scripts/audit-command-surface.sh +160 -0
  436. package/evals/scripts/check-activation-contract.sh +121 -0
  437. package/evals/scripts/check-runtime-context-hook.sh +183 -0
  438. package/evals/scripts/grade-fixture-eval.sh +446 -0
  439. package/evals/scripts/run-claude-fixture-eval.sh +26 -0
  440. package/evals/scripts/run-codex-fixture-eval.sh +26 -0
  441. package/evals/scripts/run-eryx-python-proof-spike.js +559 -0
  442. package/evals/scripts/run-fixture-eval-by-id.sh +23 -0
  443. package/evals/scripts/run-fixture-eval.sh +464 -0
  444. package/evals/scripts/run-jq-wasm-proof-spike.js +299 -0
  445. package/evals/scripts/run-output-router-transform-eval.js +115 -0
  446. package/evals/scripts/run-pi-observed-routing-eval.js +478 -0
  447. package/evals/scripts/run-quickjs-wasi-proof-spike.js +339 -0
  448. package/evals/scripts/skill-evidence.sh +316 -0
  449. package/evals/scripts/validate-release-metadata.sh +486 -0
  450. package/evals/suites/v0.1-acceptance-suite.md +131 -0
  451. package/{plugins/freeflow/hooks → hooks}/freeflow-runtime-context.mjs +46 -12
  452. package/package.json +39 -19
  453. package/pi-extension/dist/host-producer-identification.js +186 -0
  454. package/pi-extension/dist/index.js +85 -0
  455. package/pi-extension/dist/mcp-config.js +30 -0
  456. package/pi-extension/dist/native-safety-net.js +209 -0
  457. package/pi-extension/dist/observed-tool-routing.js +114 -0
  458. package/pi-extension/dist/renderers.js +835 -0
  459. package/pi-extension/dist/router-tools.js +438 -0
  460. package/pi-extension/dist/runtime-context.js +288 -0
  461. package/pi-extension/dist/schemas.js +254 -0
  462. package/pi-extension/dist/status.js +449 -0
  463. package/pi-extension/dist/utils.js +467 -0
  464. package/pi-extension/src/host-producer-identification.ts +226 -0
  465. package/pi-extension/src/index.ts +121 -0
  466. package/pi-extension/src/mcp-config.ts +32 -0
  467. package/pi-extension/src/native-safety-net.ts +252 -0
  468. package/pi-extension/src/observed-tool-routing.ts +126 -0
  469. package/pi-extension/src/renderers.ts +917 -0
  470. package/pi-extension/src/router-tools.ts +478 -0
  471. package/pi-extension/src/runtime-context.ts +347 -0
  472. package/pi-extension/src/schemas.ts +259 -0
  473. package/pi-extension/src/status.ts +505 -0
  474. package/pi-extension/src/utils.ts +492 -0
  475. package/pi-extension/tsconfig.json +16 -0
  476. package/{plugins/freeflow/docs → plugin-docs}/README.md +3 -3
  477. package/plugin-docs/adr/0002-evals-before-hooks.md +17 -0
  478. package/{plugins/freeflow/docs → plugin-docs}/adr/0003-release-boundary.md +2 -2
  479. package/plugin-docs/adr/0004-discover-replaces-shallow-discovery-skills.md +26 -0
  480. package/plugin-docs/adr/README.md +10 -0
  481. package/plugin-docs/architecture.md +89 -0
  482. package/plugin-docs/output-router.md +396 -0
  483. package/plugin-docs/release-evidence.md +77 -0
  484. package/{plugins/freeflow/docs → plugin-docs}/skills.md +3 -2
  485. package/{plugins/freeflow/docs → plugin-docs}/workflow.md +4 -4
  486. package/{plugins/freeflow/router/dist → router/dist/benchmarks}/benchmark-harness.js +1 -1
  487. package/{plugins/freeflow/router/dist → router/dist/benchmarks}/benchmarks.js +14 -14
  488. package/{plugins/freeflow/router/dist → router/dist/benchmarks}/codex-qa-benchmarks.js +6 -6
  489. package/{plugins/freeflow/router/dist → router/dist/benchmarks}/command-benchmarks.d.ts +1 -1
  490. package/{plugins/freeflow/router/dist → router/dist/benchmarks}/command-benchmarks.js +11 -10
  491. package/router/dist/benchmarks/context-mode-normalized-benchmarks.d.ts +74 -0
  492. package/router/dist/benchmarks/context-mode-normalized-benchmarks.js +707 -0
  493. package/router/dist/benchmarks/context-mode-real-deep-benchmark.d.ts +124 -0
  494. package/router/dist/benchmarks/context-mode-real-deep-benchmark.js +1295 -0
  495. package/router/dist/benchmarks/context-saving-baseline.d.ts +54 -0
  496. package/router/dist/benchmarks/context-saving-baseline.js +439 -0
  497. package/{plugins/freeflow/router/dist → router/dist/benchmarks}/index-benchmarks.d.ts +16 -2
  498. package/{plugins/freeflow/router/dist → router/dist/benchmarks}/index-benchmarks.js +330 -26
  499. package/router/dist/benchmarks/storage-policy-benchmarks.d.ts +90 -0
  500. package/router/dist/benchmarks/storage-policy-benchmarks.js +538 -0
  501. package/router/dist/benchmarks/vault-index-benchmarks.d.ts +47 -0
  502. package/router/dist/benchmarks/vault-index-benchmarks.js +257 -0
  503. package/router/dist/config/config.d.ts +96 -0
  504. package/router/dist/config/config.js +453 -0
  505. package/{plugins/freeflow/router/dist → router/dist/config}/schema.js +248 -2
  506. package/router/dist/config/types.d.ts +521 -0
  507. package/router/dist/config/types.js +30 -0
  508. package/{plugins/freeflow/router/dist → router/dist/evidence}/bounded-evidence.d.ts +1 -1
  509. package/{plugins/freeflow/router/dist → router/dist/evidence}/evidence-range-selector.js +65 -14
  510. package/{plugins/freeflow/router/dist → router/dist/evidence}/evidence-search.js +18 -2
  511. package/{plugins/freeflow/router/dist → router/dist/evidence}/evidence.d.ts +1 -1
  512. package/router/dist/evidence/failure-contracts.d.ts +27 -0
  513. package/router/dist/evidence/failure-contracts.js +160 -0
  514. package/router/dist/index.d.ts +30 -0
  515. package/router/dist/index.js +32 -0
  516. package/router/dist/processing/engine.d.ts +108 -0
  517. package/router/dist/processing/engine.js +435 -0
  518. package/router/dist/processing/reducers.d.ts +266 -0
  519. package/router/dist/processing/reducers.js +1495 -0
  520. package/router/dist/processing/renderers.d.ts +25 -0
  521. package/router/dist/processing/renderers.js +186 -0
  522. package/router/dist/processing/scripts.d.ts +78 -0
  523. package/router/dist/processing/scripts.js +333 -0
  524. package/router/dist/routing/observed-reducers.d.ts +35 -0
  525. package/router/dist/routing/observed-reducers.js +647 -0
  526. package/router/dist/routing/observed-routing.d.ts +17 -0
  527. package/router/dist/routing/observed-routing.js +377 -0
  528. package/{plugins/freeflow/router/dist → router/dist/routing}/parsers.d.ts +1 -1
  529. package/{plugins/freeflow/router/dist → router/dist/routing}/parsers.js +1 -1
  530. package/router/dist/routing/run-filters.d.ts +56 -0
  531. package/router/dist/routing/run-filters.js +230 -0
  532. package/router/dist/routing/run-reducers.d.ts +30 -0
  533. package/router/dist/routing/run-reducers.js +110 -0
  534. package/router/dist/sandbox/adapter-roots.d.ts +38 -0
  535. package/router/dist/sandbox/adapter-roots.js +64 -0
  536. package/router/dist/sandbox/eryx-python-adapter.d.ts +9 -0
  537. package/router/dist/sandbox/eryx-python-adapter.js +797 -0
  538. package/router/dist/sandbox/jq-wasm-adapter.d.ts +9 -0
  539. package/router/dist/sandbox/jq-wasm-adapter.js +421 -0
  540. package/router/dist/sandbox/quickjs-wasi-adapter.d.ts +9 -0
  541. package/router/dist/sandbox/quickjs-wasi-adapter.js +381 -0
  542. package/router/dist/sandbox/script-sandbox.d.ts +113 -0
  543. package/router/dist/sandbox/script-sandbox.js +303 -0
  544. package/router/dist/setup/script-transform-adapters.d.ts +28 -0
  545. package/router/dist/setup/script-transform-adapters.js +259 -0
  546. package/router/dist/tools/batch.d.ts +22 -0
  547. package/router/dist/tools/batch.js +509 -0
  548. package/router/dist/tools/run.d.ts +50 -0
  549. package/router/dist/tools/run.js +1219 -0
  550. package/router/dist/tools/search.d.ts +44 -0
  551. package/{plugins/freeflow/router/dist/retrieve.js → router/dist/tools/search.js} +395 -45
  552. package/router/dist/transform/engine.d.ts +143 -0
  553. package/router/dist/transform/engine.js +1955 -0
  554. package/router/dist/vault/vault-index.d.ts +106 -0
  555. package/router/dist/vault/vault-index.js +411 -0
  556. package/{plugins/freeflow/router/dist → router/dist/vault}/vault.d.ts +24 -1
  557. package/{plugins/freeflow/router/dist → router/dist/vault}/vault.js +152 -1
  558. package/skills/design-for-depth/SKILL.md +90 -0
  559. package/skills/design-for-depth/references/design-pressure-signals.md +265 -0
  560. package/skills/design-for-depth/references/software-design-philosophy.md +219 -0
  561. package/{plugins/freeflow/skills → skills}/diagnose-failure/SKILL.md +6 -1
  562. package/{plugins/freeflow/skills/research → skills/discover}/ARTIFACT-DESTINATIONS.md +4 -4
  563. package/{plugins/freeflow/skills/research → skills/discover}/CHECKPOINTS.md +4 -4
  564. package/skills/discover/SKILL.md +173 -0
  565. package/{plugins/freeflow/skills → skills}/execute-plan/SKILL.md +5 -4
  566. package/{plugins/freeflow/skills → skills}/execute-plan/references/execution-map.md +2 -2
  567. package/{plugins/freeflow/skills → skills}/mode-contract/SKILL.md +9 -4
  568. package/skills/output-router/SKILL.md +202 -0
  569. package/skills/output-router/references/safety-policy.md +40 -0
  570. package/{plugins/freeflow/skills → skills}/review-artifact/SKILL.md +5 -2
  571. package/{plugins/freeflow/skills → skills}/review-artifact/references/reviewer-prompt.md +2 -1
  572. package/{plugins/freeflow/skills → skills}/review-work/SKILL.md +6 -1
  573. package/{plugins/freeflow/skills → skills}/setup-freeflow/SKILL.md +21 -9
  574. package/{plugins/freeflow/skills → skills}/setup-freeflow/references/activation-contract.md +11 -10
  575. package/{plugins/freeflow/skills → skills}/setup-freeflow/references/host-setup.md +3 -3
  576. package/skills/setup-freeflow/references/output-router-setup.md +102 -0
  577. package/{plugins/freeflow/skills → skills}/verify-work/SKILL.md +3 -1
  578. package/{plugins/freeflow/skills → skills}/workflow/SKILL.md +16 -14
  579. package/{plugins/freeflow/skills → skills}/workflow/references/workflow-map.md +16 -14
  580. package/{plugins/freeflow/skills → skills}/write-plan/SKILL.md +9 -1
  581. package/{plugins/freeflow/skills → skills}/write-spec/SKILL.md +9 -6
  582. package/plugins/freeflow/docs/adr/0002-evals-before-hooks.md +0 -17
  583. package/plugins/freeflow/docs/adr/0004-research-replaces-shallow-discovery-skills.md +0 -26
  584. package/plugins/freeflow/docs/adr/README.md +0 -8
  585. package/plugins/freeflow/docs/architecture.md +0 -86
  586. package/plugins/freeflow/docs/output-router.md +0 -212
  587. package/plugins/freeflow/docs/release-evidence.md +0 -69
  588. package/plugins/freeflow/pi-extension/index.js +0 -1176
  589. package/plugins/freeflow/router/dist/config.d.ts +0 -22
  590. package/plugins/freeflow/router/dist/config.js +0 -114
  591. package/plugins/freeflow/router/dist/experimental-local-index.d.ts +0 -1
  592. package/plugins/freeflow/router/dist/experimental-local-index.js +0 -1
  593. package/plugins/freeflow/router/dist/index.d.ts +0 -12
  594. package/plugins/freeflow/router/dist/index.js +0 -12
  595. package/plugins/freeflow/router/dist/retrieve.d.ts +0 -33
  596. package/plugins/freeflow/router/dist/run.d.ts +0 -26
  597. package/plugins/freeflow/router/dist/run.js +0 -356
  598. package/plugins/freeflow/router/dist/types.d.ts +0 -234
  599. package/plugins/freeflow/router/dist/types.js +0 -9
  600. package/plugins/freeflow/skills/output-router/SKILL.md +0 -69
  601. package/plugins/freeflow/skills/output-router/references/safety-policy.md +0 -33
  602. package/plugins/freeflow/skills/research/LANGUAGE.md +0 -61
  603. package/plugins/freeflow/skills/research/SKILL.md +0 -128
  604. package/plugins/freeflow/skills/setup-freeflow/references/output-router-setup.md +0 -52
  605. /package/{plugins/freeflow/assets → assets}/freeflow-plugin-icon-transparent.png +0 -0
  606. /package/{plugins/freeflow/hooks → hooks}/hooks.json +0 -0
  607. /package/{plugins/freeflow/docs → plugin-docs}/adr/0001-three-modes.md +0 -0
  608. /package/{plugins/freeflow/router/dist → router/dist/benchmarks}/benchmark-harness.d.ts +0 -0
  609. /package/{plugins/freeflow/router/dist → router/dist/benchmarks}/benchmarks.d.ts +0 -0
  610. /package/{plugins/freeflow/router/dist → router/dist/benchmarks}/codex-qa-benchmarks.d.ts +0 -0
  611. /package/{plugins/freeflow/router/dist → router/dist/config}/router-contract.d.ts +0 -0
  612. /package/{plugins/freeflow/router/dist → router/dist/config}/router-contract.js +0 -0
  613. /package/{plugins/freeflow/router/dist → router/dist/config}/schema.d.ts +0 -0
  614. /package/{plugins/freeflow/router/dist → router/dist/evidence}/bounded-evidence.js +0 -0
  615. /package/{plugins/freeflow/router/dist → router/dist/evidence}/evidence-range-selector.d.ts +0 -0
  616. /package/{plugins/freeflow/router/dist → router/dist/evidence}/evidence-search.d.ts +0 -0
  617. /package/{plugins/freeflow/router/dist → router/dist/evidence}/evidence.js +0 -0
  618. /package/{plugins/freeflow/router/dist → router/dist/evidence}/line-ranges.d.ts +0 -0
  619. /package/{plugins/freeflow/router/dist → router/dist/evidence}/line-ranges.js +0 -0
  620. /package/{plugins/freeflow/router → router}/dist/experiments/local-index.d.ts +0 -0
  621. /package/{plugins/freeflow/router → router}/dist/experiments/local-index.js +0 -0
  622. /package/{plugins/freeflow/router/dist → router/dist/repo}/repo-traversal.d.ts +0 -0
  623. /package/{plugins/freeflow/router/dist → router/dist/repo}/repo-traversal.js +0 -0
  624. /package/{plugins/freeflow/skills → skills}/bypass/SKILL.md +0 -0
  625. /package/{plugins/freeflow/skills → skills}/commit-work/SKILL.md +0 -0
  626. /package/{plugins/freeflow/skills → skills}/commit-work/references/staging-decisions.md +0 -0
  627. /package/{plugins/freeflow/skills → skills}/diagnose-failure/references/feedback-loop-catalog.md +0 -0
  628. /package/{plugins/freeflow/skills → skills}/diagnose-failure/references/flaky-and-performance.md +0 -0
  629. /package/{plugins/freeflow/skills → skills}/evaluate-skill/SKILL.md +0 -0
  630. /package/{plugins/freeflow/skills → skills}/evaluate-skill/references/eval-patterns.md +0 -0
  631. /package/{plugins/freeflow/skills → skills}/evaluate-skill/references/grading-priority.md +0 -0
  632. /package/{plugins/freeflow/skills → skills}/handoff/SKILL.md +0 -0
  633. /package/{plugins/freeflow/skills → skills}/handoff/references/templates.md +0 -0
  634. /package/{plugins/freeflow/skills → skills}/interview-gate/SKILL.md +0 -0
  635. /package/{plugins/freeflow/skills → skills}/review-work/references/reviewer-prompt.md +0 -0
  636. /package/{plugins/freeflow/skills → skills}/write-plan/references/plan-shapes.md +0 -0
  637. /package/{plugins/freeflow/skills → skills}/write-skill/SKILL.md +0 -0
  638. /package/{plugins/freeflow/skills → skills}/write-spec/references/artifact-standards.md +0 -0
  639. /package/{plugins/freeflow/skills → skills}/write-spec/references/spec-shapes.md +0 -0
@@ -1,1176 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { readFile } from "node:fs/promises";
3
- import { join } from "node:path";
4
-
5
- import {
6
- createVault,
7
- findExactDuplicateTextOutput,
8
- freeflowRetrieve,
9
- freeflowRun,
10
- isNativeSafetyNetEnabled,
11
- normalizeRouterConfig,
12
- storeTextOutput,
13
- textOutputFingerprints,
14
- } from "../router/dist/index.js";
15
-
16
- const VALID_MODES = new Set(["conversation", "workflow", "strict-workflow"]);
17
-
18
- const WORKFLOW_COMMANDS = [
19
- "research",
20
- "write-spec",
21
- "review-artifact",
22
- "write-plan",
23
- "execute-plan",
24
- "diagnose-failure",
25
- "verify-work",
26
- "review-work",
27
- "commit-work",
28
- "handoff",
29
- "bypass",
30
- ];
31
-
32
- const CONTRIBUTOR_COMMANDS = [
33
- "setup-freeflow",
34
- "write-skill",
35
- "evaluate-skill",
36
- ];
37
-
38
- const MODE_STATE_ENTRY = "freeflow-mode";
39
- const RESET_MODE_ARGS = new Set(["reset"]);
40
- const SAFETY_NET_NATIVE_TOOLS = new Set(["read", "bash"]);
41
- const SAFETY_NET_EXCERPT_LINES = 8;
42
- const SAFETY_NET_HEURISTIC_MIN_BYTES = 16_384;
43
- const SAFETY_NET_HEURISTIC_MIN_LINES = 200;
44
-
45
- let runtimeContextCache = null;
46
- let currentModeOverride = null;
47
- let lastRouterConfigWarningKey = null;
48
-
49
- async function loadRuntimeContext() {
50
- const [workflowSkill, workflowMap, interviewGateSkill, outputRouterSkill, outputRouterSafetyPolicy] = await Promise.all([
51
- readFile(new URL("../skills/workflow/SKILL.md", import.meta.url), "utf8"),
52
- readFile(new URL("../skills/workflow/references/workflow-map.md", import.meta.url), "utf8"),
53
- readFile(new URL("../skills/interview-gate/SKILL.md", import.meta.url), "utf8"),
54
- readFile(new URL("../skills/output-router/SKILL.md", import.meta.url), "utf8"),
55
- readFile(new URL("../skills/output-router/references/safety-policy.md", import.meta.url), "utf8"),
56
- ]);
57
-
58
- return { workflowSkill, workflowMap, interviewGateSkill, outputRouterSkill, outputRouterSafetyPolicy };
59
- }
60
-
61
- async function refreshRuntimeContext() {
62
- runtimeContextCache = await loadRuntimeContext();
63
- return runtimeContextCache;
64
- }
65
-
66
- async function getRuntimeContext() {
67
- if (runtimeContextCache) {
68
- return runtimeContextCache;
69
- }
70
- return refreshRuntimeContext();
71
- }
72
-
73
- async function readFreeflowConfig(cwd) {
74
- try {
75
- const raw = await readFile(join(cwd, ".freeflow/config.json"), "utf8");
76
- const parsed = JSON.parse(raw);
77
- return parsed && typeof parsed === "object" ? parsed : {};
78
- } catch {
79
- return {};
80
- }
81
- }
82
-
83
- async function readDefaultMode(cwd) {
84
- const parsed = await readFreeflowConfig(cwd);
85
- return VALID_MODES.has(parsed.defaultMode) ? parsed.defaultMode : "workflow";
86
- }
87
-
88
- async function readOutputRouterConfig(cwd) {
89
- const parsed = await readFreeflowConfig(cwd);
90
- return normalizeRouterConfig(parsed.outputRouter);
91
- }
92
-
93
- function notifyRouterConfigWarnings(ctx, routerConfigResult) {
94
- if (!routerConfigResult.warnings.length) {
95
- return;
96
- }
97
-
98
- const key = routerConfigResult.warnings.join("\n");
99
- if (key === lastRouterConfigWarningKey) {
100
- return;
101
- }
102
-
103
- lastRouterConfigWarningKey = key;
104
- ctx.ui.notify(`Freeflow outputRouter config warning: ${routerConfigResult.warnings.join(" ")}`, "warning");
105
- }
106
-
107
- function restoreModeOverride(ctx) {
108
- currentModeOverride = null;
109
- const entries = ctx.sessionManager?.getEntries?.() ?? [];
110
-
111
- for (const entry of entries) {
112
- if (entry.type !== "custom" || entry.customType !== MODE_STATE_ENTRY) {
113
- continue;
114
- }
115
-
116
- const mode = entry.data?.currentMode;
117
- currentModeOverride = VALID_MODES.has(mode) ? mode : null;
118
- }
119
- }
120
-
121
- async function readModeState(cwd) {
122
- const defaultMode = await readDefaultMode(cwd);
123
- const currentMode = VALID_MODES.has(currentModeOverride) ? currentModeOverride : null;
124
- return {
125
- defaultMode,
126
- currentMode,
127
- effectiveMode: currentMode ?? defaultMode,
128
- };
129
- }
130
-
131
- function setModeStatus(ctx, modeState) {
132
- ctx.ui.setStatus("freeflow", `freeflow: ${modeState.effectiveMode}`);
133
- }
134
-
135
- function describeModeState(modeState) {
136
- if (modeState.currentMode) {
137
- return `current ${modeState.currentMode}; default ${modeState.defaultMode}`;
138
- }
139
- return `default ${modeState.defaultMode}`;
140
- }
141
-
142
- function skillPrompt(skill, args) {
143
- const trimmed = args?.trim();
144
- return trimmed ? `/skill:${skill}\n\n${trimmed}` : `/skill:${skill}`;
145
- }
146
-
147
- function hasFreeflowActivation(systemPrompt) {
148
- return (
149
- systemPrompt.includes("## Loaded Workflow Skill") &&
150
- systemPrompt.includes("## Loaded Workflow Map") &&
151
- systemPrompt.includes("## Loaded Interview Gate Skill")
152
- );
153
- }
154
-
155
- function hasOutputRouterActivation(systemPrompt) {
156
- return (
157
- systemPrompt.includes("## Loaded Output Router Skill") &&
158
- systemPrompt.includes("## Loaded Output Router Safety Policy")
159
- );
160
- }
161
-
162
- function outputRouterModeGuidance(mode) {
163
- if (mode === "conversation") {
164
- return "conversation mode: keep routed-tool guidance soft; answer questions directly.";
165
- }
166
- if (mode === "strict-workflow") {
167
- return "strict-workflow mode: strongest guidance; prefer exact, recoverable routed evidence for risky work.";
168
- }
169
- return "workflow mode: prefer routed tools for exploration and likely-large command output.";
170
- }
171
-
172
- function outputRouterContext(modeState, freeflowContext, routerConfigResult) {
173
- const safetyNetText =
174
- routerConfigResult.config.postToolRouting === "off"
175
- ? ""
176
- : "\n\nOutput-router config note: large native read/bash outputs may be vaulted and replaced with labeled routed output. Use freeflow_retrieve with the output id to recover exact content.";
177
-
178
- return `## Loaded Output Router Skill
179
-
180
- Mode guidance: ${outputRouterModeGuidance(modeState.effectiveMode)}${safetyNetText}
181
-
182
- \`\`\`md
183
- ${freeflowContext.outputRouterSkill.trim()}
184
- \`\`\`
185
-
186
- ## Loaded Output Router Safety Policy
187
-
188
- \`\`\`md
189
- ${freeflowContext.outputRouterSafetyPolicy.trim()}
190
- \`\`\``;
191
- }
192
-
193
- function runtimeContext(modeState, freeflowContext, routerConfigResult, alreadyActivated, routerAlreadyActivated) {
194
- const currentMode = modeState.currentMode ?? "none";
195
-
196
- if (alreadyActivated) {
197
- return `## Freeflow Runtime Context
198
-
199
- Repo default mode from \`.freeflow/config.json\`: ${modeState.defaultMode}.
200
- Current session mode override: ${currentMode}.
201
- Effective Freeflow mode: ${modeState.effectiveMode}.
202
-
203
- Use the installed Freeflow skills when they match the task. This Pi extension loads context and routes commands only; it does not enforce policy, block tools, grant permissions, or create repo-local hooks.${routerAlreadyActivated ? "" : `\n\n${outputRouterContext(modeState, freeflowContext, routerConfigResult)}`}`;
204
- }
205
-
206
- return `# Freeflow Runtime Context
207
-
208
- Freeflow Pi extension loaded this before the agent turn.
209
- These instructions are context-loading only. They do not override user instructions, repo instructions, or host safety and approval policy.
210
-
211
- ## Repo Setup
212
-
213
- Repo default mode from \`.freeflow/config.json\`: \`${modeState.defaultMode}\`.
214
- Current session mode override: \`${currentMode}\`.
215
- Effective Freeflow mode: \`${modeState.effectiveMode}\`.
216
- Treat the effective mode as the current mode for this agent turn.
217
- For mode changes or mode interpretation, use \`mode-contract\`.
218
- Do not announce the current mode on every reply. Mention it when the user asks, setup/config is discussed, or the mode changes the next action.
219
-
220
- ${routerAlreadyActivated ? "" : `${outputRouterContext(modeState, freeflowContext, routerConfigResult)}\n\n`}## Loaded Workflow Skill
221
-
222
- \`\`\`md
223
- ${freeflowContext.workflowSkill.trim()}
224
- \`\`\`
225
-
226
- ## Loaded Interview Gate Skill
227
-
228
- \`\`\`md
229
- ${freeflowContext.interviewGateSkill.trim()}
230
- \`\`\`
231
-
232
- ## Loaded Workflow Map
233
-
234
- \`\`\`md
235
- ${freeflowContext.workflowMap.trim()}
236
- \`\`\`
237
-
238
- This Pi extension loads context and routes commands only; it does not enforce policy, block tools, grant permissions, or create repo-local hooks.`;
239
- }
240
-
241
- const STRING_SCHEMA = { type: "string" };
242
- const PRESERVE_SCHEMA = { type: "string", enum: ["summary", "important", "full"] };
243
- const RETRIEVE_ACTION_SCHEMA = {
244
- type: "string",
245
- enum: ["query", "locate", "retrieve", "expand", "explain"],
246
- };
247
- const EXPANSION_SCHEMA = { type: "string", enum: ["lines_30", "lines_80", "full"] };
248
- const STREAM_SCHEMA = { type: "string", enum: ["stdout", "stderr", "combined", "raw"] };
249
-
250
- const FREEFLOW_RETRIEVE_PARAMETERS = {
251
- type: "object",
252
- additionalProperties: false,
253
- properties: {
254
- action: { ...RETRIEVE_ACTION_SCHEMA, description: "Retrieval action to perform." },
255
- source: {
256
- type: "object",
257
- additionalProperties: false,
258
- properties: {
259
- kind: { type: "string", enum: ["repo", "vault"] },
260
- path: { ...STRING_SCHEMA, description: "Repo path for source.kind=repo." },
261
- outputId: { ...STRING_SCHEMA, description: "Vault output id for source.kind=vault." },
262
- stream: { ...STREAM_SCHEMA, description: "Vault stream to read." },
263
- },
264
- required: ["kind"],
265
- description: "Source to retrieve from. Repo root and vault session are supplied by Freeflow/Pi.",
266
- },
267
- query: { ...STRING_SCHEMA, description: "Text query for query/locate actions." },
268
- preserve: { ...PRESERVE_SCHEMA, description: "Fidelity mode. Default: important." },
269
- evidence: {
270
- type: "object",
271
- additionalProperties: true,
272
- description: "Evidence packet from a previous freeflow_retrieve result, used for expand.",
273
- },
274
- expansion: { ...EXPANSION_SCHEMA, description: "Expansion breadth for expand action." },
275
- maxFullBytes: { type: "number", description: "Cap for preserve=full before exact chunks are returned." },
276
- topK: { type: "number", description: "Number of ranked repo candidates for query/locate. Defaults: query=1, locate=5; max 10." },
277
- lineRange: {
278
- type: "object",
279
- additionalProperties: false,
280
- properties: {
281
- start: { type: "number" },
282
- end: { type: "number" },
283
- },
284
- required: ["start", "end"],
285
- description: "Exact 1-based line range for vault retrieve.",
286
- },
287
- decision: {
288
- type: "object",
289
- additionalProperties: true,
290
- description: "Prior routed result to explain.",
291
- },
292
- },
293
- required: ["action", "source"],
294
- };
295
-
296
- const FREEFLOW_RUN_PARAMETERS = {
297
- type: "object",
298
- additionalProperties: false,
299
- properties: {
300
- command: { ...STRING_SCHEMA, description: "Shell command to run through Pi's approved command runner." },
301
- cwd: { ...STRING_SCHEMA, description: "Working directory. Defaults to the current Pi cwd." },
302
- timeoutMs: { type: "number", description: "Optional timeout in milliseconds." },
303
- preserve: { ...PRESERVE_SCHEMA, description: "Fidelity mode. Default: important." },
304
- goal: { ...STRING_SCHEMA, description: "Goal such as verification, test, build, or search." },
305
- },
306
- required: ["command"],
307
- };
308
-
309
- function stableHash(value) {
310
- return createHash("sha256").update(value).digest("hex");
311
- }
312
-
313
- function getRouterSessionId(ctx) {
314
- return ctx.sessionManager?.getSessionId?.() ?? `pi_${stableHash(ctx.cwd).slice(0, 16)}`;
315
- }
316
-
317
- function routedToolText(result) {
318
- return JSON.stringify(result, null, 2);
319
- }
320
-
321
- function textComponent(text) {
322
- return {
323
- render(width = 120) {
324
- const maxWidth = Number.isFinite(width) ? Math.max(1, width) : 120;
325
- return String(text).split("\n").map((line) => truncateAnsiToWidth(line, maxWidth));
326
- },
327
- invalidate() {},
328
- };
329
- }
330
-
331
- function truncateAnsiToWidth(input, width) {
332
- const text = String(input);
333
- let output = "";
334
- let visible = 0;
335
-
336
- for (let index = 0; index < text.length;) {
337
- const ansi = readAnsiSequence(text, index);
338
- if (ansi) {
339
- output += ansi.sequence;
340
- index = ansi.end;
341
- continue;
342
- }
343
-
344
- if (visible >= width - 1) {
345
- output += "…";
346
- return output;
347
- }
348
-
349
- const codePoint = text.codePointAt(index);
350
- const character = String.fromCodePoint(codePoint);
351
- output += character;
352
- visible += 1;
353
- index += character.length;
354
- }
355
-
356
- return output;
357
- }
358
-
359
- function readAnsiSequence(text, index) {
360
- if (text.charCodeAt(index) !== 0x1b) {
361
- return null;
362
- }
363
-
364
- const next = text[index + 1];
365
- if (next === "[") {
366
- let end = index + 2;
367
- while (end < text.length && !/[\x40-\x7e]/.test(text[end])) {
368
- end += 1;
369
- }
370
- return { sequence: text.slice(index, Math.min(end + 1, text.length)), end: Math.min(end + 1, text.length) };
371
- }
372
-
373
- if (next === "]") {
374
- const bellEnd = text.indexOf("\x07", index + 2);
375
- const stEnd = text.indexOf("\x1b\\", index + 2);
376
- const candidates = [bellEnd, stEnd === -1 ? -1 : stEnd + 1].filter((value) => value !== -1);
377
- const end = candidates.length > 0 ? Math.min(...candidates) + 1 : text.length;
378
- return { sequence: text.slice(index, end), end };
379
- }
380
-
381
- return { sequence: text.slice(index, Math.min(index + 2, text.length)), end: Math.min(index + 2, text.length) };
382
- }
383
-
384
- function themeFg(theme, color, text) {
385
- return typeof theme?.fg === "function" ? theme.fg(color, text) : text;
386
- }
387
-
388
- function themeBold(theme, text) {
389
- return typeof theme?.bold === "function" ? theme.bold(text) : text;
390
- }
391
-
392
- function formatStatus(theme, status) {
393
- const text = String(status ?? "unknown");
394
- if (text === "ok" || text === "success" || text === "routed" || text === "passed_through") {
395
- return themeFg(theme, "success", text);
396
- }
397
- if (text === "error" || text === "failed") {
398
- return themeFg(theme, "error", text);
399
- }
400
- return themeFg(theme, "warning", text);
401
- }
402
-
403
- function statusIcon(status) {
404
- if (status === "success" || status === "ok") {
405
- return "✓";
406
- }
407
- if (status === "failed" || status === "error") {
408
- return "✗";
409
- }
410
- return "!";
411
- }
412
-
413
- function oneLine(value) {
414
- return String(value ?? "").replace(/\s+/g, " ").trim();
415
- }
416
-
417
- function truncateText(value, maxLength = 120) {
418
- const text = oneLine(value);
419
- if (text.length <= maxLength) {
420
- return text;
421
- }
422
- return `${text.slice(0, Math.max(0, maxLength - 1))}…`;
423
- }
424
-
425
- function shortenMiddle(value, maxLength = 80) {
426
- const text = oneLine(value);
427
- if (text.length <= maxLength) {
428
- return text;
429
- }
430
- if (maxLength <= 5) {
431
- return text.slice(0, maxLength);
432
- }
433
- const keep = maxLength - 1;
434
- const head = Math.ceil(keep * 0.45);
435
- const tail = Math.floor(keep * 0.55);
436
- return `${text.slice(0, head)}…${text.slice(-tail)}`;
437
- }
438
-
439
- function commandLabel(command) {
440
- if (Array.isArray(command)) {
441
- return truncateText(command.join(" "), 120);
442
- }
443
- return truncateText(command ?? "...", 120);
444
- }
445
-
446
- function retrieveSourceLabel(source) {
447
- if (!source || source.kind === "repo") {
448
- return `repo ${shortenMiddle(source?.path ?? ".", 80)}`;
449
- }
450
- if (source.kind === "vault") {
451
- const stream = source.stream ? `:${source.stream}` : "";
452
- return `vault ${shortenMiddle(source.outputId ?? "...", 48)}${stream}`;
453
- }
454
- return oneLine(source.kind ?? "source");
455
- }
456
-
457
- function evidenceLabel(evidence) {
458
- if (!evidence) {
459
- return "no evidence";
460
- }
461
- const source = evidence.source;
462
- const path = evidence.path ?? (source?.kind === "repo" ? source.path : source?.kind === "vault" ? source.outputId : "evidence");
463
- const lines = evidence.lines ? `:${evidence.lines}` : "";
464
- return `${shortenMiddle(path, 90)}${lines}`;
465
- }
466
-
467
- function excerptLines(theme, excerpt, indent = " ", maxLines = 8) {
468
- const lines = splitLines(String(excerpt ?? ""));
469
- const shown = lines.slice(0, maxLines).map((line) => `${indent}${themeFg(theme, "toolOutput", truncateText(line, 140))}`);
470
- const omitted = lines.length - shown.length;
471
- if (omitted > 0) {
472
- shown.push(`${indent}${themeFg(theme, "dim", `… ${omitted} more line(s)`)}`);
473
- }
474
- return shown;
475
- }
476
-
477
- function routeSummaryLine(theme, result) {
478
- const route = result?.routing?.status ?? "unknown";
479
- const preserve = result?.preserve ? ` • preserve: ${result.preserve}` : "";
480
- return `${themeFg(theme, "muted", "routing:")} ${formatStatus(theme, route)}${themeFg(theme, "dim", preserve)}`;
481
- }
482
-
483
- function routerResultFromToolResult(result) {
484
- return result?.details?.result;
485
- }
486
-
487
- function fallbackResultText(result) {
488
- const text = extractTextContent(result?.content);
489
- return text ? truncateText(text, 200) : "No Freeflow result details available.";
490
- }
491
-
492
- function renderFreeflowRetrieveCall(args, theme) {
493
- const title = themeFg(theme, "toolTitle", themeBold(theme, "freeflow_retrieve"));
494
- const action = themeFg(theme, "muted", args?.action ?? "query");
495
- const source = themeFg(theme, "accent", retrieveSourceLabel(args?.source));
496
- const query = args?.query ? ` ${themeFg(theme, "dim", `\"${truncateText(args.query, 70)}\"`)}` : "";
497
- return textComponent(`${title} ${action} ${source}${query}`);
498
- }
499
-
500
- function renderFreeflowRunCall(args, theme) {
501
- const title = themeFg(theme, "toolTitle", themeBold(theme, "freeflow_run"));
502
- const command = themeFg(theme, "accent", `$ ${commandLabel(args?.command)}`);
503
- const extras = [];
504
- if (args?.preserve) {
505
- extras.push(`preserve=${args.preserve}`);
506
- }
507
- if (args?.timeoutMs !== undefined) {
508
- extras.push(`timeout=${args.timeoutMs}ms`);
509
- }
510
- const suffix = extras.length > 0 ? ` ${themeFg(theme, "dim", `(${extras.join(", ")})`)}` : "";
511
- return textComponent(`${title} ${command}${suffix}`);
512
- }
513
-
514
- function renderFreeflowRetrieveResult(result, { expanded } = {}, theme) {
515
- const routed = routerResultFromToolResult(result);
516
- if (!routed) {
517
- return textComponent(fallbackResultText(result));
518
- }
519
-
520
- const evidence = Array.isArray(routed.evidence) ? routed.evidence : [];
521
- const firstEvidence = evidence[0];
522
- const icon = statusIcon(routed.toolStatus);
523
- const lines = [
524
- `${themeFg(theme, "success", icon)} ${themeFg(theme, "toolTitle", "freeflow_retrieve")} ${themeFg(theme, "muted", `${evidence.length} evidence packet(s)`)} • ${routeSummaryLine(theme, routed)}`,
525
- ];
526
-
527
- if (firstEvidence) {
528
- lines.push(`${themeFg(theme, "accent", evidenceLabel(firstEvidence))}${firstEvidence.expandable ? themeFg(theme, "dim", " • expandable") : ""}`);
529
- } else {
530
- lines.push(themeFg(theme, "warning", truncateText(routed.routing?.reason ?? "No matching evidence returned.", 140)));
531
- }
532
-
533
- if (!expanded) {
534
- lines.push(themeFg(theme, "dim", "ctrl+o to expand evidence and recovery details"));
535
- return textComponent(lines.join("\n"));
536
- }
537
-
538
- lines.push("", themeFg(theme, "toolTitle", "Routing"));
539
- lines.push(` ${themeFg(theme, "muted", "toolStatus:")} ${formatStatus(theme, routed.toolStatus)}`);
540
- lines.push(` ${themeFg(theme, "muted", "routing.status:")} ${formatStatus(theme, routed.routing?.status)}`);
541
- lines.push(` ${themeFg(theme, "muted", "route:")} ${routed.routing?.route ?? "retrieve"}`);
542
- if (routed.routing?.reason) {
543
- lines.push(` ${themeFg(theme, "muted", "reason:")} ${truncateText(routed.routing.reason, 160)}`);
544
- }
545
-
546
- lines.push("", themeFg(theme, "toolTitle", "Evidence"));
547
- if (evidence.length === 0) {
548
- lines.push(` ${themeFg(theme, "dim", "No evidence packets returned.")}`);
549
- } else {
550
- evidence.forEach((packet, index) => {
551
- lines.push(` ${themeFg(theme, "accent", `#${index + 1} ${evidenceLabel(packet)}`)} ${themeFg(theme, "dim", `window=${packet.window}`)}`);
552
- if (packet.why) {
553
- lines.push(` ${themeFg(theme, "muted", "why:")} ${truncateText(packet.why, 160)}`);
554
- }
555
- lines.push(...excerptLines(theme, packet.excerpt, " ", 8));
556
- });
557
- }
558
-
559
- if (routed.recovery?.how) {
560
- lines.push("", themeFg(theme, "toolTitle", "Recovery"));
561
- lines.push(` ${truncateText(routed.recovery.how, 180)}`);
562
- if (routed.recovery.outputId) {
563
- lines.push(` ${themeFg(theme, "muted", "outputId:")} ${themeFg(theme, "accent", routed.recovery.outputId)}`);
564
- }
565
- if (routed.recovery.evidenceId) {
566
- lines.push(` ${themeFg(theme, "muted", "evidenceId:")} ${themeFg(theme, "accent", routed.recovery.evidenceId)}`);
567
- }
568
- }
569
-
570
- return textComponent(lines.join("\n"));
571
- }
572
-
573
- function renderFreeflowRunResult(result, { expanded } = {}, theme, context = {}) {
574
- const routed = routerResultFromToolResult(result);
575
- if (!routed) {
576
- return textComponent(fallbackResultText(result));
577
- }
578
-
579
- const executionStatus = routed.execution?.status ?? routed.toolStatus;
580
- const outputId = routed.outputId || routed.recovery?.outputId;
581
- const icon = statusIcon(executionStatus);
582
- const importantLines = Array.isArray(routed.importantLines) ? routed.importantLines : [];
583
- const lines = [
584
- `${themeFg(theme, executionStatus === "failed" ? "error" : "success", icon)} ${themeFg(theme, "toolTitle", "freeflow_run")} ${themeFg(theme, "muted", "execution:")} ${formatStatus(theme, executionStatus)} • ${routeSummaryLine(theme, routed)}`,
585
- ];
586
-
587
- const statusParts = [];
588
- if (routed.execution?.exitCode !== undefined && routed.execution?.exitCode !== null) {
589
- statusParts.push(`exit ${routed.execution.exitCode}`);
590
- }
591
- if (routed.execution?.durationMs !== undefined) {
592
- statusParts.push(`${routed.execution.durationMs}ms`);
593
- }
594
- if (outputId) {
595
- statusParts.push(`outputId ${outputId}`);
596
- }
597
- if (routed.parser?.name) {
598
- statusParts.push(`parser ${routed.parser.name} ${Number(routed.parser.confidence ?? 0).toFixed(2)}`);
599
- }
600
- if (statusParts.length > 0) {
601
- lines.push(themeFg(theme, "accent", statusParts.join(" • ")));
602
- }
603
- if (routed.summary) {
604
- lines.push(themeFg(theme, "muted", truncateText(routed.summary, 140)));
605
- }
606
- lines.push(themeFg(theme, "dim", `${importantLines.length} important span(s) • raw output recoverable from vault`));
607
-
608
- if (!expanded) {
609
- lines.push(themeFg(theme, "dim", "ctrl+o to expand status, evidence, and vault recovery"));
610
- return textComponent(lines.join("\n"));
611
- }
612
-
613
- lines.push("", themeFg(theme, "toolTitle", "Command"));
614
- lines.push(` ${themeFg(theme, "accent", `$ ${commandLabel(context.args?.command)}`)}`);
615
-
616
- lines.push("", themeFg(theme, "toolTitle", "Status"));
617
- lines.push(` ${themeFg(theme, "muted", "toolStatus:")} ${formatStatus(theme, routed.toolStatus)}`);
618
- lines.push(` ${themeFg(theme, "muted", "execution.status:")} ${formatStatus(theme, routed.execution?.status)}`);
619
- lines.push(` ${themeFg(theme, "muted", "routing.status:")} ${formatStatus(theme, routed.routing?.status)}`);
620
- if (routed.execution?.exitCode !== undefined) {
621
- lines.push(` ${themeFg(theme, "muted", "exitCode:")} ${routed.execution.exitCode}`);
622
- }
623
- if (routed.execution?.durationMs !== undefined) {
624
- lines.push(` ${themeFg(theme, "muted", "durationMs:")} ${routed.execution.durationMs}`);
625
- }
626
-
627
- if (routed.routing?.reason || routed.summary) {
628
- lines.push("", themeFg(theme, "toolTitle", "Routing"));
629
- if (routed.summary) {
630
- lines.push(` ${themeFg(theme, "muted", "summary:")} ${truncateText(routed.summary, 160)}`);
631
- }
632
- if (routed.routing?.reason) {
633
- lines.push(` ${themeFg(theme, "muted", "reason:")} ${truncateText(routed.routing.reason, 180)}`);
634
- }
635
- }
636
-
637
- if (routed.parser?.name) {
638
- lines.push("", themeFg(theme, "toolTitle", "Parser"));
639
- lines.push(` ${themeFg(theme, "muted", "name:")} ${routed.parser.name}`);
640
- lines.push(` ${themeFg(theme, "muted", "confidence:")} ${Number(routed.parser.confidence ?? 0).toFixed(2)}`);
641
- lines.push(` ${themeFg(theme, "muted", "fidelity:")} ${routed.parser.fidelity ?? "exact"}`);
642
- lines.push(` ${themeFg(theme, "muted", "compressed:")} ${String(Boolean(routed.parser.compressed))}`);
643
- if (routed.parser.counts && Object.keys(routed.parser.counts).length > 0) {
644
- lines.push(` ${themeFg(theme, "muted", "counts:")} ${truncateText(JSON.stringify(routed.parser.counts), 160)}`);
645
- }
646
- if (Array.isArray(routed.parser.references) && routed.parser.references.length > 0) {
647
- const refs = routed.parser.references.slice(0, 3).map((ref) => `${ref.path}${ref.line ? `:${ref.line}${ref.column ? `:${ref.column}` : ""}` : ""}${ref.code ? ` ${ref.code}` : ""}`);
648
- lines.push(` ${themeFg(theme, "muted", "references:")} ${truncateText(refs.join(", "), 180)}`);
649
- }
650
- }
651
-
652
- lines.push("", themeFg(theme, "toolTitle", "Evidence"));
653
- if (importantLines.length === 0) {
654
- lines.push(` ${themeFg(theme, "dim", "No important lines selected.")}`);
655
- } else {
656
- importantLines.forEach((line, index) => {
657
- lines.push(` ${themeFg(theme, "accent", `#${index + 1} ${line.stream} lines ${line.lines}`)}`);
658
- lines.push(...excerptLines(theme, line.excerpt, " ", 8));
659
- });
660
- }
661
-
662
- if (routed.recovery?.how || outputId) {
663
- lines.push("", themeFg(theme, "toolTitle", "Vault recovery"));
664
- if (outputId) {
665
- lines.push(` ${themeFg(theme, "muted", "outputId:")} ${themeFg(theme, "accent", outputId)}`);
666
- }
667
- if (routed.recovery?.how) {
668
- lines.push(` ${truncateText(routed.recovery.how, 180)}`);
669
- }
670
- }
671
-
672
- return textComponent(lines.join("\n"));
673
- }
674
-
675
- function byteLength(text) {
676
- return Buffer.byteLength(text, "utf8");
677
- }
678
-
679
- function splitLines(text) {
680
- if (text.length === 0) {
681
- return [];
682
- }
683
- return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
684
- }
685
-
686
- function extractTextContent(content) {
687
- if (!Array.isArray(content) || content.length === 0) {
688
- return null;
689
- }
690
-
691
- if (!content.every((part) => part?.type === "text" && typeof part.text === "string")) {
692
- return null;
693
- }
694
-
695
- return content.map((part) => part.text).join("\n");
696
- }
697
-
698
- async function nativeResultText(event) {
699
- const fullOutputPath = event.toolName === "bash" ? event.details?.fullOutputPath : undefined;
700
- if (typeof fullOutputPath === "string" && fullOutputPath.length > 0) {
701
- try {
702
- return await readFile(fullOutputPath, "utf8");
703
- } catch {
704
- // Fall back to the exact text that would otherwise enter model context.
705
- }
706
- }
707
-
708
- return extractTextContent(event.content);
709
- }
710
-
711
- function nativeOutputStats(text, truncation) {
712
- const measuredLines = splitLines(text).length;
713
- const measuredBytes = byteLength(text);
714
- return {
715
- lines: Number.isInteger(truncation?.totalLines) ? truncation.totalLines : measuredLines,
716
- bytes: Number.isInteger(truncation?.totalBytes) ? truncation.totalBytes : measuredBytes,
717
- capturedLines: measuredLines,
718
- capturedBytes: measuredBytes,
719
- };
720
- }
721
-
722
- function isSafetyNetEnabled(routerConfig) {
723
- return isNativeSafetyNetEnabled(routerConfig.postToolRouting);
724
- }
725
-
726
- function shouldRouteNativeToolResult(event, routerConfig, text) {
727
- if (!SAFETY_NET_NATIVE_TOOLS.has(event.toolName) || !isSafetyNetEnabled(routerConfig)) {
728
- return { route: false };
729
- }
730
-
731
- const stats = nativeOutputStats(text, event.details?.truncation);
732
- if (stats.bytes > routerConfig.thresholds.largeOutputBytes) {
733
- return {
734
- route: true,
735
- stats,
736
- reason: `native ${event.toolName} output exceeded largeOutputBytes (${stats.bytes} > ${routerConfig.thresholds.largeOutputBytes})`,
737
- };
738
- }
739
-
740
- if (stats.lines > routerConfig.thresholds.largeOutputLines) {
741
- return {
742
- route: true,
743
- stats,
744
- reason: `native ${event.toolName} output exceeded largeOutputLines (${stats.lines} > ${routerConfig.thresholds.largeOutputLines})`,
745
- };
746
- }
747
-
748
- if (matchesConfiguredNoiseHint(event, routerConfig) && exceedsHeuristicMinimum(stats, routerConfig)) {
749
- return {
750
- route: true,
751
- stats,
752
- reason: `native ${event.toolName} output matched configured noisy/generated-output hints and exceeded the conservative heuristic floor`,
753
- };
754
- }
755
-
756
- return { route: false };
757
- }
758
-
759
- function exceedsHeuristicMinimum(stats, routerConfig) {
760
- const byteFloor = Math.min(routerConfig.thresholds.largeOutputBytes, SAFETY_NET_HEURISTIC_MIN_BYTES);
761
- const lineFloor = Math.min(routerConfig.thresholds.largeOutputLines, SAFETY_NET_HEURISTIC_MIN_LINES);
762
- return stats.bytes > byteFloor || stats.lines > lineFloor;
763
- }
764
-
765
- function matchesConfiguredNoiseHint(event, routerConfig) {
766
- if (event.toolName === "bash") {
767
- const command = typeof event.input?.command === "string" ? event.input.command : "";
768
- return matchesAnyHint(command, routerConfig.hints?.noisyCommandPatterns);
769
- }
770
-
771
- if (event.toolName === "read") {
772
- const path = typeof event.input?.path === "string" ? event.input.path : "";
773
- return matchesAnyPathHint(path, routerConfig.hints?.generatedPathGlobs);
774
- }
775
-
776
- return false;
777
- }
778
-
779
- function matchesAnyHint(value, hints) {
780
- if (!value || !Array.isArray(hints)) {
781
- return false;
782
- }
783
- return hints.some((hint) => typeof hint === "string" && hint.length > 0 && value.includes(hint));
784
- }
785
-
786
- function matchesAnyPathHint(path, hints) {
787
- if (!path || !Array.isArray(hints)) {
788
- return false;
789
- }
790
- return hints.some((hint) => matchesSimpleGlob(path, hint));
791
- }
792
-
793
- function matchesSimpleGlob(path, pattern) {
794
- if (typeof pattern !== "string" || pattern.length === 0) {
795
- return false;
796
- }
797
-
798
- if (pattern.endsWith("/**")) {
799
- const prefix = pattern.slice(0, -3);
800
- return path === prefix || path.startsWith(`${prefix}/`);
801
- }
802
-
803
- if (!pattern.includes("*")) {
804
- return path === pattern || path.includes(pattern);
805
- }
806
-
807
- const escaped = pattern
808
- .split("*")
809
- .map((part) => part.replace(/[|\\{}()[\]^$+?.]/g, "\\$&"))
810
- .join(".*");
811
- return new RegExp(`^${escaped}$`).test(path);
812
- }
813
-
814
- function nativeSafetyDecisionId(event, text) {
815
- return `ffdec_native_${stableHash(`${event.toolName}:${event.toolCallId}:${text}`).slice(0, 24)}`;
816
- }
817
-
818
- function formatNativeSafetyNetResult({ event, record, duplicate, stats, reason, mode, text }) {
819
- const lines = splitLines(text);
820
- const shownLines = lines.slice(0, SAFETY_NET_EXCERPT_LINES);
821
- const shownEnd = shownLines.length;
822
- const omittedLines = Math.max(0, stats.capturedLines - shownLines.length);
823
- const inputLabel = nativeInputLabel(event);
824
- const duplicateLine = duplicate
825
- ? `Duplicate: exact native output matches previous outputId=${duplicate.outputId}; current raw output was vaulted as outputId=${record.outputId}.`
826
- : null;
827
-
828
- return [
829
- `Freeflow routed this native ${event.toolName} result (post-tool safety net).`,
830
- `Reason: ${reason}; outputRouter.postToolRouting=${mode}.`,
831
- `Captured exact native text in the Freeflow vault: outputId=${record.outputId}, stream=raw, lines=${stats.capturedLines}, bytes=${stats.capturedBytes}.`,
832
- ...(duplicateLine ? [duplicateLine] : []),
833
- `Original native result stats: lines=${stats.lines}, bytes=${stats.bytes}.${inputLabel ? ` Input: ${inputLabel}.` : ""}`,
834
- `Recovery: use freeflow_retrieve with action=retrieve, source.kind=vault, outputId=${record.outputId}, stream=raw, and a lineRange to recover exact content.`,
835
- `Showing exact captured lines 1-${shownEnd}${omittedLines > 0 ? ` (${omittedLines} captured lines omitted from context)` : ""}:`,
836
- "```text",
837
- shownLines.join("\n"),
838
- "```",
839
- ].join("\n");
840
- }
841
-
842
- function nativeInputLabel(event) {
843
- if (event.toolName === "bash" && typeof event.input?.command === "string") {
844
- return `command=${JSON.stringify(event.input.command)}`;
845
- }
846
- if (event.toolName === "read" && typeof event.input?.path === "string") {
847
- return `path=${JSON.stringify(event.input.path)}`;
848
- }
849
- return "";
850
- }
851
-
852
- function appendSafetyNetWarning(event, message) {
853
- return [
854
- ...event.content,
855
- {
856
- type: "text",
857
- text: `Freeflow safety-net warning: ${message} Native output was not shortened or removed.`,
858
- },
859
- ];
860
- }
861
-
862
- // Keep post-tool native transformations aligned with
863
- // plugins/freeflow/skills/output-router/references/safety-policy.md.
864
- async function handleNativeToolSafetyNet(event, ctx) {
865
- const routerConfigResult = await readOutputRouterConfig(ctx.cwd);
866
- notifyRouterConfigWarnings(ctx, routerConfigResult);
867
- const routerConfig = routerConfigResult.config;
868
-
869
- if (!SAFETY_NET_NATIVE_TOOLS.has(event.toolName) || !isSafetyNetEnabled(routerConfig)) {
870
- return undefined;
871
- }
872
-
873
- const text = await nativeResultText(event);
874
- if (text === null) {
875
- return undefined;
876
- }
877
-
878
- const routeDecision = shouldRouteNativeToolResult(event, routerConfig, text);
879
- if (!routeDecision.route) {
880
- return undefined;
881
- }
882
-
883
- try {
884
- const vault = createVault({ root: routerConfig.vault.root, retention: routerConfig.vault.retention });
885
- const sessionId = getRouterSessionId(ctx);
886
- const fingerprints = textOutputFingerprints({ raw: text });
887
- const duplicate = await findExactDuplicateTextOutput(vault, { sessionId, fingerprints });
888
- const decisionId = nativeSafetyDecisionId(event, text);
889
- const record = await storeTextOutput(vault, {
890
- sessionId,
891
- raw: text,
892
- sourceKind: "native",
893
- decisionIds: [decisionId],
894
- });
895
- const routedText = formatNativeSafetyNetResult({
896
- event,
897
- record,
898
- duplicate,
899
- stats: routeDecision.stats,
900
- reason: routeDecision.reason,
901
- mode: routerConfig.postToolRouting,
902
- text,
903
- });
904
-
905
- return {
906
- content: [{ type: "text", text: routedText }],
907
- details: {
908
- ...(event.details && typeof event.details === "object" ? event.details : {}),
909
- freeflowOutputRouter: {
910
- route: "safety-net",
911
- outputId: record.outputId,
912
- decisionId,
913
- reason: routeDecision.reason,
914
- ...(duplicate ? { duplicateOfOutputId: duplicate.outputId } : {}),
915
- },
916
- },
917
- };
918
- } catch (error) {
919
- const message = error instanceof Error ? error.message : String(error);
920
- ctx.ui.notify(`Freeflow safety-net routing failed; passing native ${event.toolName} output through. ${message}`, "warning");
921
- return {
922
- content: appendSafetyNetWarning(event, message),
923
- };
924
- }
925
- }
926
-
927
- async function normalizeRetrieveParams(params, ctx) {
928
- const routerConfigResult = await readOutputRouterConfig(ctx.cwd);
929
- notifyRouterConfigWarnings(ctx, routerConfigResult);
930
- const source = params.source ?? { kind: "repo" };
931
-
932
- if (source.kind === "repo") {
933
- return {
934
- ...params,
935
- generatedPathGlobs: routerConfigResult.config.hints?.generatedPathGlobs,
936
- source: {
937
- kind: "repo",
938
- root: ctx.cwd,
939
- ...(source.path ? { path: source.path } : {}),
940
- },
941
- };
942
- }
943
-
944
- if (source.kind === "vault") {
945
- if (!source.outputId) {
946
- throw new Error("freeflow_retrieve source.kind=vault requires source.outputId.");
947
- }
948
- return {
949
- ...params,
950
- source: {
951
- kind: "vault",
952
- root: routerConfigResult.config.vault.root,
953
- sessionId: getRouterSessionId(ctx),
954
- outputId: source.outputId,
955
- ...(source.stream ? { stream: source.stream } : {}),
956
- },
957
- };
958
- }
959
-
960
- throw new Error(`Unsupported freeflow_retrieve source kind: ${source.kind}`);
961
- }
962
-
963
- function createPiCommandRunner(pi, signal) {
964
- return {
965
- async run(request) {
966
- const startedAt = Date.now();
967
- const command = Array.isArray(request.command) ? request.command.join(" ") : request.command;
968
- const result = await pi.exec("bash", ["-lc", command], {
969
- cwd: request.cwd,
970
- timeout: request.timeoutMs,
971
- signal,
972
- });
973
- const durationMs = Date.now() - startedAt;
974
- const killed = Boolean(result.killed);
975
- const code = typeof result.code === "number" ? result.code : null;
976
- return {
977
- stdout: result.stdout ?? "",
978
- stderr: result.stderr ?? "",
979
- executionStatus: signal?.aborted ? "cancelled" : killed ? "timed_out" : code === 0 ? "success" : "failed",
980
- exitCode: code,
981
- durationMs,
982
- };
983
- },
984
- };
985
- }
986
-
987
- function registerRouterTools(pi) {
988
- pi.registerTool({
989
- name: "freeflow_retrieve",
990
- label: "Freeflow Retrieve",
991
- description:
992
- "Retrieve targeted evidence from repo files or Freeflow-vaulted output. Returns labeled, recoverable routed evidence instead of broad raw output.",
993
- promptSnippet: "Retrieve targeted repo/vault evidence with recoverable routed output.",
994
- promptGuidelines: [
995
- "Use freeflow_retrieve for targeted repo or vault evidence before reading whole files or dumping captured output.",
996
- "Use freeflow_retrieve with source.kind=vault and an outputId to recover exact output from freeflow_run.",
997
- ],
998
- parameters: FREEFLOW_RETRIEVE_PARAMETERS,
999
- async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
1000
- const result = await freeflowRetrieve(await normalizeRetrieveParams(params, ctx));
1001
- return {
1002
- content: [{ type: "text", text: routedToolText(result) }],
1003
- details: { result },
1004
- };
1005
- },
1006
- renderCall(args, theme) {
1007
- return renderFreeflowRetrieveCall(args, theme);
1008
- },
1009
- renderResult(result, options, theme) {
1010
- return renderFreeflowRetrieveResult(result, options, theme);
1011
- },
1012
- });
1013
-
1014
- pi.registerTool({
1015
- name: "freeflow_run",
1016
- label: "Freeflow Run",
1017
- description:
1018
- "Run a command through Pi's approved runner, vault exact stdout/stderr, and return compact routed evidence plus an outputId.",
1019
- promptSnippet: "Run likely-large/noisy commands with vaulted raw output and compact evidence.",
1020
- promptGuidelines: [
1021
- "Use freeflow_run for commands likely to produce large or noisy output when routed evidence is enough.",
1022
- "Use native bash when direct shell behavior or exact small raw output is intentionally needed.",
1023
- ],
1024
- parameters: FREEFLOW_RUN_PARAMETERS,
1025
- async execute(_toolCallId, params, signal, _onUpdate, ctx) {
1026
- const routerConfigResult = await readOutputRouterConfig(ctx.cwd);
1027
- notifyRouterConfigWarnings(ctx, routerConfigResult);
1028
- const runner = createPiCommandRunner(pi, signal);
1029
- const result = await freeflowRun(
1030
- {
1031
- command: params.command,
1032
- cwd: params.cwd ?? ctx.cwd,
1033
- timeoutMs: params.timeoutMs,
1034
- preserve: params.preserve,
1035
- goal: params.goal,
1036
- sessionId: getRouterSessionId(ctx),
1037
- vaultRoot: routerConfigResult.config.vault.root,
1038
- vaultRetention: routerConfigResult.config.vault.retention,
1039
- thresholds: routerConfigResult.config.thresholds,
1040
- },
1041
- {
1042
- async run(request) {
1043
- if (signal?.aborted) {
1044
- return { stdout: "", stderr: "", executionStatus: "cancelled", exitCode: null };
1045
- }
1046
- return runner.run(request);
1047
- },
1048
- },
1049
- );
1050
- return {
1051
- content: [{ type: "text", text: routedToolText(result) }],
1052
- details: { result },
1053
- };
1054
- },
1055
- renderCall(args, theme) {
1056
- return renderFreeflowRunCall(args, theme);
1057
- },
1058
- renderResult(result, options, theme, context) {
1059
- return renderFreeflowRunResult(result, options, theme, context);
1060
- },
1061
- });
1062
- }
1063
-
1064
- async function handleWorkflowCommand(args, ctx, pi) {
1065
- const arg = args?.trim();
1066
-
1067
- if (VALID_MODES.has(arg)) {
1068
- currentModeOverride = arg;
1069
- pi.appendEntry?.(MODE_STATE_ENTRY, { currentMode: arg });
1070
- const modeState = await readModeState(ctx.cwd);
1071
- setModeStatus(ctx, modeState);
1072
- ctx.ui.notify(
1073
- `Freeflow mode is now ${modeState.effectiveMode} for this session. Repo default remains ${modeState.defaultMode}.`,
1074
- "info"
1075
- );
1076
- return;
1077
- }
1078
-
1079
- if (RESET_MODE_ARGS.has(arg)) {
1080
- currentModeOverride = null;
1081
- pi.appendEntry?.(MODE_STATE_ENTRY, { currentMode: null });
1082
- const modeState = await readModeState(ctx.cwd);
1083
- setModeStatus(ctx, modeState);
1084
- ctx.ui.notify(`Freeflow mode reset to repo default: ${modeState.defaultMode}.`, "info");
1085
- return;
1086
- }
1087
-
1088
- const modeState = await readModeState(ctx.cwd);
1089
- setModeStatus(ctx, modeState);
1090
- ctx.ui.notify(
1091
- `Freeflow mode is ${modeState.effectiveMode} (${describeModeState(modeState)}). Use /workflow conversation, /workflow workflow, /workflow strict-workflow, or /workflow reset.`,
1092
- "info"
1093
- );
1094
- }
1095
-
1096
- export default function freeflow(pi) {
1097
- registerRouterTools(pi);
1098
-
1099
- pi.on("session_start", async (_event, ctx) => {
1100
- restoreModeOverride(ctx);
1101
- const [modeState, routerConfigResult] = await Promise.all([
1102
- readModeState(ctx.cwd),
1103
- readOutputRouterConfig(ctx.cwd),
1104
- refreshRuntimeContext(),
1105
- ]);
1106
- setModeStatus(ctx, modeState);
1107
- notifyRouterConfigWarnings(ctx, routerConfigResult);
1108
- });
1109
-
1110
- pi.on("session_compact", async (_event, ctx) => {
1111
- const [modeState, routerConfigResult] = await Promise.all([
1112
- readModeState(ctx.cwd),
1113
- readOutputRouterConfig(ctx.cwd),
1114
- refreshRuntimeContext(),
1115
- ]);
1116
- setModeStatus(ctx, modeState);
1117
- notifyRouterConfigWarnings(ctx, routerConfigResult);
1118
- });
1119
-
1120
- pi.on("before_agent_start", async (event, ctx) => {
1121
- const [modeState, freeflowContext, routerConfigResult] = await Promise.all([
1122
- readModeState(ctx.cwd),
1123
- getRuntimeContext(),
1124
- readOutputRouterConfig(ctx.cwd),
1125
- ]);
1126
- setModeStatus(ctx, modeState);
1127
- notifyRouterConfigWarnings(ctx, routerConfigResult);
1128
- return {
1129
- systemPrompt:
1130
- event.systemPrompt +
1131
- "\n\n" +
1132
- runtimeContext(
1133
- modeState,
1134
- freeflowContext,
1135
- routerConfigResult,
1136
- hasFreeflowActivation(event.systemPrompt),
1137
- hasOutputRouterActivation(event.systemPrompt)
1138
- ),
1139
- };
1140
- });
1141
-
1142
- pi.on("tool_result", async (event, ctx) => {
1143
- return handleNativeToolSafetyNet(event, ctx);
1144
- });
1145
-
1146
- for (const skill of WORKFLOW_COMMANDS) {
1147
- pi.registerCommand(skill, {
1148
- description: `Run Freeflow ${skill}`,
1149
- handler: async (args) => {
1150
- await pi.sendUserMessage(skillPrompt(skill, args));
1151
- },
1152
- });
1153
- }
1154
-
1155
- for (const skill of CONTRIBUTOR_COMMANDS) {
1156
- pi.registerCommand(skill, {
1157
- description: `Run Freeflow ${skill}`,
1158
- handler: async (args) => {
1159
- await pi.sendUserMessage(skillPrompt(skill, args));
1160
- },
1161
- });
1162
- }
1163
-
1164
- pi.registerCommand("workflow", {
1165
- description: "Set or inspect the current Freeflow session mode",
1166
- getArgumentCompletions: (prefix) => {
1167
- const query = prefix ?? "";
1168
- const values = ["conversation", "workflow", "strict-workflow", "reset"];
1169
- const filtered = values.filter((value) => value.startsWith(query));
1170
- return filtered.map((value) => ({ value, label: value }));
1171
- },
1172
- handler: async (args, ctx) => {
1173
- await handleWorkflowCommand(args, ctx, pi);
1174
- },
1175
- });
1176
- }