@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,13 +1,18 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { mkdir, mkdtemp, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
3
+ import { createRequire } from "node:module";
3
4
  import { tmpdir } from "node:os";
4
- import { dirname, resolve } from "node:path";
5
+ import { dirname, relative, resolve } from "node:path";
5
6
  import { fileURLToPath } from "node:url";
6
7
  import { performance } from "node:perf_hooks";
7
8
  import { defaultJsonRunReportPath, escapeMarkdownTableCell as escapeTable, formatPercent, latencySummary, normalizeIterations, parseBenchmarkCliArgs, reductionPercent, writeBenchmarkReportPair, } from "./benchmark-harness.js";
8
- import { freeflowRetrieve } from "./retrieve.js";
9
- import { buildOrLoadExperimentalRepoIndex, queryExperimentalRepoIndex, } from "./experiments/local-index.js";
9
+ import { freeflowSearch } from "../tools/search.js";
10
+ import { buildOrLoadExperimentalRepoIndex, queryExperimentalRepoIndex, } from "../experiments/local-index.js";
10
11
  const DEFAULT_ITERATIONS = 3;
12
+ const BENCHMARK_TOP_K = 3;
13
+ const FTS_CONTEXT_LINES = 2;
14
+ const require = createRequire(import.meta.url);
15
+ let cachedFtsCandidateStatus;
11
16
  export async function runIndexBenchmarks(options = {}) {
12
17
  const iterations = normalizeIterations(options.iterations, DEFAULT_ITERATIONS);
13
18
  const fixtures = indexFixtureDefinitions();
@@ -35,9 +40,9 @@ export function renderIndexBenchmarkReport(report) {
35
40
  "",
36
41
  "## Scope",
37
42
  "",
38
- "Optional Local Index Experiment for `freeflow_retrieve`. The scanner remains the product default; this benchmark measures an isolated no-dependency local index for cold build, warm query, stale refresh, accuracy, and bounded context bytes.",
43
+ "Repo Search Backend Benchmark for `freeflow_search`. The scanner remains the product default; this benchmark compares scanner-only retrieval, the no-dependency local lexical index, a conservative hybrid scanner+index path, and records whether an FTS5/BM25/trigram candidate is available.",
39
44
  "",
40
- "The index cache is keyed by repo root and stores outside the repo by default. No external service, vector DB, or native dependency is required.",
45
+ "The index cache is keyed by repo root and stores outside the repo by default. No external service, vector DB, or native dependency is required for the local lexical index.",
41
46
  "",
42
47
  "## Command",
43
48
  "",
@@ -45,15 +50,18 @@ export function renderIndexBenchmarkReport(report) {
45
50
  "npm run bench:router:index",
46
51
  "```",
47
52
  "",
48
- "The CLI writes machine-readable JSON under `plugins/freeflow/evals/runs/output-router/` by default. That JSON is generated run data; this Markdown file is the durable runtime report.",
53
+ "The CLI writes machine-readable JSON under `evals/runs/output-router/` by default. That JSON is generated run data; this Markdown file is the durable runtime report.",
49
54
  "",
50
55
  "## Summary",
51
56
  "",
52
57
  `- Fixtures: ${report.summary.fixtures}`,
53
58
  `- Scanner remains default: ${report.summary.scannerDefault ? "yes" : "no"}`,
54
59
  `- Index adopted by default: ${report.summary.indexAdopted ? "yes" : "no"}`,
55
- `- Scanner pass: ${report.summary.scanner.passed}/${report.summary.fixtures}`,
56
- `- Index warm pass: ${report.summary.index.passed}/${report.summary.fixtures}`,
60
+ `- Scanner pass: ${report.summary.scanner.passed}/${report.summary.fixtures} (recall@${BENCHMARK_TOP_K}: ${report.summary.scanner.recallAtK}/${report.summary.fixtures})`,
61
+ `- Index warm pass: ${report.summary.index.passed}/${report.summary.fixtures} (recall@${BENCHMARK_TOP_K}: ${report.summary.index.recallAtK}/${report.summary.fixtures})`,
62
+ `- FTS5/BM25/trigram pass: ${report.summary.fts.passed}/${report.summary.fixtures} (skipped: ${report.summary.fts.skipped}; recall@${BENCHMARK_TOP_K}: ${report.summary.fts.recallAtK}/${report.summary.fixtures})`,
63
+ `- Hybrid warm pass: ${report.summary.hybrid.passed}/${report.summary.fixtures} (recall@${BENCHMARK_TOP_K}: ${report.summary.hybrid.recallAtK}/${report.summary.fixtures})`,
64
+ `- FTS5/BM25/trigram candidate: ${report.summary.ftsCandidate.available ? "available" : "unavailable"} — ${report.summary.ftsCandidate.reason}`,
57
65
  `- Generated false positives: ${report.summary.generatedFalsePositiveCount}/${report.summary.modeResults}`,
58
66
  `- Cold build p50/p95: ${report.summary.coldBuildMs.p50.toFixed(2)}/${report.summary.coldBuildMs.p95.toFixed(2)} ms`,
59
67
  `- Warm query p50/p95: ${report.summary.warmQueryMs.p50.toFixed(2)}/${report.summary.warmQueryMs.p95.toFixed(2)} ms`,
@@ -62,21 +70,21 @@ export function renderIndexBenchmarkReport(report) {
62
70
  "",
63
71
  "## Results",
64
72
  "",
65
- "| fixture | mode | correctness | checks | path | lines | raw/context bytes | context reduction | latency p50/p95 ms | build/query ms | index mode | notes |",
66
- "| --- | --- | --- | --- | --- | --- | ---: | ---: | ---: | ---: | --- | --- |",
73
+ "| fixture | mode | correctness | checks | path | lines | candidates | raw/context bytes | context reduction | latency p50/p95 ms | build/query ms | index mode | notes |",
74
+ "| --- | --- | --- | --- | --- | --- | --- | ---: | ---: | ---: | ---: | --- | --- |",
67
75
  ];
68
76
  for (const fixture of report.fixtures) {
69
77
  for (const result of fixture.results) {
70
- const correctness = result.correctness.passed ? "pass" : "fail";
78
+ const correctness = result.skipped ? "skipped" : result.correctness.passed ? "pass" : "fail";
71
79
  const checks = formatCorrectnessChecks(result.correctness);
72
80
  const buildQuery = `${(result.buildMs ?? 0).toFixed(2)}/${(result.queryMs ?? 0).toFixed(2)}`;
73
81
  const notes = result.notes.length ? result.notes.join("; ") : "";
74
- lines.push(`| ${escapeTable(fixture.id)} | ${escapeTable(result.mode)} | ${correctness} | ${escapeTable(checks)} | ${escapeTable(result.actualPath ?? "-")} | ${escapeTable(result.actualLines ?? "-")} | ${result.rawBytes}/${result.contextBytes} | ${formatPercent(result.contextReductionPercent)} | ${result.latencyMs.p50.toFixed(2)}/${result.latencyMs.p95.toFixed(2)} | ${buildQuery} | ${escapeTable(result.indexMode ?? "-")} | ${escapeTable(notes)} |`);
82
+ lines.push(`| ${escapeTable(fixture.id)} | ${escapeTable(result.mode)} | ${correctness} | ${escapeTable(checks)} | ${escapeTable(result.actualPath ?? "-")} | ${escapeTable(result.actualLines ?? "-")} | ${escapeTable(result.candidatePaths.join(", ") || "-")} | ${result.rawBytes}/${result.contextBytes} | ${formatPercent(result.contextReductionPercent)} | ${result.latencyMs.p50.toFixed(2)}/${result.latencyMs.p95.toFixed(2)} | ${buildQuery} | ${escapeTable(result.indexMode ?? "-")} | ${escapeTable(notes)} |`);
75
83
  }
76
84
  }
77
- lines.push("", "## Adoption Decision", "", "Index adopted by default: no. This slice only adds an experiment and benchmark evidence; scanner behavior remains the default until a later adoption checkpoint explicitly approves otherwise.", "", "## Regression Status", "", report.summary.index.failed === 0
78
- ? "Warm experimental index passed all gated fixtures without generated-artifact false positives."
79
- : `Warm experimental index failed ${report.summary.index.failed} fixture(s).`, "");
85
+ lines.push("", "## Adoption Decision", "", "Index adopted by default: no. This slice only records benchmark evidence; scanner behavior remains the default until a later adoption checkpoint explicitly approves otherwise.", "", "## Regression Status", "", report.summary.index.failed === 0 && report.summary.fts.failed === 0 && report.summary.hybrid.failed === 0
86
+ ? "Warm experimental index, FTS5/BM25/trigram, and hybrid modes passed all gated fixtures without generated-artifact false positives."
87
+ : `Failures: warm index ${report.summary.index.failed}, FTS5/BM25/trigram ${report.summary.fts.failed}, hybrid ${report.summary.hybrid.failed}.`, "");
80
88
  return lines.join("\n");
81
89
  }
82
90
  export async function writeIndexBenchmarkReport(report, reportPath) {
@@ -104,20 +112,25 @@ async function runIndexFixtureMode(fixture, mode, iterations) {
104
112
  latencies.push(performance.now() - startedAt);
105
113
  }
106
114
  if (!observation) {
107
- observation = { toolPathUsed: mode, rawBytes: 0, contextBytes: 0, excerpt: "", notes: ["no observation"] };
115
+ observation = { toolPathUsed: mode, skipped: true, skipReason: "No observation was produced.", rawBytes: 0, contextBytes: 0, excerpt: "", notes: ["no observation"] };
108
116
  }
109
117
  const correctness = scoreCorrectness(fixtureExpectedForMode(fixture, mode), observation);
110
118
  const result = {
111
119
  mode,
112
120
  toolPathUsed: observation.toolPathUsed,
121
+ skipped: observation.skipped ?? false,
113
122
  rawBytes: observation.rawBytes,
114
123
  contextBytes: observation.contextBytes,
115
124
  contextReductionPercent: reductionPercent(observation.rawBytes, observation.contextBytes),
116
125
  latencyMs: latencySummary(latencies),
126
+ candidatePaths: observation.candidatePaths ?? [],
117
127
  excerpt: observation.excerpt,
118
128
  correctness,
119
129
  notes: observation.notes ?? [],
120
130
  };
131
+ if (observation.skipReason) {
132
+ result.skipReason = observation.skipReason;
133
+ }
121
134
  if (observation.buildMs !== undefined) {
122
135
  result.buildMs = observation.buildMs;
123
136
  }
@@ -145,13 +158,20 @@ async function observeIndexFixture(fixture, mode) {
145
158
  await writeFixtureFiles(root.path, fixture.staleFiles ?? { "stale-marker.txt": "stale refresh marker" });
146
159
  return await indexObservation(root.path, cacheRoot.path, fixture.staleQuery ?? fixture.query, mode);
147
160
  }
148
- const finalFiles = mode === "scanner-default" || mode === "index-cold" || mode === "index-warm"
161
+ const finalFiles = mode === "scanner-default" || mode === "index-cold" || mode === "index-warm" || mode === "fts5-bm25-trigram" || mode === "hybrid-warm"
149
162
  ? { ...fixture.files, ...(fixture.staleFiles && fixture.staleExpected ? fixture.staleFiles : {}) }
150
163
  : fixture.files;
151
164
  await writeFixtureFiles(root.path, finalFiles);
152
165
  if (mode === "scanner-default") {
153
166
  return await scannerObservation(root.path, fixture.staleQuery && fixture.staleExpected ? fixture.staleQuery : fixture.query);
154
167
  }
168
+ if (mode === "fts5-bm25-trigram") {
169
+ return await ftsObservation(root.path, fixture.staleQuery && fixture.staleExpected ? fixture.staleQuery : fixture.query);
170
+ }
171
+ if (mode === "hybrid-warm") {
172
+ await buildOrLoadExperimentalRepoIndex({ root: root.path, cacheRoot: cacheRoot.path });
173
+ return await hybridObservation(root.path, cacheRoot.path, fixture.staleQuery && fixture.staleExpected ? fixture.staleQuery : fixture.query);
174
+ }
155
175
  if (mode === "index-warm") {
156
176
  await buildOrLoadExperimentalRepoIndex({ root: root.path, cacheRoot: cacheRoot.path });
157
177
  return await indexObservation(root.path, cacheRoot.path, fixture.staleQuery && fixture.staleExpected ? fixture.staleQuery : fixture.query, mode);
@@ -165,15 +185,17 @@ async function observeIndexFixture(fixture, mode) {
165
185
  async function scannerObservation(root, query) {
166
186
  const rawBytes = await repoRawBytes(root);
167
187
  const queryStartedAt = performance.now();
168
- const result = await freeflowRetrieve({ action: "query", source: { kind: "repo", root }, query, preserve: "important" });
188
+ const result = await freeflowSearch({ action: "query", source: { kind: "repo", root }, query, preserve: "important", topK: BENCHMARK_TOP_K });
169
189
  const queryMs = performance.now() - queryStartedAt;
170
190
  const evidence = result.evidence?.[0];
191
+ const candidatePaths = uniqueCandidatePaths(result.evidence?.map((packet) => packet.path));
171
192
  return {
172
- toolPathUsed: "scanner-default: freeflowRetrieve repo scanner",
193
+ toolPathUsed: "scanner-default: freeflowSearch repo scanner",
173
194
  rawBytes,
174
195
  contextBytes: byteLength(JSON.stringify(result)),
175
196
  ...(evidence?.path !== undefined ? { actualPath: evidence.path } : {}),
176
197
  ...(evidence?.lines !== undefined ? { actualLines: evidence.lines } : {}),
198
+ candidatePaths,
177
199
  excerpt: evidence?.excerpt ?? "",
178
200
  queryMs,
179
201
  notes: [result.routing.reason],
@@ -183,7 +205,7 @@ async function indexObservation(root, cacheRoot, query, mode) {
183
205
  const rawBytes = await repoRawBytes(root);
184
206
  const load = await buildOrLoadExperimentalRepoIndex({ root, cacheRoot });
185
207
  const queryStartedAt = performance.now();
186
- const candidates = queryExperimentalRepoIndex(load.index, query, { topK: 1 });
208
+ const candidates = queryExperimentalRepoIndex(load.index, query, { topK: BENCHMARK_TOP_K });
187
209
  const queryMs = performance.now() - queryStartedAt;
188
210
  const candidate = candidates[0];
189
211
  return {
@@ -192,6 +214,7 @@ async function indexObservation(root, cacheRoot, query, mode) {
192
214
  contextBytes: byteLength(JSON.stringify(candidates)),
193
215
  ...(candidate?.path !== undefined ? { actualPath: candidate.path } : {}),
194
216
  ...(candidate?.lines !== undefined ? { actualLines: candidate.lines } : {}),
217
+ candidatePaths: uniqueCandidatePaths(candidates.map((entry) => entry.path)),
195
218
  excerpt: candidate?.excerpt ?? "",
196
219
  buildMs: load.buildMs,
197
220
  queryMs,
@@ -199,9 +222,250 @@ async function indexObservation(root, cacheRoot, query, mode) {
199
222
  notes: candidate ? [candidate.reason, `cachePath=${load.cachePath}`, ...(load.refreshReason ? [`refresh=${load.refreshReason}`] : [])] : ["no index candidate"],
200
223
  };
201
224
  }
225
+ async function ftsObservation(root, query) {
226
+ const rawBytes = await repoRawBytes(root);
227
+ const ftsStatus = detectFtsCandidateStatus();
228
+ if (!ftsStatus.available) {
229
+ return {
230
+ toolPathUsed: "fts5-bm25-trigram: unavailable optional candidate",
231
+ skipped: true,
232
+ skipReason: ftsStatus.reason,
233
+ rawBytes,
234
+ contextBytes: 0,
235
+ candidatePaths: [],
236
+ excerpt: "",
237
+ notes: [ftsStatus.reason],
238
+ };
239
+ }
240
+ const files = await readFtsTextFiles(root);
241
+ const sqlite = loadSqliteModule();
242
+ const startedAt = performance.now();
243
+ const db = new sqlite.DatabaseSync(":memory:");
244
+ try {
245
+ db.exec("CREATE VIRTUAL TABLE docs USING fts5(path UNINDEXED, body, tokenize='trigram')");
246
+ const insert = db.prepare("INSERT INTO docs(path, body) VALUES (?, ?)");
247
+ for (const file of files) {
248
+ insert.run(file.path, file.text);
249
+ }
250
+ const matchQuery = ftsMatchQuery(query);
251
+ const rows = matchQuery
252
+ ? db.prepare("SELECT path, bm25(docs) AS rank FROM docs WHERE docs MATCH ? ORDER BY rank LIMIT ?").all(matchQuery, BENCHMARK_TOP_K)
253
+ : [];
254
+ const queryMs = performance.now() - startedAt;
255
+ const byPath = new Map(files.map((file) => [file.path, file]));
256
+ const candidates = rows.flatMap((row) => {
257
+ const file = byPath.get(row.path);
258
+ if (!file) {
259
+ return [];
260
+ }
261
+ const range = bestFtsLineRange(file, query);
262
+ return [{
263
+ path: file.path,
264
+ lines: `${range.start}-${range.end}`,
265
+ excerpt: file.lines.slice(range.start - 1, range.end).join("\n"),
266
+ rank: row.rank,
267
+ reason: `SQLite FTS5 trigram MATCH with bm25 rank ${row.rank.toFixed(6)}`,
268
+ }];
269
+ });
270
+ const first = candidates[0];
271
+ return {
272
+ toolPathUsed: "fts5-bm25-trigram: node:sqlite FTS5 trigram virtual table",
273
+ rawBytes,
274
+ contextBytes: byteLength(JSON.stringify(candidates)),
275
+ ...(first?.path !== undefined ? { actualPath: first.path } : {}),
276
+ ...(first?.lines !== undefined ? { actualLines: first.lines } : {}),
277
+ candidatePaths: uniqueCandidatePaths(candidates.map((candidate) => candidate.path)),
278
+ excerpt: first?.excerpt ?? "",
279
+ buildMs: queryMs,
280
+ queryMs,
281
+ notes: first ? [first.reason] : ["no FTS5 candidate"],
282
+ };
283
+ }
284
+ finally {
285
+ db.close();
286
+ }
287
+ }
288
+ async function hybridObservation(root, cacheRoot, query) {
289
+ const rawBytes = await repoRawBytes(root);
290
+ const load = await buildOrLoadExperimentalRepoIndex({ root, cacheRoot });
291
+ const indexStartedAt = performance.now();
292
+ const indexCandidates = queryExperimentalRepoIndex(load.index, query, { topK: BENCHMARK_TOP_K });
293
+ const indexQueryMs = performance.now() - indexStartedAt;
294
+ const scannerStartedAt = performance.now();
295
+ const scanner = await freeflowSearch({ action: "query", source: { kind: "repo", root }, query, preserve: "important", topK: BENCHMARK_TOP_K });
296
+ const scannerQueryMs = performance.now() - scannerStartedAt;
297
+ const scannerEvidence = scanner.evidence?.[0];
298
+ const scannerPaths = uniqueCandidatePaths(scanner.evidence?.map((packet) => packet.path));
299
+ const indexPaths = uniqueCandidatePaths(indexCandidates.map((candidate) => candidate.path));
300
+ const hybridInput = { scannerPaths, indexCandidates, indexPaths };
301
+ if (scannerEvidence !== undefined) {
302
+ hybridInput.scannerEvidence = scannerEvidence;
303
+ }
304
+ const selected = chooseHybridCandidate(hybridInput);
305
+ const contextPayload = {
306
+ selected: selected.payload,
307
+ scannerCandidateCount: scannerPaths.length,
308
+ indexCandidateCount: indexPaths.length,
309
+ selection: selected.selection,
310
+ };
311
+ return {
312
+ toolPathUsed: "hybrid-warm: scanner fallback with warm lexical-index candidates",
313
+ rawBytes,
314
+ contextBytes: byteLength(JSON.stringify(contextPayload)),
315
+ ...(selected.path !== undefined ? { actualPath: selected.path } : {}),
316
+ ...(selected.lines !== undefined ? { actualLines: selected.lines } : {}),
317
+ candidatePaths: uniqueCandidatePaths([...scannerPaths, ...indexPaths]),
318
+ excerpt: selected.excerpt,
319
+ buildMs: load.buildMs,
320
+ queryMs: indexQueryMs + scannerQueryMs,
321
+ indexMode: load.mode,
322
+ notes: [
323
+ `selection=${selected.selection}`,
324
+ `scannerQueryMs=${scannerQueryMs.toFixed(2)}`,
325
+ `indexQueryMs=${indexQueryMs.toFixed(2)}`,
326
+ ...(load.refreshReason ? [`refresh=${load.refreshReason}`] : []),
327
+ ],
328
+ };
329
+ }
330
+ function chooseHybridCandidate(options) {
331
+ const scannerEvidence = options.scannerEvidence;
332
+ if (scannerEvidence?.path) {
333
+ const indexAgrees = options.indexPaths.includes(scannerEvidence.path);
334
+ return {
335
+ selection: indexAgrees ? "scanner-index-agree" : "scanner-fallback",
336
+ path: scannerEvidence.path,
337
+ ...(scannerEvidence.lines !== undefined ? { lines: scannerEvidence.lines } : {}),
338
+ excerpt: scannerEvidence.excerpt ?? "",
339
+ payload: {
340
+ source: "scanner",
341
+ path: scannerEvidence.path,
342
+ ...(scannerEvidence.lines !== undefined ? { lines: scannerEvidence.lines } : {}),
343
+ indexAgrees,
344
+ },
345
+ };
346
+ }
347
+ const indexCandidate = options.indexCandidates[0];
348
+ if (indexCandidate) {
349
+ return {
350
+ selection: "index-only",
351
+ path: indexCandidate.path,
352
+ lines: indexCandidate.lines,
353
+ excerpt: indexCandidate.excerpt,
354
+ payload: {
355
+ source: "index",
356
+ path: indexCandidate.path,
357
+ lines: indexCandidate.lines,
358
+ score: indexCandidate.score,
359
+ },
360
+ };
361
+ }
362
+ return { selection: "none", excerpt: "", payload: { source: "none" } };
363
+ }
364
+ function detectFtsCandidateStatus() {
365
+ if (cachedFtsCandidateStatus !== undefined) {
366
+ return cachedFtsCandidateStatus;
367
+ }
368
+ let db;
369
+ try {
370
+ const sqlite = loadSqliteModule();
371
+ db = new sqlite.DatabaseSync(":memory:");
372
+ db.exec("CREATE VIRTUAL TABLE docs USING fts5(path UNINDEXED, body, tokenize='trigram')");
373
+ db.exec("INSERT INTO docs(path, body) VALUES ('probe', 'freeflow fts probe')");
374
+ const rows = db.prepare("SELECT path, bm25(docs) AS rank FROM docs WHERE docs MATCH ?").all("freeflow AND probe");
375
+ cachedFtsCandidateStatus = rows.length > 0
376
+ ? {
377
+ available: true,
378
+ engine: "fts5-bm25-trigram",
379
+ reason: "Node node:sqlite is available and supports SQLite FTS5 trigram tokenization with bm25 ranking.",
380
+ }
381
+ : {
382
+ available: false,
383
+ engine: "none",
384
+ reason: "SQLite FTS5 probe returned no rows for a known trigram query.",
385
+ };
386
+ }
387
+ catch (error) {
388
+ const message = error instanceof Error ? error.message : String(error);
389
+ cachedFtsCandidateStatus = {
390
+ available: false,
391
+ engine: "none",
392
+ reason: `SQLite FTS5/BM25/trigram candidate unavailable: ${message}`,
393
+ };
394
+ }
395
+ finally {
396
+ db?.close();
397
+ }
398
+ return cachedFtsCandidateStatus;
399
+ }
400
+ function loadSqliteModule() {
401
+ return require("node:sqlite");
402
+ }
403
+ async function readFtsTextFiles(root) {
404
+ const files = [];
405
+ await collectFtsTextFiles(root, root, files);
406
+ return files.sort((a, b) => a.path.localeCompare(b.path));
407
+ }
408
+ async function collectFtsTextFiles(root, currentPath, files) {
409
+ const currentStat = await stat(currentPath);
410
+ if (currentStat.isDirectory()) {
411
+ const dirEntries = await readdir(currentPath, { withFileTypes: true });
412
+ for (const entry of dirEntries.sort((a, b) => a.name.localeCompare(b.name))) {
413
+ await collectFtsTextFiles(root, resolve(currentPath, entry.name), files);
414
+ }
415
+ return;
416
+ }
417
+ if (!currentStat.isFile()) {
418
+ return;
419
+ }
420
+ const path = relative(root, currentPath).split(/[\\/]+/).join("/");
421
+ if (isGeneratedBenchmarkPath(path)) {
422
+ return;
423
+ }
424
+ try {
425
+ const text = await readFile(currentPath, "utf8");
426
+ if (!text.includes("\0")) {
427
+ files.push({ path, text, lines: splitLines(text) });
428
+ }
429
+ }
430
+ catch {
431
+ // ignore non-text fixture files
432
+ }
433
+ }
434
+ function ftsMatchQuery(query) {
435
+ return searchTokens(query).filter((token) => token.length >= 3).join(" AND ");
436
+ }
437
+ function bestFtsLineRange(file, query) {
438
+ const tokens = searchTokens(query);
439
+ let bestIndex = 0;
440
+ let bestScore = -1;
441
+ for (let index = 0; index < file.lines.length; index += 1) {
442
+ const normalizedLine = (file.lines[index] ?? "").toLowerCase();
443
+ const score = tokens.reduce((sum, token) => sum + (normalizedLine.includes(token) ? 1 : 0), 0);
444
+ if (score > bestScore) {
445
+ bestScore = score;
446
+ bestIndex = index;
447
+ }
448
+ }
449
+ const start = Math.max(1, bestIndex + 1 - FTS_CONTEXT_LINES);
450
+ const end = Math.min(file.lines.length, bestIndex + 1 + FTS_CONTEXT_LINES);
451
+ return { start, end };
452
+ }
453
+ function searchTokens(value) {
454
+ const seen = new Set();
455
+ const tokens = [];
456
+ for (const token of value.toLowerCase().match(/[a-z0-9_]+/g) ?? []) {
457
+ if (!seen.has(token)) {
458
+ seen.add(token);
459
+ tokens.push(token);
460
+ }
461
+ }
462
+ return tokens;
463
+ }
202
464
  function summarizeIndexReport(fixtures) {
203
465
  const scanner = summarizeMode(fixtures, "scanner-default");
204
466
  const index = summarizeMode(fixtures, "index-warm");
467
+ const fts = summarizeMode(fixtures, "fts5-bm25-trigram");
468
+ const hybrid = summarizeMode(fixtures, "hybrid-warm");
205
469
  const generatedFalsePositiveCount = fixtures
206
470
  .flatMap((fixture) => fixture.results)
207
471
  .filter((result) => result.correctness.generatedFalsePositive).length;
@@ -213,8 +477,11 @@ function summarizeIndexReport(fixtures) {
213
477
  modeResults: fixtures.reduce((count, fixture) => count + fixture.results.length, 0),
214
478
  scannerDefault: true,
215
479
  indexAdopted: false,
480
+ ftsCandidate: detectFtsCandidateStatus(),
216
481
  scanner,
217
482
  index,
483
+ fts,
484
+ hybrid,
218
485
  generatedFalsePositiveCount,
219
486
  coldBuildMs,
220
487
  warmQueryMs,
@@ -228,7 +495,10 @@ function summarizeMode(fixtures, mode) {
228
495
  const totalRawBytes = results.reduce((sum, result) => sum + result.rawBytes, 0);
229
496
  const totalContextBytes = results.reduce((sum, result) => sum + result.contextBytes, 0);
230
497
  return results.reduce((summary, result) => {
231
- if (result.correctness.passed) {
498
+ if (result.skipped) {
499
+ summary.skipped += 1;
500
+ }
501
+ else if (result.correctness.passed) {
232
502
  summary.passed += 1;
233
503
  }
234
504
  else {
@@ -243,13 +513,18 @@ function summarizeMode(fixtures, mode) {
243
513
  if (result.correctness.excerptComplete) {
244
514
  summary.excerptComplete += 1;
245
515
  }
516
+ if (result.correctness.recallAtK) {
517
+ summary.recallAtK += 1;
518
+ }
246
519
  return summary;
247
520
  }, {
248
521
  passed: 0,
249
522
  failed: 0,
523
+ skipped: 0,
250
524
  pathCorrect: 0,
251
525
  spanCorrect: 0,
252
526
  excerptComplete: 0,
527
+ recallAtK: 0,
253
528
  totalRawBytes,
254
529
  totalContextBytes,
255
530
  weightedContextReductionPercent: reductionPercent(totalRawBytes, totalContextBytes),
@@ -336,15 +611,28 @@ function fixtureExpectedForMode(fixture, mode) {
336
611
  return fixture.expected;
337
612
  }
338
613
  function scoreCorrectness(expected, observation) {
614
+ if (observation.skipped) {
615
+ return {
616
+ passed: false,
617
+ pathCorrect: false,
618
+ spanCorrect: false,
619
+ excerptComplete: false,
620
+ recallAtK: false,
621
+ generatedFalsePositive: false,
622
+ };
623
+ }
339
624
  const pathCorrect = observation.actualPath === expected.path;
340
625
  const spanCorrect = expected.lines ? Boolean(observation.actualLines && rangesOverlap(expected.lines, observation.actualLines)) : true;
341
626
  const excerptComplete = expected.requiredExcerpt.every((snippet) => observation.excerpt.toLowerCase().includes(snippet.toLowerCase()));
627
+ const candidatePaths = observation.candidatePaths ?? [];
628
+ const recallAtK = candidatePaths.length === 0 ? pathCorrect : candidatePaths.includes(expected.path);
342
629
  const generatedFalsePositive = observation.actualPath ? isGeneratedBenchmarkPath(observation.actualPath) : false;
343
630
  return {
344
- passed: pathCorrect && spanCorrect && excerptComplete && !generatedFalsePositive,
631
+ passed: pathCorrect && spanCorrect && excerptComplete && recallAtK && !generatedFalsePositive,
345
632
  pathCorrect,
346
633
  spanCorrect,
347
634
  excerptComplete,
635
+ recallAtK,
348
636
  generatedFalsePositive,
349
637
  };
350
638
  }
@@ -392,7 +680,7 @@ async function createTempDir(prefix) {
392
680
  };
393
681
  }
394
682
  function indexBenchmarkModes() {
395
- return ["scanner-default", "index-cold", "index-warm", "index-stale-refresh"];
683
+ return ["scanner-default", "index-cold", "index-warm", "index-stale-refresh", "fts5-bm25-trigram", "hybrid-warm"];
396
684
  }
397
685
  function rangesOverlap(left, right) {
398
686
  const leftRange = parseRange(left);
@@ -411,6 +699,18 @@ function parseRange(range) {
411
699
  const end = Number(match[2]);
412
700
  return Number.isInteger(start) && Number.isInteger(end) ? { start, end } : null;
413
701
  }
702
+ function uniqueCandidatePaths(paths) {
703
+ const seen = new Set();
704
+ const unique = [];
705
+ for (const path of paths ?? []) {
706
+ if (!path || seen.has(path)) {
707
+ continue;
708
+ }
709
+ seen.add(path);
710
+ unique.push(path);
711
+ }
712
+ return unique;
713
+ }
414
714
  function isGeneratedBenchmarkPath(path) {
415
715
  const segments = path.split(/[\\/]+/);
416
716
  if (segments.includes("graphify-out")) {
@@ -419,6 +719,9 @@ function isGeneratedBenchmarkPath(path) {
419
719
  const name = segments.at(-1)?.toLowerCase() ?? path.toLowerCase();
420
720
  return name.endsWith(".log") || name.endsWith(".map") || name.endsWith(".min.js") || name.endsWith(".min.css") || name.includes(".bundle.");
421
721
  }
722
+ function splitLines(text) {
723
+ return text.split(/\r?\n/);
724
+ }
422
725
  function byteLength(value) {
423
726
  return Buffer.byteLength(value, "utf8");
424
727
  }
@@ -427,11 +730,12 @@ function formatCorrectnessChecks(correctness) {
427
730
  `path ${correctness.pathCorrect ? "✓" : "✗"}`,
428
731
  `span ${correctness.spanCorrect ? "✓" : "✗"}`,
429
732
  `excerpt ${correctness.excerptComplete ? "✓" : "✗"}`,
733
+ `recall@${BENCHMARK_TOP_K} ${correctness.recallAtK ? "✓" : "✗"}`,
430
734
  `gen-fp ${correctness.generatedFalsePositive ? "✗" : "✓"}`,
431
735
  ].join(" ");
432
736
  }
433
737
  function defaultReportPath() {
434
- return resolve(process.cwd(), "plugins/freeflow/evals/reports/runtime/output-router-index-benchmark-1-report.md");
738
+ return resolve(process.cwd(), "evals/reports/runtime/output-router-index-benchmark-1-report.md");
435
739
  }
436
740
  async function runCli() {
437
741
  const { iterations, reportPath, jsonReportPath } = parseBenchmarkCliArgs(process.argv.slice(2), { reportPath: defaultReportPath() });
@@ -444,12 +748,12 @@ async function runCli() {
444
748
  jsonReportPath: jsonReportPath === undefined ? defaultJsonRunReportPath(reportPath) : jsonReportPath,
445
749
  });
446
750
  const shortId = createHash("sha256").update(JSON.stringify(report.summary)).digest("hex").slice(0, 8);
447
- console.log(`Freeflow index benchmark ${shortId}: index ${report.summary.index.passed}/${report.summary.fixtures} pass`);
751
+ console.log(`Freeflow repo search backend benchmark ${shortId}: scanner ${report.summary.scanner.passed}/${report.summary.fixtures}, index ${report.summary.index.passed}/${report.summary.fixtures}, fts ${report.summary.fts.passed}/${report.summary.fixtures}, hybrid ${report.summary.hybrid.passed}/${report.summary.fixtures} pass`);
448
752
  console.log(`Markdown report: ${reports.markdown}`);
449
753
  if (reports.json) {
450
754
  console.log(`JSON run data: ${reports.json}`);
451
755
  }
452
- if (report.summary.index.failed > 0) {
756
+ if (report.summary.scanner.failed > 0 || report.summary.index.failed > 0 || report.summary.fts.failed > 0 || report.summary.hybrid.failed > 0) {
453
757
  process.exitCode = 1;
454
758
  }
455
759
  }
@@ -0,0 +1,90 @@
1
+ import type { ExecutionStatus } from "../config/types.js";
2
+ export interface StoragePolicyBenchmarkOptions {
3
+ iterations?: number;
4
+ generatedAt?: string;
5
+ }
6
+ export interface StoragePolicyBenchmarkReport {
7
+ generatedAt: string;
8
+ iterations: number;
9
+ summary: StoragePolicyBenchmarkSummary;
10
+ fixtures: StoragePolicyFixtureDefinition[];
11
+ policies: StoragePolicyResult[];
12
+ }
13
+ export interface StoragePolicyBenchmarkSummary {
14
+ fixtures: number;
15
+ policies: number;
16
+ safeCandidateIds: string[];
17
+ disqualifiedCandidateIds: string[];
18
+ defaultUnchanged: true;
19
+ }
20
+ export interface StoragePolicyResult {
21
+ policyId: StoragePolicyId;
22
+ label: string;
23
+ description: string;
24
+ totals: StoragePolicyTotals;
25
+ safety: StoragePolicySafety;
26
+ fixtures: StoragePolicyFixtureResult[];
27
+ notes: string[];
28
+ }
29
+ export interface StoragePolicyTotals {
30
+ rawCombinedBytes: number;
31
+ rawCombinedTokensApprox: number;
32
+ exactStoredCombinedBytes: number;
33
+ exactStoredTokensApprox: number;
34
+ storageBytes: number;
35
+ indexBytes: number;
36
+ metadataOnlyRecords: number;
37
+ exactRecords: number;
38
+ duplicateMetadataRecords: number;
39
+ storageReductionPercent: number;
40
+ tokenSurfaceReductionPercent: number;
41
+ privacySurfacePercent: number;
42
+ latencyMs: {
43
+ p50: number;
44
+ p95: number;
45
+ };
46
+ }
47
+ export interface StoragePolicySafety {
48
+ exactnessSensitiveFixtures: number;
49
+ exactnessSensitiveRecoverable: number;
50
+ exactnessSensitiveRecoveryPassed: boolean;
51
+ metadataOnlyRecoveryLabeled: boolean;
52
+ repeatedOutputsDeduped: boolean;
53
+ }
54
+ export interface StoragePolicyFixtureResult {
55
+ fixtureId: string;
56
+ iteration: number;
57
+ outputId: string;
58
+ recordKind: "command" | "metadata";
59
+ persistence: string;
60
+ recoverability: string;
61
+ rawCombinedBytes: number;
62
+ exactStoredCombinedBytes: number;
63
+ latencyMs: number;
64
+ exactRecovery: "passed" | "failed" | "not-exact";
65
+ usefulRecovery: "exact" | "metadata-only" | "duplicate-ref" | "none";
66
+ duplicateOf?: string;
67
+ exactnessSensitive: boolean;
68
+ notes: string[];
69
+ }
70
+ interface StoragePolicyFixtureDefinition {
71
+ id: string;
72
+ title: string;
73
+ command: string;
74
+ stdout: string;
75
+ stderr: string;
76
+ executionStatus: ExecutionStatus;
77
+ exitCode: number | null;
78
+ exactnessSensitive: boolean;
79
+ repeatedGroup?: string;
80
+ }
81
+ type StoragePolicyId = "store-everything" | "threshold-exact" | "metadata-small-exact-large-hybrid" | "duplicate-output-dedupe" | "hybrid-dedupe";
82
+ export declare function runStoragePolicyBenchmarks(options?: StoragePolicyBenchmarkOptions): Promise<StoragePolicyBenchmarkReport>;
83
+ export declare function renderStoragePolicyBenchmarkReport(report: StoragePolicyBenchmarkReport): string;
84
+ export declare function writeStoragePolicyBenchmarkReports(report: StoragePolicyBenchmarkReport, markdownReportPath?: string, options?: {
85
+ jsonReportPath?: string | false;
86
+ }): Promise<{
87
+ markdown: string;
88
+ json?: string;
89
+ }>;
90
+ export {};