@hassangameryt/freeflow 0.3.0 → 0.5.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 (692) hide show
  1. package/.claude-plugin/marketplace.json +4 -4
  2. package/.claude-plugin/plugin.json +6 -2
  3. package/.codex-plugin/plugin.json +9 -9
  4. package/README.md +190 -127
  5. package/assets/feedback-loop.png +0 -0
  6. package/assets/freeflow_workflow_map.png +0 -0
  7. package/assets/workflow.png +0 -0
  8. package/{skills → capabilities}/output-router/SKILL.md +21 -17
  9. package/{skills → capabilities}/output-router/references/safety-policy.md +1 -1
  10. package/capabilities/output-router/references/setup.md +110 -0
  11. package/command-surface.json +62 -7
  12. package/hooks/freeflow-runtime-context.mjs +572 -154
  13. package/hooks/hooks.json +26 -1
  14. package/hooks/tests/check-runtime-context-hook.sh +375 -0
  15. package/package.json +24 -24
  16. package/pi-extension/dist/index.js +264 -80
  17. package/pi-extension/dist/integrations/mcp-config.js +29 -0
  18. package/pi-extension/dist/output-router/host-producer-identification.js +232 -0
  19. package/pi-extension/dist/output-router/native-safety-net.js +216 -0
  20. package/pi-extension/dist/output-router/observed-tool-routing.js +122 -0
  21. package/pi-extension/dist/output-router/renderers.js +1023 -0
  22. package/pi-extension/dist/output-router/router-tools.js +554 -0
  23. package/pi-extension/dist/output-router/schemas.js +383 -0
  24. package/pi-extension/dist/output-router/status.js +744 -0
  25. package/pi-extension/dist/output-router/utils.js +502 -0
  26. package/pi-extension/dist/runtime/runtime-context.js +798 -0
  27. package/pi-extension/dist/settings/settings-tui.js +314 -0
  28. package/pi-extension/dist/settings/settings-ui.js +1487 -0
  29. package/pi-extension/freeflow/index.js +1 -0
  30. package/pi-extension/src/index.ts +230 -56
  31. package/pi-extension/src/{host-producer-identification.ts → output-router/host-producer-identification.ts} +37 -7
  32. package/pi-extension/src/{native-safety-net.ts → output-router/native-safety-net.ts} +8 -12
  33. package/pi-extension/src/{observed-tool-routing.ts → output-router/observed-tool-routing.ts} +19 -11
  34. package/pi-extension/src/{renderers.ts → output-router/renderers.ts} +246 -55
  35. package/pi-extension/src/{router-tools.ts → output-router/router-tools.ts} +130 -29
  36. package/pi-extension/src/{schemas.ts → output-router/schemas.ts} +171 -43
  37. package/pi-extension/src/output-router/status.ts +791 -0
  38. package/pi-extension/src/{utils.ts → output-router/utils.ts} +80 -18
  39. package/pi-extension/src/runtime/runtime-context.ts +895 -0
  40. package/pi-extension/src/settings/settings-tui.ts +408 -0
  41. package/pi-extension/src/settings/settings-ui.ts +1730 -0
  42. package/pi-extension/tests/integration/pi-extension.test.js +4020 -0
  43. package/pi-extension/tests/output-router/observed-producers.test.js +132 -0
  44. package/pi-extension/tests/output-router/search.test.js +722 -0
  45. package/pi-extension/tests/settings/settings-tui.test.js +243 -0
  46. package/router/dist/benchmarks/benchmark-harness.d.ts +16 -13
  47. package/router/dist/benchmarks/benchmark-harness.js +62 -62
  48. package/router/dist/benchmarks/benchmarks.d.ts +80 -73
  49. package/router/dist/benchmarks/benchmarks.js +860 -761
  50. package/router/dist/benchmarks/codex-qa-benchmarks.d.ts +71 -67
  51. package/router/dist/benchmarks/codex-qa-benchmarks.js +429 -390
  52. package/router/dist/benchmarks/command-benchmarks.d.ts +107 -92
  53. package/router/dist/benchmarks/command-benchmarks.js +616 -571
  54. package/router/dist/benchmarks/context-mode-normalized-benchmarks.d.ts +64 -56
  55. package/router/dist/benchmarks/context-mode-normalized-benchmarks.js +679 -613
  56. package/router/dist/benchmarks/context-mode-real-deep-benchmark.d.ts +103 -95
  57. package/router/dist/benchmarks/context-mode-real-deep-benchmark.js +1188 -1103
  58. package/router/dist/benchmarks/context-saving-baseline.d.ts +47 -41
  59. package/router/dist/benchmarks/context-saving-baseline.js +405 -374
  60. package/router/dist/benchmarks/index-benchmarks.d.ts +74 -69
  61. package/router/dist/benchmarks/index-benchmarks.js +761 -661
  62. package/router/dist/benchmarks/storage-policy-benchmarks.d.ts +80 -69
  63. package/router/dist/benchmarks/storage-policy-benchmarks.js +549 -469
  64. package/router/dist/benchmarks/vault-index-benchmarks.d.ts +43 -34
  65. package/router/dist/benchmarks/vault-index-benchmarks.js +294 -229
  66. package/router/dist/config/config.d.ts +62 -55
  67. package/router/dist/config/config.js +552 -373
  68. package/router/dist/config/router-contract.d.ts +2 -2
  69. package/router/dist/config/router-contract.js +38 -38
  70. package/router/dist/config/schema.d.ts +19 -10
  71. package/router/dist/config/schema.js +586 -538
  72. package/router/dist/config/types.d.ts +413 -361
  73. package/router/dist/config/types.js +19 -8
  74. package/router/dist/evidence/bounded-evidence.d.ts +26 -26
  75. package/router/dist/evidence/bounded-evidence.js +265 -252
  76. package/router/dist/evidence/evidence-range-selector.d.ts +16 -14
  77. package/router/dist/evidence/evidence-range-selector.js +192 -191
  78. package/router/dist/evidence/evidence-search.d.ts +18 -16
  79. package/router/dist/evidence/evidence-search.js +401 -377
  80. package/router/dist/evidence/evidence.d.ts +17 -17
  81. package/router/dist/evidence/evidence.js +163 -159
  82. package/router/dist/evidence/failure-contracts.d.ts +25 -15
  83. package/router/dist/evidence/failure-contracts.js +132 -126
  84. package/router/dist/evidence/line-ranges.d.ts +17 -15
  85. package/router/dist/evidence/line-ranges.js +18 -18
  86. package/router/dist/experiments/local-index.d.ts +47 -41
  87. package/router/dist/experiments/local-index.js +477 -458
  88. package/router/dist/local/local-traversal.d.ts +18 -0
  89. package/router/dist/local/local-traversal.js +334 -0
  90. package/router/dist/processing/engine.d.ts +94 -70
  91. package/router/dist/processing/engine.js +462 -364
  92. package/router/dist/processing/reducers.d.ts +208 -194
  93. package/router/dist/processing/reducers.js +1434 -1256
  94. package/router/dist/processing/renderers.d.ts +24 -18
  95. package/router/dist/processing/renderers.js +161 -152
  96. package/router/dist/processing/scripts.d.ts +80 -67
  97. package/router/dist/processing/scripts.js +343 -290
  98. package/router/dist/repo/repo-traversal.d.ts +9 -9
  99. package/router/dist/repo/repo-traversal.js +205 -202
  100. package/router/dist/routing/observed-reducers.d.ts +25 -19
  101. package/router/dist/routing/observed-reducers.js +559 -545
  102. package/router/dist/routing/observed-routing.d.ts +23 -14
  103. package/router/dist/routing/observed-routing.js +319 -318
  104. package/router/dist/routing/parsers.d.ts +10 -10
  105. package/router/dist/routing/parsers.js +454 -406
  106. package/router/dist/routing/run-filters.d.ts +45 -41
  107. package/router/dist/routing/run-filters.js +215 -207
  108. package/router/dist/routing/run-reducers.d.ts +45 -26
  109. package/router/dist/routing/run-reducers.js +102 -90
  110. package/router/dist/sandbox/adapter-roots.d.ts +34 -26
  111. package/router/dist/sandbox/adapter-roots.js +43 -41
  112. package/router/dist/sandbox/eryx-python-adapter.d.ts +9 -5
  113. package/router/dist/sandbox/eryx-python-adapter.js +659 -588
  114. package/router/dist/sandbox/jq-wasm-adapter.d.ts +3 -3
  115. package/router/dist/sandbox/jq-wasm-adapter.js +319 -311
  116. package/router/dist/sandbox/quickjs-wasi-adapter.d.ts +9 -5
  117. package/router/dist/sandbox/quickjs-wasi-adapter.js +336 -333
  118. package/router/dist/sandbox/script-sandbox.d.ts +105 -84
  119. package/router/dist/sandbox/script-sandbox.js +294 -260
  120. package/router/dist/setup/script-transform-adapters.d.ts +23 -19
  121. package/router/dist/setup/script-transform-adapters.js +223 -204
  122. package/router/dist/tools/batch.d.ts +27 -16
  123. package/router/dist/tools/batch.js +493 -416
  124. package/router/dist/tools/run.d.ts +47 -35
  125. package/router/dist/tools/run.js +1172 -1087
  126. package/router/dist/tools/search.d.ts +53 -31
  127. package/router/dist/tools/search.js +1224 -1065
  128. package/router/dist/transform/engine.d.ts +121 -96
  129. package/router/dist/transform/engine.js +1853 -1736
  130. package/router/dist/vault/vault-index.d.ts +97 -78
  131. package/router/dist/vault/vault-index.js +347 -342
  132. package/router/dist/vault/vault.d.ts +109 -74
  133. package/router/dist/vault/vault.js +528 -533
  134. package/runtime/interaction-contract.md +16 -0
  135. package/skills/bypass/SKILL.md +52 -38
  136. package/skills/commit-work/SKILL.md +54 -46
  137. package/skills/commit-work/references/staging-decisions.md +46 -24
  138. package/skills/decision-gate/SKILL.md +48 -0
  139. package/skills/design-for-depth/SKILL.md +75 -59
  140. package/skills/design-for-depth/references/design-pressure-signals.md +56 -7
  141. package/skills/design-for-depth/references/interface-design-loop.md +156 -0
  142. package/skills/design-for-depth/references/software-design-philosophy.md +32 -3
  143. package/skills/diagnose-failure/SKILL.md +65 -60
  144. package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +36 -0
  145. package/skills/diagnose-failure/references/flaky-and-performance.md +30 -18
  146. package/skills/discuss/SKILL.md +121 -0
  147. package/skills/discuss/references/checkpoints.md +66 -0
  148. package/skills/evaluate-skill/SKILL.md +62 -53
  149. package/skills/evaluate-skill/references/definition-schema.md +345 -0
  150. package/skills/evaluate-skill/references/evaluation-design.md +86 -0
  151. package/skills/evaluate-skill/references/execution-and-evidence.md +85 -0
  152. package/skills/evaluate-skill/references/review-and-revision.md +51 -0
  153. package/skills/evaluate-skill/scripts/lib/definitions.mjs +296 -0
  154. package/skills/evaluate-skill/scripts/lib/evidence.mjs +46 -0
  155. package/skills/evaluate-skill/scripts/lib/grade-comparison.mjs +60 -0
  156. package/skills/evaluate-skill/scripts/lib/grade-interaction.mjs +148 -0
  157. package/skills/evaluate-skill/scripts/lib/grade-support.mjs +126 -0
  158. package/skills/evaluate-skill/scripts/lib/grade-workspace.mjs +192 -0
  159. package/skills/evaluate-skill/scripts/lib/grade.mjs +56 -0
  160. package/skills/evaluate-skill/scripts/lib/pi.mjs +489 -0
  161. package/skills/evaluate-skill/scripts/lib/process.mjs +79 -0
  162. package/skills/evaluate-skill/scripts/lib/rpc.mjs +444 -0
  163. package/skills/evaluate-skill/scripts/lib/runner.mjs +346 -0
  164. package/skills/evaluate-skill/scripts/lib/sandbox.mjs +409 -0
  165. package/skills/evaluate-skill/scripts/lib/view.mjs +337 -0
  166. package/skills/evaluate-skill/scripts/pi-guard.mjs +164 -0
  167. package/skills/evaluate-skill/scripts/skill-eval.mjs +101 -0
  168. package/skills/execute-work/SKILL.md +99 -0
  169. package/skills/execute-work/references/code-practices.md +78 -0
  170. package/skills/execute-work/references/execution-loop.md +77 -0
  171. package/skills/finish-branch/SKILL.md +117 -0
  172. package/skills/finish-branch/references/integration-options.md +80 -0
  173. package/skills/handoff/SKILL.md +65 -39
  174. package/skills/handoff/references/templates.md +104 -27
  175. package/skills/launch-work/SKILL.md +116 -0
  176. package/skills/launch-work/references/launch-readiness.md +85 -0
  177. package/skills/migration-work/SKILL.md +115 -0
  178. package/skills/migration-work/references/migration-lifecycle.md +82 -0
  179. package/skills/mode-contract/SKILL.md +72 -52
  180. package/skills/release-work/SKILL.md +118 -0
  181. package/skills/release-work/references/release-evidence.md +78 -0
  182. package/skills/review-artifact/SKILL.md +77 -69
  183. package/skills/review-artifact/references/reviewer-prompt.md +133 -42
  184. package/skills/review-work/SKILL.md +82 -57
  185. package/skills/review-work/references/reviewer-prompt.md +97 -60
  186. package/skills/review-work/references/security-risk-lens.md +67 -0
  187. package/skills/setup-freeflow/SKILL.md +54 -68
  188. package/skills/setup-freeflow/references/activation-contract.md +84 -69
  189. package/skills/setup-freeflow/references/host-setup.md +50 -17
  190. package/skills/simplify-code/SKILL.md +80 -0
  191. package/skills/simplify-code/references/simplification-patterns.md +70 -0
  192. package/skills/tdd/SKILL.md +96 -0
  193. package/skills/tdd/references/test-design.md +96 -0
  194. package/skills/track-work/SKILL.md +84 -0
  195. package/skills/track-work/references/working-record-schema.md +378 -0
  196. package/skills/verify-work/SKILL.md +59 -38
  197. package/skills/verify-work/references/browser-runtime-evidence.md +55 -0
  198. package/skills/verify-work/references/integration-evidence.md +51 -0
  199. package/skills/verify-work/references/performance-evidence.md +57 -0
  200. package/skills/workflow/SKILL.md +53 -59
  201. package/skills/workflow/references/domain-skill-composition.md +57 -0
  202. package/skills/workflow/references/workflow-loop.md +92 -0
  203. package/skills/write-plan/SKILL.md +85 -58
  204. package/skills/write-plan/references/plan-shapes.md +132 -46
  205. package/skills/write-skill/SKILL.md +82 -51
  206. package/skills/write-skill/references/activation-boundaries.md +62 -0
  207. package/skills/write-skill/references/agent-first-instructions.md +87 -0
  208. package/skills/write-skill/references/progressive-disclosure.md +63 -0
  209. package/skills/write-skill/scripts/lib/skill-author.mjs +653 -0
  210. package/skills/write-skill/scripts/skill-author.mjs +104 -0
  211. package/skills/write-spec/SKILL.md +65 -54
  212. package/skills/write-spec/references/artifact-standards.md +60 -41
  213. package/skills/write-spec/references/decision-records.md +77 -0
  214. package/skills/write-spec/references/spec-shapes.md +119 -60
  215. package/evals/README.md +0 -32
  216. package/evals/fixtures/copy-conventions.md +0 -31
  217. package/evals/fixtures/output-router/README.md +0 -12
  218. package/evals/fixtures/output-router/failed-command-output.txt +0 -9
  219. package/evals/fixtures/output-router/large-router-manual.md +0 -63
  220. package/evals/fixtures/output-router/native-large-output.txt +0 -40
  221. package/evals/fixtures/output-router/noisy-test-output.txt +0 -30
  222. package/evals/fixtures/output-router/verification-output.txt +0 -8
  223. package/evals/fixtures/tiny-artifact-review-app/README.md +0 -5
  224. package/evals/fixtures/tiny-artifact-review-app/docs/billing-policy.md +0 -10
  225. package/evals/fixtures/tiny-artifact-review-app/docs/specs/billing-webhook-api-draft.md +0 -21
  226. package/evals/fixtures/tiny-artifact-review-app/docs/specs/failed-payment-grace-period.md +0 -24
  227. package/evals/fixtures/tiny-artifact-review-app/docs/specs/immediate-downgrade.md +0 -17
  228. package/evals/fixtures/tiny-artifact-review-app/tests/billing.test.md +0 -8
  229. package/evals/fixtures/tiny-commit-ambiguous-app/.freeflow-eval-setup.sh +0 -15
  230. package/evals/fixtures/tiny-commit-ambiguous-app/README.md +0 -3
  231. package/evals/fixtures/tiny-commit-ambiguous-app/src/billing.ts +0 -5
  232. package/evals/fixtures/tiny-commit-ambiguous-app/src/settings-page.ts +0 -1
  233. package/evals/fixtures/tiny-commit-ambiguous-app/tests/settings.test.md +0 -5
  234. package/evals/fixtures/tiny-commit-app/.freeflow-eval-setup.sh +0 -14
  235. package/evals/fixtures/tiny-commit-app/README.md +0 -3
  236. package/evals/fixtures/tiny-commit-app/docs/specs/settings-title.md +0 -5
  237. package/evals/fixtures/tiny-commit-app/src/billing.ts +0 -5
  238. package/evals/fixtures/tiny-commit-app/src/settings-page.ts +0 -1
  239. package/evals/fixtures/tiny-commit-app/tests/settings.test.md +0 -5
  240. package/evals/fixtures/tiny-commit-everything-app/.freeflow-eval-setup.sh +0 -15
  241. package/evals/fixtures/tiny-commit-everything-app/README.md +0 -3
  242. package/evals/fixtures/tiny-commit-everything-app/docs/specs/settings-title.md +0 -5
  243. package/evals/fixtures/tiny-commit-everything-app/src/billing.ts +0 -5
  244. package/evals/fixtures/tiny-commit-everything-app/src/settings-page.ts +0 -1
  245. package/evals/fixtures/tiny-commit-everything-app/tests/settings.test.md +0 -5
  246. package/evals/fixtures/tiny-commit-staged-app/.freeflow-eval-setup.sh +0 -15
  247. package/evals/fixtures/tiny-commit-staged-app/README.md +0 -3
  248. package/evals/fixtures/tiny-commit-staged-app/docs/specs/settings-title.md +0 -5
  249. package/evals/fixtures/tiny-commit-staged-app/src/billing.ts +0 -5
  250. package/evals/fixtures/tiny-commit-staged-app/src/settings-page.ts +0 -1
  251. package/evals/fixtures/tiny-commit-staged-app/tests/settings.test.md +0 -5
  252. package/evals/fixtures/tiny-commit-staged-mixed-app/.freeflow-eval-setup.sh +0 -15
  253. package/evals/fixtures/tiny-commit-staged-mixed-app/README.md +0 -3
  254. package/evals/fixtures/tiny-commit-staged-mixed-app/docs/billing-policy.md +0 -3
  255. package/evals/fixtures/tiny-commit-staged-mixed-app/docs/release-notes.md +0 -3
  256. package/evals/fixtures/tiny-commit-staged-mixed-app/src/billing.ts +0 -5
  257. package/evals/fixtures/tiny-dashboard-stale-app/README.md +0 -11
  258. package/evals/fixtures/tiny-dashboard-stale-app/src/api-client.ts +0 -13
  259. package/evals/fixtures/tiny-dashboard-stale-app/src/dashboard-data.ts +0 -19
  260. package/evals/fixtures/tiny-dashboard-stale-app/tests/dashboard-data.test.md +0 -9
  261. package/evals/fixtures/tiny-decision-destination-app/README.md +0 -6
  262. package/evals/fixtures/tiny-decision-destination-app/src/risk.ts +0 -8
  263. package/evals/fixtures/tiny-decision-destination-app/tests/risk.test.md +0 -4
  264. package/evals/fixtures/tiny-design-depth-app/README.md +0 -15
  265. package/evals/fixtures/tiny-design-depth-app/src/routes.ts +0 -25
  266. package/evals/fixtures/tiny-design-depth-app/src/sendEmail.ts +0 -3
  267. package/evals/fixtures/tiny-design-depth-app/src/sendSms.ts +0 -3
  268. package/evals/fixtures/tiny-design-depth-app/src/telemetry.ts +0 -3
  269. package/evals/fixtures/tiny-design-depth-app/tests/routes.test.md +0 -12
  270. package/evals/fixtures/tiny-eval-method-app/README.md +0 -8
  271. package/evals/fixtures/tiny-eval-method-app/evals/reports/review-pr-eval-result.md +0 -5
  272. package/evals/fixtures/tiny-eval-method-app/evals/reports/triage-question-failure.md +0 -17
  273. package/evals/fixtures/tiny-eval-method-app/evals/runs/review-pr-with-skill-output.diff +0 -11
  274. package/evals/fixtures/tiny-eval-method-app/evals/runs/review-pr-with-skill-output.md +0 -3
  275. package/evals/fixtures/tiny-eval-method-app/skills/review-pr/SKILL.md +0 -10
  276. package/evals/fixtures/tiny-eval-method-app/skills/triage-question/SKILL.md +0 -10
  277. package/evals/fixtures/tiny-execute-plan-app/README.md +0 -5
  278. package/evals/fixtures/tiny-execute-plan-app/checks/settings-and-billing-check.sh +0 -5
  279. package/evals/fixtures/tiny-execute-plan-app/docs/billing-policy.md +0 -10
  280. package/evals/fixtures/tiny-execute-plan-app/docs/plans/immediate-downgrade-plan.md +0 -11
  281. package/evals/fixtures/tiny-execute-plan-app/docs/plans/settings-title-plan.md +0 -12
  282. package/evals/fixtures/tiny-execute-plan-app/docs/plans/settings-title-with-bad-check.md +0 -15
  283. package/evals/fixtures/tiny-execute-plan-app/docs/plans/unverified-billing-plan.md +0 -9
  284. package/evals/fixtures/tiny-execute-plan-app/docs/specs/failed-payment-grace-period.md +0 -9
  285. package/evals/fixtures/tiny-execute-plan-app/docs/specs/settings-title.md +0 -9
  286. package/evals/fixtures/tiny-execute-plan-app/src/billing.ts +0 -7
  287. package/evals/fixtures/tiny-execute-plan-app/src/settings-page.ts +0 -1
  288. package/evals/fixtures/tiny-execute-plan-app/tests/billing.test.md +0 -7
  289. package/evals/fixtures/tiny-execute-plan-app/tests/settings.test.md +0 -5
  290. package/evals/fixtures/tiny-execute-review-loop-app/README.md +0 -5
  291. package/evals/fixtures/tiny-execute-review-loop-app/docs/billing-policy.md +0 -9
  292. package/evals/fixtures/tiny-execute-review-loop-app/docs/plans/settings-title-plan.md +0 -12
  293. package/evals/fixtures/tiny-execute-review-loop-app/docs/review/previous-agent-summary.md +0 -15
  294. package/evals/fixtures/tiny-execute-review-loop-app/docs/review/review-pass-1-non-pass.md +0 -11
  295. package/evals/fixtures/tiny-execute-review-loop-app/docs/specs/settings-title.md +0 -9
  296. package/evals/fixtures/tiny-execute-review-loop-app/src/billing.ts +0 -7
  297. package/evals/fixtures/tiny-execute-review-loop-app/src/settings-page.ts +0 -1
  298. package/evals/fixtures/tiny-execute-review-loop-app/tests/billing.test.md +0 -7
  299. package/evals/fixtures/tiny-execute-review-loop-app/tests/settings.test.md +0 -5
  300. package/evals/fixtures/tiny-flaky-session-app/README.md +0 -10
  301. package/evals/fixtures/tiny-flaky-session-app/src/session-timeout.ts +0 -13
  302. package/evals/fixtures/tiny-flaky-session-app/tests/session-timeout.test.md +0 -8
  303. package/evals/fixtures/tiny-handoff-app/README.md +0 -5
  304. package/evals/fixtures/tiny-handoff-app/docs/billing-policy.md +0 -10
  305. package/evals/fixtures/tiny-handoff-app/docs/handoffs/old-agent-handoff.md +0 -8
  306. package/evals/fixtures/tiny-handoff-app/docs/plans/billing-retry-plan.md +0 -11
  307. package/evals/fixtures/tiny-handoff-app/src/billing.ts +0 -7
  308. package/evals/fixtures/tiny-handoff-report-app/README.md +0 -3
  309. package/evals/fixtures/tiny-handoff-report-app/evals/runs/handoff-3/hof-003/with-skill-output.diff +0 -1
  310. package/evals/fixtures/tiny-handoff-report-app/evals/runs/handoff-3/hof-003/with-skill-output.md +0 -1
  311. package/evals/fixtures/tiny-handoff-report-app/evals/scores/hof-003-score.txt +0 -4
  312. package/evals/fixtures/tiny-plan-app/README.md +0 -5
  313. package/evals/fixtures/tiny-plan-app/docs/billing-policy.md +0 -10
  314. package/evals/fixtures/tiny-plan-app/docs/specs/failed-payment-grace-period.md +0 -25
  315. package/evals/fixtures/tiny-plan-app/src/billing.ts +0 -17
  316. package/evals/fixtures/tiny-plan-app/src/settings-page.ts +0 -1
  317. package/evals/fixtures/tiny-plan-app/tests/billing.test.md +0 -8
  318. package/evals/fixtures/tiny-plan-app/tests/settings.test.md +0 -5
  319. package/evals/fixtures/tiny-plan-strict-api-app/README.md +0 -3
  320. package/evals/fixtures/tiny-plan-strict-api-app/docs/billing-policy.md +0 -5
  321. package/evals/fixtures/tiny-plan-strict-api-app/docs/specs/billing-webhook-api.md +0 -25
  322. package/evals/fixtures/tiny-plan-strict-api-app/src/billing.ts +0 -5
  323. package/evals/fixtures/tiny-plan-strict-api-app/src/webhooks.ts +0 -3
  324. package/evals/fixtures/tiny-plan-strict-api-app/tests/billing-webhook.test.md +0 -8
  325. package/evals/fixtures/tiny-post-setup-invalid-config-app/.freeflow/config.json +0 -3
  326. package/evals/fixtures/tiny-post-setup-invalid-config-app/AGENTS.md +0 -15
  327. package/evals/fixtures/tiny-post-setup-invalid-config-app/README.md +0 -16
  328. package/evals/fixtures/tiny-post-setup-invalid-config-app/docs/auth-review.md +0 -15
  329. package/evals/fixtures/tiny-post-setup-invalid-config-app/docs/billing-policy.md +0 -10
  330. package/evals/fixtures/tiny-post-setup-invalid-config-app/docs/copy-conventions.md +0 -15
  331. package/evals/fixtures/tiny-post-setup-invalid-config-app/src/auth-middleware.ts +0 -12
  332. package/evals/fixtures/tiny-post-setup-invalid-config-app/src/billing.ts +0 -20
  333. package/evals/fixtures/tiny-post-setup-invalid-config-app/src/login-copy.ts +0 -1
  334. package/evals/fixtures/tiny-post-setup-invalid-config-app/src/settings-page.ts +0 -1
  335. package/evals/fixtures/tiny-post-setup-invalid-config-app/tests/auth-middleware.test.md +0 -8
  336. package/evals/fixtures/tiny-post-setup-invalid-config-app/tests/billing.test.md +0 -8
  337. package/evals/fixtures/tiny-post-setup-invalid-config-app/tests/copy.test.md +0 -7
  338. package/evals/fixtures/tiny-post-setup-missing-config-app/AGENTS.md +0 -15
  339. package/evals/fixtures/tiny-post-setup-missing-config-app/README.md +0 -16
  340. package/evals/fixtures/tiny-post-setup-missing-config-app/docs/auth-review.md +0 -15
  341. package/evals/fixtures/tiny-post-setup-missing-config-app/docs/billing-policy.md +0 -10
  342. package/evals/fixtures/tiny-post-setup-missing-config-app/docs/copy-conventions.md +0 -15
  343. package/evals/fixtures/tiny-post-setup-missing-config-app/src/auth-middleware.ts +0 -12
  344. package/evals/fixtures/tiny-post-setup-missing-config-app/src/billing.ts +0 -20
  345. package/evals/fixtures/tiny-post-setup-missing-config-app/src/login-copy.ts +0 -1
  346. package/evals/fixtures/tiny-post-setup-missing-config-app/src/settings-page.ts +0 -1
  347. package/evals/fixtures/tiny-post-setup-missing-config-app/tests/auth-middleware.test.md +0 -8
  348. package/evals/fixtures/tiny-post-setup-missing-config-app/tests/billing.test.md +0 -8
  349. package/evals/fixtures/tiny-post-setup-missing-config-app/tests/copy.test.md +0 -7
  350. package/evals/fixtures/tiny-post-setup-source-conflict-app/.freeflow/config.json +0 -3
  351. package/evals/fixtures/tiny-post-setup-source-conflict-app/AGENTS.md +0 -15
  352. package/evals/fixtures/tiny-post-setup-source-conflict-app/README.md +0 -16
  353. package/evals/fixtures/tiny-post-setup-source-conflict-app/docs/auth-review.md +0 -15
  354. package/evals/fixtures/tiny-post-setup-source-conflict-app/docs/billing-policy.md +0 -10
  355. package/evals/fixtures/tiny-post-setup-source-conflict-app/docs/copy-conventions.md +0 -15
  356. package/evals/fixtures/tiny-post-setup-source-conflict-app/src/auth-middleware.ts +0 -12
  357. package/evals/fixtures/tiny-post-setup-source-conflict-app/src/billing.ts +0 -20
  358. package/evals/fixtures/tiny-post-setup-source-conflict-app/src/login-copy.ts +0 -1
  359. package/evals/fixtures/tiny-post-setup-source-conflict-app/src/settings-page.ts +0 -1
  360. package/evals/fixtures/tiny-post-setup-source-conflict-app/tests/auth-middleware.test.md +0 -8
  361. package/evals/fixtures/tiny-post-setup-source-conflict-app/tests/billing.test.md +0 -8
  362. package/evals/fixtures/tiny-post-setup-source-conflict-app/tests/copy.test.md +0 -7
  363. package/evals/fixtures/tiny-report-performance-app/README.md +0 -11
  364. package/evals/fixtures/tiny-report-performance-app/docs/performance.md +0 -10
  365. package/evals/fixtures/tiny-report-performance-app/src/report-summary.ts +0 -29
  366. package/evals/fixtures/tiny-report-performance-app/tests/report-performance.test.md +0 -8
  367. package/evals/fixtures/tiny-review-request-app/README.md +0 -3
  368. package/evals/fixtures/tiny-review-request-app/docs/billing-policy.md +0 -5
  369. package/evals/fixtures/tiny-review-request-app/docs/plans/billing-webhook-api.md +0 -19
  370. package/evals/fixtures/tiny-review-request-app/docs/review/previous-agent-summary.md +0 -20
  371. package/evals/fixtures/tiny-review-request-app/docs/specs/billing-webhook-api.md +0 -25
  372. package/evals/fixtures/tiny-review-request-app/src/billing.ts +0 -11
  373. package/evals/fixtures/tiny-review-request-app/src/webhooks.ts +0 -19
  374. package/evals/fixtures/tiny-review-request-app/tests/billing-webhook.test.md +0 -8
  375. package/evals/fixtures/tiny-review-work-app/README.md +0 -5
  376. package/evals/fixtures/tiny-review-work-app/docs/billing-policy.md +0 -9
  377. package/evals/fixtures/tiny-review-work-app/docs/plans/settings-title-plan.md +0 -12
  378. package/evals/fixtures/tiny-review-work-app/docs/review/previous-agent-summary.md +0 -15
  379. package/evals/fixtures/tiny-review-work-app/docs/specs/settings-title.md +0 -9
  380. package/evals/fixtures/tiny-review-work-app/src/billing.ts +0 -7
  381. package/evals/fixtures/tiny-review-work-app/src/settings-page.ts +0 -1
  382. package/evals/fixtures/tiny-review-work-app/tests/billing.test.md +0 -7
  383. package/evals/fixtures/tiny-review-work-app/tests/settings.test.md +0 -5
  384. package/evals/fixtures/tiny-saas-app/README.md +0 -16
  385. package/evals/fixtures/tiny-saas-app/docs/auth-review.md +0 -15
  386. package/evals/fixtures/tiny-saas-app/docs/billing-policy.md +0 -10
  387. package/evals/fixtures/tiny-saas-app/docs/copy-conventions.md +0 -15
  388. package/evals/fixtures/tiny-saas-app/docs/specs/settings-title.md +0 -13
  389. package/evals/fixtures/tiny-saas-app/src/auth-middleware.ts +0 -12
  390. package/evals/fixtures/tiny-saas-app/src/billing.ts +0 -20
  391. package/evals/fixtures/tiny-saas-app/src/login-copy.ts +0 -1
  392. package/evals/fixtures/tiny-saas-app/src/settings-page.ts +0 -1
  393. package/evals/fixtures/tiny-saas-app/tests/auth-middleware.test.md +0 -8
  394. package/evals/fixtures/tiny-saas-app/tests/billing.test.md +0 -8
  395. package/evals/fixtures/tiny-saas-app/tests/copy.test.md +0 -7
  396. package/evals/fixtures/tiny-setup-agents-app/AGENTS.md +0 -6
  397. package/evals/fixtures/tiny-setup-both-app/AGENTS.md +0 -5
  398. package/evals/fixtures/tiny-setup-both-app/CLAUDE.md +0 -5
  399. package/evals/fixtures/tiny-setup-claude-app/CLAUDE.md +0 -6
  400. package/evals/fixtures/tiny-setup-codex-rules-app/.codex/rules/shell.rules +0 -5
  401. package/evals/fixtures/tiny-setup-codex-rules-app/AGENTS.md +0 -6
  402. package/evals/fixtures/tiny-setup-conflict-app/AGENTS.md +0 -6
  403. package/evals/fixtures/tiny-setup-existing-block-app/AGENTS.md +0 -14
  404. package/evals/fixtures/tiny-setup-four-rules-app/CLAUDE.md +0 -6
  405. package/evals/fixtures/tiny-skill-dev-app/README.md +0 -10
  406. package/evals/fixtures/tiny-skill-dev-app/evals/prompts/review-pr-001.txt +0 -8
  407. package/evals/fixtures/tiny-skill-dev-app/evals/reports/review-pr-failure.md +0 -17
  408. package/evals/fixtures/tiny-skill-dev-app/skills/review-pr/SKILL.md +0 -13
  409. package/evals/fixtures/tiny-team-app/README.md +0 -5
  410. package/evals/fixtures/tiny-team-app/docs/product.md +0 -6
  411. package/evals/fixtures/tiny-team-app/src/teams.ts +0 -9
  412. package/evals/fixtures/tiny-team-app/src/users.ts +0 -5
  413. package/evals/fixtures/tiny-team-app/tests/teams.test.md +0 -7
  414. package/evals/fixtures/tiny-verify-app/README.md +0 -5
  415. package/evals/fixtures/tiny-verify-app/src/settings-nav.ts +0 -1
  416. package/evals/fixtures/tiny-verify-app/src/settings-page.ts +0 -1
  417. package/evals/fixtures/tiny-verify-app/tests/settings.test.md +0 -7
  418. package/evals/prompts/aon-001.txt +0 -2
  419. package/evals/prompts/byp-001.txt +0 -2
  420. package/evals/prompts/byp-002.txt +0 -2
  421. package/evals/prompts/cap-001.txt +0 -3
  422. package/evals/prompts/cap-002.txt +0 -3
  423. package/evals/prompts/cmd-001.txt +0 -3
  424. package/evals/prompts/cmd-002.txt +0 -3
  425. package/evals/prompts/cmd-003.txt +0 -6
  426. package/evals/prompts/cmd-004.txt +0 -5
  427. package/evals/prompts/cmd-005.txt +0 -5
  428. package/evals/prompts/cmd-006.txt +0 -5
  429. package/evals/prompts/cmd-007.txt +0 -5
  430. package/evals/prompts/cmd-008.txt +0 -5
  431. package/evals/prompts/cmd-009.txt +0 -8
  432. package/evals/prompts/cmd-010.txt +0 -5
  433. package/evals/prompts/cmd-011.txt +0 -5
  434. package/evals/prompts/cmd-012.txt +0 -5
  435. package/evals/prompts/cmd-013.txt +0 -5
  436. package/evals/prompts/cmd-014.txt +0 -7
  437. package/evals/prompts/cmd-015.txt +0 -7
  438. package/evals/prompts/cmd-016.txt +0 -5
  439. package/evals/prompts/cmt-001.txt +0 -1
  440. package/evals/prompts/cmt-002.txt +0 -1
  441. package/evals/prompts/cmt-003.txt +0 -1
  442. package/evals/prompts/cmt-004.txt +0 -1
  443. package/evals/prompts/cmt-005.txt +0 -1
  444. package/evals/prompts/dfd-001.txt +0 -3
  445. package/evals/prompts/dia-001.txt +0 -3
  446. package/evals/prompts/dia-002.txt +0 -3
  447. package/evals/prompts/dia-003.txt +0 -3
  448. package/evals/prompts/dis-001.txt +0 -5
  449. package/evals/prompts/dis-002.txt +0 -5
  450. package/evals/prompts/esk-001.txt +0 -5
  451. package/evals/prompts/esk-002.txt +0 -5
  452. package/evals/prompts/esk-003.txt +0 -5
  453. package/evals/prompts/grc-001.txt +0 -3
  454. package/evals/prompts/hof-001.txt +0 -3
  455. package/evals/prompts/hof-002.txt +0 -1
  456. package/evals/prompts/hof-003.txt +0 -1
  457. package/evals/prompts/hof-004.txt +0 -1
  458. package/evals/prompts/hof-005.txt +0 -1
  459. package/evals/prompts/ivg-001.txt +0 -1
  460. package/evals/prompts/ivg-002.txt +0 -11
  461. package/evals/prompts/ivg-003.txt +0 -1
  462. package/evals/prompts/ivg-004.txt +0 -1
  463. package/evals/prompts/mode-001.txt +0 -3
  464. package/evals/prompts/mode-002.txt +0 -1
  465. package/evals/prompts/mode-003.txt +0 -3
  466. package/evals/prompts/mode-004.txt +0 -3
  467. package/evals/prompts/mode-005.txt +0 -3
  468. package/evals/prompts/mode-006.txt +0 -3
  469. package/evals/prompts/mode-007.txt +0 -3
  470. package/evals/prompts/otr-001.txt +0 -3
  471. package/evals/prompts/otr-002.txt +0 -3
  472. package/evals/prompts/rar-001.txt +0 -5
  473. package/evals/prompts/rar-002.txt +0 -3
  474. package/evals/prompts/rar-003.txt +0 -6
  475. package/evals/prompts/rar-004.txt +0 -15
  476. package/evals/prompts/rar-005.txt +0 -10
  477. package/evals/prompts/rbr-001.txt +0 -3
  478. package/evals/prompts/rbr-002.txt +0 -3
  479. package/evals/prompts/rbr-003.txt +0 -7
  480. package/evals/prompts/rev-001.txt +0 -3
  481. package/evals/prompts/rev-002.txt +0 -5
  482. package/evals/prompts/rev-003.txt +0 -6
  483. package/evals/prompts/rev-004.txt +0 -1
  484. package/evals/prompts/rev-005.txt +0 -15
  485. package/evals/prompts/rev-006.txt +0 -5
  486. package/evals/prompts/stp-001.txt +0 -1
  487. package/evals/prompts/stp-002.txt +0 -1
  488. package/evals/prompts/stp-003.txt +0 -1
  489. package/evals/prompts/stp-004.txt +0 -1
  490. package/evals/prompts/stp-005.txt +0 -1
  491. package/evals/prompts/stp-006.txt +0 -1
  492. package/evals/prompts/stp-007.txt +0 -1
  493. package/evals/prompts/stp-008.txt +0 -1
  494. package/evals/prompts/stp-009.txt +0 -1
  495. package/evals/prompts/stp-010.txt +0 -1
  496. package/evals/prompts/stp-011.txt +0 -1
  497. package/evals/prompts/vfy-003.txt +0 -1
  498. package/evals/prompts/wpl-001.txt +0 -3
  499. package/evals/prompts/wpl-002.txt +0 -5
  500. package/evals/prompts/wpl-003.txt +0 -3
  501. package/evals/prompts/wpl-004.txt +0 -5
  502. package/evals/prompts/wpl-005.txt +0 -1
  503. package/evals/prompts/wrc-001.txt +0 -10
  504. package/evals/prompts/wrc-002.txt +0 -3
  505. package/evals/prompts/wsk-001.txt +0 -6
  506. package/evals/prompts/wsp-001.txt +0 -5
  507. package/evals/prompts/wsp-002.txt +0 -15
  508. package/evals/prompts/wsp-003.txt +0 -3
  509. package/evals/prompts/wsp-004.txt +0 -15
  510. package/evals/prompts/wsp-005.txt +0 -5
  511. package/evals/prompts/wsp-006.txt +0 -12
  512. package/evals/prompts/wsp-007.txt +0 -9
  513. package/evals/prompts/wsp-008.txt +0 -13
  514. package/evals/prompts/xpl-001.txt +0 -1
  515. package/evals/prompts/xpl-002.txt +0 -3
  516. package/evals/prompts/xpl-003.txt +0 -3
  517. package/evals/prompts/xpl-004.txt +0 -3
  518. package/evals/prompts/xpl-005.txt +0 -5
  519. package/evals/prompts/xpl-006.txt +0 -3
  520. package/evals/registries/adversarial-evals.json +0 -39
  521. package/evals/registries/fixture-evals.json +0 -2513
  522. package/evals/registries/handoff-evals.json +0 -74
  523. package/evals/registries/legacy-evals.json +0 -147
  524. package/evals/registries/skill-evidence.json +0 -193
  525. package/evals/registries/verify-work-evals.json +0 -46
  526. package/evals/reports/acceptance/v0.1-acceptance-report.md +0 -130
  527. package/evals/reports/by-command-surface/command-surface-1-report.md +0 -45
  528. package/evals/reports/by-command-surface/command-surface-10-report.md +0 -76
  529. package/evals/reports/by-command-surface/command-surface-11-report.md +0 -77
  530. package/evals/reports/by-command-surface/command-surface-12-report.md +0 -91
  531. package/evals/reports/by-command-surface/command-surface-13-report.md +0 -64
  532. package/evals/reports/by-command-surface/command-surface-14-report.md +0 -66
  533. package/evals/reports/by-command-surface/command-surface-15-report.md +0 -124
  534. package/evals/reports/by-command-surface/command-surface-16-report.md +0 -39
  535. package/evals/reports/by-command-surface/command-surface-2-report.md +0 -80
  536. package/evals/reports/by-command-surface/command-surface-3-report.md +0 -86
  537. package/evals/reports/by-command-surface/command-surface-4-report.md +0 -76
  538. package/evals/reports/by-command-surface/command-surface-5-report.md +0 -80
  539. package/evals/reports/by-command-surface/command-surface-6-report.md +0 -74
  540. package/evals/reports/by-command-surface/command-surface-7-report.md +0 -84
  541. package/evals/reports/by-command-surface/command-surface-8-report.md +0 -79
  542. package/evals/reports/by-command-surface/command-surface-9-report.md +0 -79
  543. package/evals/reports/by-command-surface/command-surface-matrix.md +0 -91
  544. package/evals/reports/by-skill/bypass-1-report.md +0 -124
  545. package/evals/reports/by-skill/capture-decisions-1-report.md +0 -99
  546. package/evals/reports/by-skill/capture-decisions-2-report.md +0 -102
  547. package/evals/reports/by-skill/commit-work-1-report.md +0 -165
  548. package/evals/reports/by-skill/commit-work-2-report.md +0 -109
  549. package/evals/reports/by-skill/design-for-depth-1-report.md +0 -95
  550. package/evals/reports/by-skill/diagnose-failure-1-report.md +0 -91
  551. package/evals/reports/by-skill/diagnose-failure-2-report.md +0 -94
  552. package/evals/reports/by-skill/discover-1-report.md +0 -118
  553. package/evals/reports/by-skill/evaluate-skill-2-report.md +0 -71
  554. package/evals/reports/by-skill/execute-plan-1-report.md +0 -103
  555. package/evals/reports/by-skill/execute-plan-2-report.md +0 -112
  556. package/evals/reports/by-skill/execute-plan-3-report.md +0 -87
  557. package/evals/reports/by-skill/grill-context-1-report.md +0 -103
  558. package/evals/reports/by-skill/handoff-1-report.md +0 -123
  559. package/evals/reports/by-skill/handoff-2-report.md +0 -105
  560. package/evals/reports/by-skill/handoff-3-report.md +0 -100
  561. package/evals/reports/by-skill/handoff-7-report.md +0 -77
  562. package/evals/reports/by-skill/interview-gate-1-report.md +0 -63
  563. package/evals/reports/by-skill/interview-gate-2-report.md +0 -105
  564. package/evals/reports/by-skill/mode-contract-1-report.md +0 -74
  565. package/evals/reports/by-skill/mode-contract-2-report.md +0 -87
  566. package/evals/reports/by-skill/mode-contract-3-report.md +0 -65
  567. package/evals/reports/by-skill/mode-contract-4-report.md +0 -71
  568. package/evals/reports/by-skill/mode-contract-5-report.md +0 -70
  569. package/evals/reports/by-skill/output-router-1-report.md +0 -76
  570. package/evals/reports/by-skill/output-router-2-report.md +0 -65
  571. package/evals/reports/by-skill/research-1-report.md +0 -144
  572. package/evals/reports/by-skill/research-brief-1-report.md +0 -94
  573. package/evals/reports/by-skill/research-brief-2-report.md +0 -75
  574. package/evals/reports/by-skill/review-artifact-1-report.md +0 -91
  575. package/evals/reports/by-skill/review-artifact-2-report.md +0 -79
  576. package/evals/reports/by-skill/review-artifact-3-report.md +0 -120
  577. package/evals/reports/by-skill/review-artifact-4-report.md +0 -89
  578. package/evals/reports/by-skill/review-artifact-5-report.md +0 -66
  579. package/evals/reports/by-skill/review-work-1-report.md +0 -85
  580. package/evals/reports/by-skill/review-work-2-report.md +0 -87
  581. package/evals/reports/by-skill/review-work-3-report.md +0 -104
  582. package/evals/reports/by-skill/review-work-4-report.md +0 -108
  583. package/evals/reports/by-skill/review-work-5-report.md +0 -73
  584. package/evals/reports/by-skill/review-work-6-report.md +0 -66
  585. package/evals/reports/by-skill/setup-freeflow-1-report.md +0 -199
  586. package/evals/reports/by-skill/setup-freeflow-2-report.md +0 -105
  587. package/evals/reports/by-skill/setup-freeflow-3-report.md +0 -105
  588. package/evals/reports/by-skill/setup-freeflow-4-report.md +0 -88
  589. package/evals/reports/by-skill/setup-freeflow-5-report.md +0 -115
  590. package/evals/reports/by-skill/skill-authoring-1-report.md +0 -81
  591. package/evals/reports/by-skill/verify-work-1-report.md +0 -111
  592. package/evals/reports/by-skill/verify-work-2-report.md +0 -120
  593. package/evals/reports/by-skill/workflow-1-report.md +0 -65
  594. package/evals/reports/by-skill/write-plan-1-report.md +0 -123
  595. package/evals/reports/by-skill/write-plan-2-report.md +0 -98
  596. package/evals/reports/by-skill/write-plan-3-report.md +0 -110
  597. package/evals/reports/by-skill/write-spec-1-report.md +0 -88
  598. package/evals/reports/by-skill/write-spec-2-report.md +0 -89
  599. package/evals/reports/by-skill/write-spec-3-report.md +0 -90
  600. package/evals/reports/by-skill/write-spec-4-report.md +0 -167
  601. package/evals/reports/harness/claude-harness-1-report.md +0 -103
  602. package/evals/reports/harness/eval-harness-1-report.md +0 -91
  603. package/evals/reports/iterations/iteration-1-report.md +0 -71
  604. package/evals/reports/iterations/iteration-2-report.md +0 -78
  605. package/evals/reports/iterations/iteration-3-report.md +0 -118
  606. package/evals/reports/iterations/iteration-4-report.md +0 -131
  607. package/evals/reports/iterations/iteration-5-report.md +0 -149
  608. package/evals/reports/iterations/iteration-6-report.md +0 -136
  609. package/evals/reports/runtime/always-on-runtime-1-report.md +0 -107
  610. package/evals/reports/runtime/context-mode-normalized-benchmark-1-report.md +0 -52
  611. package/evals/reports/runtime/context-mode-real-deep-baseline-1-report.md +0 -410
  612. package/evals/reports/runtime/context-mode-real-deep-final-slice-11-report.md +0 -203
  613. package/evals/reports/runtime/context-mode-real-deep-final-slice-11-review.md +0 -51
  614. package/evals/reports/runtime/context-saving-native-tools-baseline-1-report.md +0 -99
  615. package/evals/reports/runtime/eryx-python-compatibility-reprobe-1-report.md +0 -166
  616. package/evals/reports/runtime/eryx-python-proof-spike-1-report.md +0 -96
  617. package/evals/reports/runtime/eryx-python-proof-spike-2-report.md +0 -151
  618. package/evals/reports/runtime/eryx-python-script-derive-execution-1-report.md +0 -233
  619. package/evals/reports/runtime/jq-script-derive-execution-1-report.md +0 -215
  620. package/evals/reports/runtime/jq-wasm-proof-spike-1-report.md +0 -67
  621. package/evals/reports/runtime/output-router-benchmark-1-report.md +0 -81
  622. package/evals/reports/runtime/output-router-capture-derive-provider-eval-1-report.md +0 -35
  623. package/evals/reports/runtime/output-router-codex-large-index-sqlite-adhoc-report.md +0 -150
  624. package/evals/reports/runtime/output-router-codex-qa-benchmark-1-report.md +0 -46
  625. package/evals/reports/runtime/output-router-command-benchmark-1-report.md +0 -62
  626. package/evals/reports/runtime/output-router-index-benchmark-1-report.md +0 -64
  627. package/evals/reports/runtime/output-router-regression-1-report.md +0 -81
  628. package/evals/reports/runtime/output-router-transform-eval-1-report.md +0 -28
  629. package/evals/reports/runtime/pi-observed-routing-eval-1-report.md +0 -44
  630. package/evals/reports/runtime/quickjs-script-derive-execution-1-report.md +0 -159
  631. package/evals/reports/runtime/quickjs-wasi-proof-spike-1-report.md +0 -55
  632. package/evals/reports/runtime/render-format-row-protocol-1-report.md +0 -58
  633. package/evals/reports/runtime/script-sandbox-adapter-selection-review-1-report.md +0 -84
  634. package/evals/reports/runtime/script-sandbox-probe-resource-hardening-1-report.md +0 -51
  635. package/evals/reports/runtime/storage-policy-benchmark-1-report.md +0 -176
  636. package/evals/reports/runtime/vault-index-storage-spike-1-report.md +0 -39
  637. package/evals/reports/runtime/workflow-context-hook-1-report.md +0 -82
  638. package/evals/runbooks/adversarial-eval-runbook.md +0 -28
  639. package/evals/runbooks/fixture-eval-runbook.md +0 -137
  640. package/evals/runbooks/handoff-eval-runbook.md +0 -22
  641. package/evals/runbooks/verify-work-eval-runbook.md +0 -27
  642. package/evals/scripts/audit-command-surface.sh +0 -160
  643. package/evals/scripts/check-activation-contract.sh +0 -121
  644. package/evals/scripts/check-runtime-context-hook.sh +0 -183
  645. package/evals/scripts/grade-fixture-eval.sh +0 -446
  646. package/evals/scripts/run-claude-fixture-eval.sh +0 -26
  647. package/evals/scripts/run-codex-fixture-eval.sh +0 -26
  648. package/evals/scripts/run-eryx-python-proof-spike.js +0 -559
  649. package/evals/scripts/run-fixture-eval-by-id.sh +0 -23
  650. package/evals/scripts/run-fixture-eval.sh +0 -464
  651. package/evals/scripts/run-jq-wasm-proof-spike.js +0 -299
  652. package/evals/scripts/run-output-router-transform-eval.js +0 -115
  653. package/evals/scripts/run-pi-observed-routing-eval.js +0 -478
  654. package/evals/scripts/run-quickjs-wasi-proof-spike.js +0 -339
  655. package/evals/scripts/skill-evidence.sh +0 -316
  656. package/evals/scripts/validate-release-metadata.sh +0 -486
  657. package/evals/suites/v0.1-acceptance-suite.md +0 -131
  658. package/pi-extension/dist/host-producer-identification.js +0 -186
  659. package/pi-extension/dist/mcp-config.js +0 -30
  660. package/pi-extension/dist/native-safety-net.js +0 -209
  661. package/pi-extension/dist/observed-tool-routing.js +0 -114
  662. package/pi-extension/dist/renderers.js +0 -835
  663. package/pi-extension/dist/router-tools.js +0 -438
  664. package/pi-extension/dist/runtime-context.js +0 -288
  665. package/pi-extension/dist/schemas.js +0 -254
  666. package/pi-extension/dist/status.js +0 -449
  667. package/pi-extension/dist/utils.js +0 -467
  668. package/pi-extension/src/runtime-context.ts +0 -347
  669. package/pi-extension/src/status.ts +0 -505
  670. package/plugin-docs/README.md +0 -40
  671. package/plugin-docs/adr/0001-three-modes.md +0 -27
  672. package/plugin-docs/adr/0002-evals-before-hooks.md +0 -17
  673. package/plugin-docs/adr/0003-release-boundary.md +0 -21
  674. package/plugin-docs/adr/0004-discover-replaces-shallow-discovery-skills.md +0 -26
  675. package/plugin-docs/adr/README.md +0 -10
  676. package/plugin-docs/architecture.md +0 -89
  677. package/plugin-docs/output-router.md +0 -396
  678. package/plugin-docs/release-evidence.md +0 -77
  679. package/plugin-docs/skills.md +0 -44
  680. package/plugin-docs/workflow.md +0 -57
  681. package/skills/diagnose-failure/references/feedback-loop-catalog.md +0 -25
  682. package/skills/discover/ARTIFACT-DESTINATIONS.md +0 -58
  683. package/skills/discover/CHECKPOINTS.md +0 -74
  684. package/skills/discover/SKILL.md +0 -173
  685. package/skills/evaluate-skill/references/eval-patterns.md +0 -41
  686. package/skills/evaluate-skill/references/grading-priority.md +0 -33
  687. package/skills/execute-plan/SKILL.md +0 -133
  688. package/skills/execute-plan/references/execution-map.md +0 -122
  689. package/skills/interview-gate/SKILL.md +0 -90
  690. package/skills/setup-freeflow/references/output-router-setup.md +0 -102
  691. package/skills/workflow/references/workflow-map.md +0 -104
  692. /package/pi-extension/src/{mcp-config.ts → integrations/mcp-config.ts} +0 -0
@@ -17,420 +17,449 @@ const ERYX_CHILD_MODE_ARG = "__freeflow_eryx_child__";
17
17
  const ERYX_CHILD_TIMEOUT_FLOOR_MS = 30_000;
18
18
  export const ERYX_ROOT_ENV = "FREEFLOW_ERYX_ROOT";
19
19
  const PREVIEW2_IMPORTS = new Map([
20
- ["@bytecodealliance/preview2-shim/cli", "../../@bytecodealliance/preview2-shim/lib/browser/cli.js"],
21
- ["@bytecodealliance/preview2-shim/clocks", "../../@bytecodealliance/preview2-shim/lib/browser/clocks.js"],
22
- ["@bytecodealliance/preview2-shim/filesystem", "../../@bytecodealliance/preview2-shim/lib/browser/filesystem.js"],
23
- ["@bytecodealliance/preview2-shim/io", "../../@bytecodealliance/preview2-shim/lib/browser/io.js"],
24
- ["@bytecodealliance/preview2-shim/random", "../../@bytecodealliance/preview2-shim/lib/browser/random.js"],
20
+ ["@bytecodealliance/preview2-shim/cli", "../../@bytecodealliance/preview2-shim/lib/browser/cli.js"],
21
+ ["@bytecodealliance/preview2-shim/clocks", "../../@bytecodealliance/preview2-shim/lib/browser/clocks.js"],
22
+ ["@bytecodealliance/preview2-shim/filesystem", "../../@bytecodealliance/preview2-shim/lib/browser/filesystem.js"],
23
+ ["@bytecodealliance/preview2-shim/io", "../../@bytecodealliance/preview2-shim/lib/browser/io.js"],
24
+ ["@bytecodealliance/preview2-shim/random", "../../@bytecodealliance/preview2-shim/lib/browser/random.js"],
25
25
  ]);
26
26
  const eryxProbeCache = new Map();
27
27
  export async function discoverEryxPythonSandboxAdaptersFromEnv(env = process.env) {
28
- const candidate = await resolveScriptTransformAdapterRoot("python", env);
29
- if (!candidate) {
30
- return [];
31
- }
32
- try {
33
- return [await createEryxPythonSandboxAdapter({ packageRoot: candidate.packageRoot })];
34
- }
35
- catch (error) {
36
- return [unavailableEryxAdapter(`eryx-python adapter could not load from ${candidate.source === "env" ? candidate.envVar : "global adapter cache"}: ${errorMessage(error)}`)];
37
- }
28
+ const candidate = await resolveScriptTransformAdapterRoot("python", env);
29
+ if (!candidate) {
30
+ return [];
31
+ }
32
+ try {
33
+ return [await createEryxPythonSandboxAdapter({ packageRoot: candidate.packageRoot })];
34
+ } catch (error) {
35
+ return [
36
+ unavailableEryxAdapter(
37
+ `eryx-python adapter could not load from ${candidate.source === "env" ? candidate.envVar : "global adapter cache"}: ${errorMessage(error)}`,
38
+ ),
39
+ ];
40
+ }
38
41
  }
39
42
  export async function createEryxPythonSandboxAdapter(options) {
40
- const runtime = await loadEryxRuntime(options.packageRoot);
41
- return {
42
- id: options.id ?? "eryx-python",
43
- version: options.version ?? runtime.packageVersion,
44
- languages: ["python"],
45
- async probe(language, config) {
46
- if (language !== "python") {
47
- return {
48
- status: "unavailable",
49
- reason: `eryx-python supports python, not ${language}.`,
50
- passedProofs: [],
51
- failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
52
- runtime: runtimeInfo(runtime),
53
- };
54
- }
55
- return probeEryxRuntime(runtime, config);
56
- },
57
- async execute(request) {
58
- if (request.language !== "python") {
59
- return {
60
- status: "policy_violation",
61
- stdout: "",
62
- stderr: "",
63
- outputFiles: [],
64
- exitCode: null,
65
- reason: `eryx-python supports python, not ${request.language}.`,
66
- };
67
- }
68
- if (request.network !== "off") {
69
- return {
70
- status: "policy_violation",
71
- stdout: "",
72
- stderr: "",
73
- outputFiles: [],
74
- exitCode: null,
75
- reason: "eryx-python adapter only supports network=off.",
76
- };
77
- }
78
- if (!runtime.jspiAvailable) {
79
- return executeEryxInJspiChild(runtime, request);
80
- }
81
- const inputs = {};
82
- for (const source of request.sources) {
83
- inputs[source.alias] = await readFile(source.path, "utf8");
84
- }
85
- const run = await runEryx(runtime, {
86
- code: pythonPrelude(inputs) + request.code,
87
- timeoutMs: request.limits.timeoutMs,
88
- outputBytes: request.limits.maxOutputBytes,
89
- inputs,
90
- });
91
- return eryxRunToExecutionResult(run);
92
- },
93
- };
43
+ const runtime = await loadEryxRuntime(options.packageRoot);
44
+ return {
45
+ id: options.id ?? "eryx-python",
46
+ version: options.version ?? runtime.packageVersion,
47
+ languages: ["python"],
48
+ async probe(language, config) {
49
+ if (language !== "python") {
50
+ return {
51
+ status: "unavailable",
52
+ reason: `eryx-python supports python, not ${language}.`,
53
+ passedProofs: [],
54
+ failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
55
+ runtime: runtimeInfo(runtime),
56
+ };
57
+ }
58
+ return probeEryxRuntime(runtime, config);
59
+ },
60
+ async execute(request) {
61
+ if (request.language !== "python") {
62
+ return {
63
+ status: "policy_violation",
64
+ stdout: "",
65
+ stderr: "",
66
+ outputFiles: [],
67
+ exitCode: null,
68
+ reason: `eryx-python supports python, not ${request.language}.`,
69
+ };
70
+ }
71
+ if (request.network !== "off") {
72
+ return {
73
+ status: "policy_violation",
74
+ stdout: "",
75
+ stderr: "",
76
+ outputFiles: [],
77
+ exitCode: null,
78
+ reason: "eryx-python adapter only supports network=off.",
79
+ };
80
+ }
81
+ if (!runtime.jspiAvailable) {
82
+ return executeEryxInJspiChild(runtime, request);
83
+ }
84
+ const inputs = {};
85
+ for (const source of request.sources) {
86
+ inputs[source.alias] = await readFile(source.path, "utf8");
87
+ }
88
+ const run = await runEryx(runtime, {
89
+ code: pythonPrelude(inputs) + request.code,
90
+ timeoutMs: request.limits.timeoutMs,
91
+ outputBytes: request.limits.maxOutputBytes,
92
+ inputs,
93
+ });
94
+ return eryxRunToExecutionResult(run);
95
+ },
96
+ };
94
97
  }
95
98
  function unavailableEryxAdapter(reason) {
96
- return {
97
- id: "eryx-python",
98
- version: "unavailable",
99
- languages: ["python"],
100
- async probe() {
101
- return {
102
- status: "unavailable",
103
- reason,
104
- passedProofs: [],
105
- failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
106
- };
107
- },
108
- async execute() {
109
- return {
110
- status: "policy_violation",
111
- stdout: "",
112
- stderr: "",
113
- outputFiles: [],
114
- exitCode: null,
115
- reason,
116
- };
117
- },
118
- };
99
+ return {
100
+ id: "eryx-python",
101
+ version: "unavailable",
102
+ languages: ["python"],
103
+ async probe() {
104
+ return {
105
+ status: "unavailable",
106
+ reason,
107
+ passedProofs: [],
108
+ failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
109
+ };
110
+ },
111
+ async execute() {
112
+ return {
113
+ status: "policy_violation",
114
+ stdout: "",
115
+ stderr: "",
116
+ outputFiles: [],
117
+ exitCode: null,
118
+ reason,
119
+ };
120
+ },
121
+ };
119
122
  }
120
123
  async function loadEryxRuntime(packageRoot) {
121
- const resolvedRoot = resolve(packageRoot);
122
- const packageJson = JSON.parse(await readFile(join(resolvedRoot, "package.json"), "utf8"));
123
- const preview2ShimRoot = resolve(resolvedRoot, "..", "..", "@bytecodealliance", "preview2-shim");
124
- const preview2ShimJson = JSON.parse(await readFile(join(preview2ShimRoot, "package.json"), "utf8"));
125
- const runtimeHash = await hashEryxRuntime(resolvedRoot, preview2ShimRoot);
126
- return {
127
- packageName: String(packageJson.name ?? "@bsull/eryx"),
128
- packageVersion: String(packageJson.version ?? "unknown"),
129
- packageRoot: resolvedRoot,
130
- preview2ShimRoot,
131
- preview2ShimVersion: String(preview2ShimJson.version ?? "unknown"),
132
- runtimeHash,
133
- jspiAvailable: nodeJspiAvailable(),
134
- };
124
+ const resolvedRoot = resolve(packageRoot);
125
+ const packageJson = JSON.parse(await readFile(join(resolvedRoot, "package.json"), "utf8"));
126
+ const preview2ShimRoot = resolve(resolvedRoot, "..", "..", "@bytecodealliance", "preview2-shim");
127
+ const preview2ShimJson = JSON.parse(await readFile(join(preview2ShimRoot, "package.json"), "utf8"));
128
+ const runtimeHash = await hashEryxRuntime(resolvedRoot, preview2ShimRoot);
129
+ return {
130
+ packageName: String(packageJson.name ?? "@bsull/eryx"),
131
+ packageVersion: String(packageJson.version ?? "unknown"),
132
+ packageRoot: resolvedRoot,
133
+ preview2ShimRoot,
134
+ preview2ShimVersion: String(preview2ShimJson.version ?? "unknown"),
135
+ runtimeHash,
136
+ jspiAvailable: nodeJspiAvailable(),
137
+ };
135
138
  }
136
139
  async function hashEryxRuntime(packageRoot, preview2ShimRoot) {
137
- const hash = createHash("sha256");
138
- hash.update("eryx-runtime-tree-v1\0");
139
- await hashRuntimeTree(hash, packageRoot, "eryx");
140
- await hashRuntimeTree(hash, preview2ShimRoot, "preview2-shim");
141
- return `sha256_${hash.digest("hex")}`;
140
+ const hash = createHash("sha256");
141
+ hash.update("eryx-runtime-tree-v1\0");
142
+ await hashRuntimeTree(hash, packageRoot, "eryx");
143
+ await hashRuntimeTree(hash, preview2ShimRoot, "preview2-shim");
144
+ return `sha256_${hash.digest("hex")}`;
142
145
  }
143
146
  async function hashRuntimeTree(hash, root, label, relativeDir = ".") {
144
- const dir = join(root, relativeDir);
145
- const entries = await readdir(dir, { withFileTypes: true });
146
- entries.sort((left, right) => left.name.localeCompare(right.name));
147
- for (const entry of entries) {
148
- const relativePath = relativeDir === "." ? entry.name : join(relativeDir, entry.name);
149
- const fullPath = join(root, relativePath);
150
- const stats = await lstat(fullPath);
151
- if (stats.isSymbolicLink()) {
152
- throw new Error(`${label} runtime tree contains unsupported symlink: ${relativePath}`);
153
- }
154
- if (stats.isDirectory()) {
155
- hash.update(`${label}:dir:${relativePath}\0`);
156
- await hashRuntimeTree(hash, root, label, relativePath);
157
- continue;
158
- }
159
- if (!stats.isFile()) {
160
- throw new Error(`${label} runtime tree contains unsupported non-file entry: ${relativePath}`);
161
- }
162
- hash.update(`${label}:file:${relativePath}:${stats.size}\0`);
163
- hash.update(await readFile(fullPath));
164
- }
147
+ const dir = join(root, relativeDir);
148
+ const entries = await readdir(dir, { withFileTypes: true });
149
+ entries.sort((left, right) => left.name.localeCompare(right.name));
150
+ for (const entry of entries) {
151
+ const relativePath = relativeDir === "." ? entry.name : join(relativeDir, entry.name);
152
+ const fullPath = join(root, relativePath);
153
+ const stats = await lstat(fullPath);
154
+ if (stats.isSymbolicLink()) {
155
+ throw new Error(`${label} runtime tree contains unsupported symlink: ${relativePath}`);
156
+ }
157
+ if (stats.isDirectory()) {
158
+ hash.update(`${label}:dir:${relativePath}\0`);
159
+ await hashRuntimeTree(hash, root, label, relativePath);
160
+ continue;
161
+ }
162
+ if (!stats.isFile()) {
163
+ throw new Error(`${label} runtime tree contains unsupported non-file entry: ${relativePath}`);
164
+ }
165
+ hash.update(`${label}:file:${relativePath}:${stats.size}\0`);
166
+ hash.update(await readFile(fullPath));
167
+ }
165
168
  }
166
169
  function nodeJspiAvailable() {
167
- const nodeOptions = process.env.NODE_OPTIONS ?? "";
168
- const flagPresent = process.execArgv.includes("--experimental-wasm-jspi") || nodeOptions.split(/\s+/).includes("--experimental-wasm-jspi");
169
- return flagPresent && typeof WebAssembly.Suspending === "function";
170
+ const nodeOptions = process.env.NODE_OPTIONS ?? "";
171
+ const flagPresent =
172
+ process.execArgv.includes("--experimental-wasm-jspi") ||
173
+ nodeOptions.split(/\s+/).includes("--experimental-wasm-jspi");
174
+ return flagPresent && typeof WebAssembly.Suspending === "function";
170
175
  }
171
176
  function runtimeInfo(runtime) {
172
- return {
173
- name: runtime.packageName,
174
- version: `${runtime.packageVersion}+preview2-shim-${runtime.preview2ShimVersion}`,
175
- };
177
+ return {
178
+ name: runtime.packageName,
179
+ version: `${runtime.packageVersion}+preview2-shim-${runtime.preview2ShimVersion}`,
180
+ };
176
181
  }
177
182
  async function probeEryxRuntime(runtime, config) {
178
- const timeoutMs = Math.min(config.limits.timeoutMs, DEFAULT_PROBE_TIMEOUT_MS);
179
- const outputBytes = Math.min(config.limits.maxOutputBytes, DEFAULT_PROBE_OUTPUT_BYTES);
180
- const currentRuntimeHash = await hashEryxRuntime(runtime.packageRoot, runtime.preview2ShimRoot);
181
- if (currentRuntimeHash !== runtime.runtimeHash) {
182
- return {
183
- status: "unavailable",
184
- reason: "eryx-python explicit package root changed after adapter creation; refusing to reuse stale proof cache.",
185
- passedProofs: [],
186
- failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
187
- runtime: runtimeInfo(runtime),
188
- };
189
- }
190
- const cacheKey = [runtime.packageVersion, runtime.preview2ShimVersion, currentRuntimeHash, runtime.jspiAvailable, timeoutMs, outputBytes, config.network].join(":");
191
- const cached = eryxProbeCache.get(cacheKey);
192
- if (cached) {
193
- return cloneProbeResult(await cached);
194
- }
195
- const probePromise = runEryxProbe(runtime, config, timeoutMs, outputBytes);
196
- eryxProbeCache.set(cacheKey, probePromise);
197
- try {
198
- return cloneProbeResult(await probePromise);
199
- }
200
- catch (error) {
201
- eryxProbeCache.delete(cacheKey);
202
- throw error;
203
- }
183
+ const timeoutMs = Math.min(config.limits.timeoutMs, DEFAULT_PROBE_TIMEOUT_MS);
184
+ const outputBytes = Math.min(config.limits.maxOutputBytes, DEFAULT_PROBE_OUTPUT_BYTES);
185
+ const currentRuntimeHash = await hashEryxRuntime(runtime.packageRoot, runtime.preview2ShimRoot);
186
+ if (currentRuntimeHash !== runtime.runtimeHash) {
187
+ return {
188
+ status: "unavailable",
189
+ reason: "eryx-python explicit package root changed after adapter creation; refusing to reuse stale proof cache.",
190
+ passedProofs: [],
191
+ failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
192
+ runtime: runtimeInfo(runtime),
193
+ };
194
+ }
195
+ const cacheKey = [
196
+ runtime.packageVersion,
197
+ runtime.preview2ShimVersion,
198
+ currentRuntimeHash,
199
+ runtime.jspiAvailable,
200
+ timeoutMs,
201
+ outputBytes,
202
+ config.network,
203
+ ].join(":");
204
+ const cached = eryxProbeCache.get(cacheKey);
205
+ if (cached) {
206
+ return cloneProbeResult(await cached);
207
+ }
208
+ const probePromise = runEryxProbe(runtime, config, timeoutMs, outputBytes);
209
+ eryxProbeCache.set(cacheKey, probePromise);
210
+ try {
211
+ return cloneProbeResult(await probePromise);
212
+ } catch (error) {
213
+ eryxProbeCache.delete(cacheKey);
214
+ throw error;
215
+ }
204
216
  }
205
217
  async function runEryxProbe(runtime, config, timeoutMs, outputBytes) {
206
- if (config.network !== "off") {
207
- return {
208
- status: "unavailable",
209
- reason: "eryx-python adapter only supports network=off.",
210
- passedProofs: [],
211
- failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
212
- runtime: runtimeInfo(runtime),
213
- };
214
- }
215
- if (!runtime.jspiAvailable) {
216
- return probeEryxInJspiChild(runtime, config);
217
- }
218
- const previousSecret = process.env.FREEFLOW_SANDBOX_SECRET_SENTINEL;
219
- process.env.FREEFLOW_SANDBOX_SECRET_SENTINEL = SECRET_SENTINEL;
220
- try {
221
- const passedProofs = [];
222
- const failedProofs = [];
223
- const fixtures = scriptSandboxProofFixturesForLanguage("python");
224
- for (const fixture of fixtures) {
225
- const run = await runEryx(runtime, {
226
- code: fixture.program,
227
- timeoutMs,
228
- outputBytes,
229
- });
230
- const assessment = assessEryxProof(fixture.proof, run, timeoutMs, outputBytes);
231
- if (assessment) {
232
- passedProofs.push(fixture.proof);
233
- }
234
- else {
235
- failedProofs.push(fixture.proof);
236
- }
237
- }
238
- const allPassed = SCRIPT_SANDBOX_REQUIRED_PROOFS.every((proof) => passedProofs.includes(proof));
239
- return {
240
- status: allPassed ? "available" : "unavailable",
241
- reason: allPassed ? "eryx-python passed every required Python sandbox proof." : "eryx-python did not pass every required Python sandbox proof.",
242
- passedProofs,
243
- failedProofs,
244
- runtime: runtimeInfo(runtime),
245
- };
218
+ if (config.network !== "off") {
219
+ return {
220
+ status: "unavailable",
221
+ reason: "eryx-python adapter only supports network=off.",
222
+ passedProofs: [],
223
+ failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
224
+ runtime: runtimeInfo(runtime),
225
+ };
226
+ }
227
+ if (!runtime.jspiAvailable) {
228
+ return probeEryxInJspiChild(runtime, config);
229
+ }
230
+ const previousSecret = process.env.FREEFLOW_SANDBOX_SECRET_SENTINEL;
231
+ process.env.FREEFLOW_SANDBOX_SECRET_SENTINEL = SECRET_SENTINEL;
232
+ try {
233
+ const passedProofs = [];
234
+ const failedProofs = [];
235
+ const fixtures = scriptSandboxProofFixturesForLanguage("python");
236
+ for (const fixture of fixtures) {
237
+ const run = await runEryx(runtime, {
238
+ code: fixture.program,
239
+ timeoutMs,
240
+ outputBytes,
241
+ });
242
+ const assessment = assessEryxProof(fixture.proof, run, timeoutMs, outputBytes);
243
+ if (assessment) {
244
+ passedProofs.push(fixture.proof);
245
+ } else {
246
+ failedProofs.push(fixture.proof);
247
+ }
246
248
  }
247
- finally {
248
- if (previousSecret === undefined) {
249
- delete process.env.FREEFLOW_SANDBOX_SECRET_SENTINEL;
250
- }
251
- else {
252
- process.env.FREEFLOW_SANDBOX_SECRET_SENTINEL = previousSecret;
253
- }
249
+ const allPassed = SCRIPT_SANDBOX_REQUIRED_PROOFS.every((proof) => passedProofs.includes(proof));
250
+ return {
251
+ status: allPassed ? "available" : "unavailable",
252
+ reason: allPassed
253
+ ? "eryx-python passed every required Python sandbox proof."
254
+ : "eryx-python did not pass every required Python sandbox proof.",
255
+ passedProofs,
256
+ failedProofs,
257
+ runtime: runtimeInfo(runtime),
258
+ };
259
+ } finally {
260
+ if (previousSecret === undefined) {
261
+ delete process.env.FREEFLOW_SANDBOX_SECRET_SENTINEL;
262
+ } else {
263
+ process.env.FREEFLOW_SANDBOX_SECRET_SENTINEL = previousSecret;
254
264
  }
265
+ }
255
266
  }
256
267
  async function probeEryxInJspiChild(runtime, config) {
257
- try {
258
- const result = await runEryxChildRequest({
259
- kind: "probe",
260
- packageRoot: runtime.packageRoot,
261
- config,
262
- }, childTimeoutMsForProbe(config));
263
- if (isProbeResult(result)) {
264
- return {
265
- ...result,
266
- reason: result.status === "available"
267
- ? `${result.reason} via child Node --experimental-wasm-jspi.`
268
- : result.reason,
269
- };
270
- }
271
- return unavailableProbeResult("eryx-python child probe returned an execution result instead of a probe result.", runtime);
272
- }
273
- catch (error) {
274
- return unavailableProbeResult(`eryx-python child JSPI probe failed: ${errorMessage(error)}`, runtime);
275
- }
268
+ try {
269
+ const result = await runEryxChildRequest(
270
+ {
271
+ kind: "probe",
272
+ packageRoot: runtime.packageRoot,
273
+ config,
274
+ },
275
+ childTimeoutMsForProbe(config),
276
+ );
277
+ if (isProbeResult(result)) {
278
+ return {
279
+ ...result,
280
+ reason:
281
+ result.status === "available" ? `${result.reason} via child Node --experimental-wasm-jspi.` : result.reason,
282
+ };
283
+ }
284
+ return unavailableProbeResult(
285
+ "eryx-python child probe returned an execution result instead of a probe result.",
286
+ runtime,
287
+ );
288
+ } catch (error) {
289
+ return unavailableProbeResult(`eryx-python child JSPI probe failed: ${errorMessage(error)}`, runtime);
290
+ }
276
291
  }
277
292
  async function executeEryxInJspiChild(runtime, request) {
278
- try {
279
- const result = await runEryxChildRequest({
280
- kind: "execute",
281
- packageRoot: runtime.packageRoot,
282
- request,
283
- }, childTimeoutMsForExecution(request));
284
- if (isExecutionResult(result)) {
285
- return result;
286
- }
287
- return {
288
- status: "failed",
289
- stdout: "",
290
- stderr: "eryx-python child execution returned a probe result instead of an execution result.",
291
- outputFiles: [],
292
- exitCode: null,
293
- reason: "Invalid child execution response.",
294
- };
295
- }
296
- catch (error) {
297
- const message = errorMessage(error);
298
- return {
299
- status: "failed",
300
- stdout: "",
301
- stderr: message,
302
- outputFiles: [],
303
- exitCode: null,
304
- reason: `eryx-python child JSPI execution failed: ${message}`,
305
- };
293
+ try {
294
+ const result = await runEryxChildRequest(
295
+ {
296
+ kind: "execute",
297
+ packageRoot: runtime.packageRoot,
298
+ request,
299
+ },
300
+ childTimeoutMsForExecution(request),
301
+ );
302
+ if (isExecutionResult(result)) {
303
+ return result;
306
304
  }
305
+ return {
306
+ status: "failed",
307
+ stdout: "",
308
+ stderr: "eryx-python child execution returned a probe result instead of an execution result.",
309
+ outputFiles: [],
310
+ exitCode: null,
311
+ reason: "Invalid child execution response.",
312
+ };
313
+ } catch (error) {
314
+ const message = errorMessage(error);
315
+ return {
316
+ status: "failed",
317
+ stdout: "",
318
+ stderr: message,
319
+ outputFiles: [],
320
+ exitCode: null,
321
+ reason: `eryx-python child JSPI execution failed: ${message}`,
322
+ };
323
+ }
307
324
  }
308
325
  async function runEryxChildRequest(request, timeoutMs) {
309
- const root = await mkdtemp(join(tmpdir(), "freeflow-eryx-child-"));
310
- const requestPath = join(root, "request.json");
311
- const responsePath = join(root, "response.json");
312
- try {
313
- await writeFile(requestPath, JSON.stringify(request), "utf8");
314
- await runEryxChildProcess(requestPath, responsePath, timeoutMs);
315
- const response = JSON.parse(await readFile(responsePath, "utf8"));
316
- if (!response.ok) {
317
- throw new Error(response.message);
318
- }
319
- return response.result;
320
- }
321
- finally {
322
- await rm(root, { recursive: true, force: true });
323
- }
326
+ const root = await mkdtemp(join(tmpdir(), "freeflow-eryx-child-"));
327
+ const requestPath = join(root, "request.json");
328
+ const responsePath = join(root, "response.json");
329
+ try {
330
+ await writeFile(requestPath, JSON.stringify(request), "utf8");
331
+ await runEryxChildProcess(requestPath, responsePath, timeoutMs);
332
+ const response = JSON.parse(await readFile(responsePath, "utf8"));
333
+ if (!response.ok) {
334
+ throw new Error(response.message);
335
+ }
336
+ return response.result;
337
+ } finally {
338
+ await rm(root, { recursive: true, force: true });
339
+ }
324
340
  }
325
341
  async function runEryxChildProcess(requestPath, responsePath, timeoutMs) {
326
- const nodeBinary = await resolveEryxChildNodeBinary();
327
- const child = spawn(nodeBinary, ["--experimental-wasm-jspi", fileURLToPath(import.meta.url), ERYX_CHILD_MODE_ARG, requestPath, responsePath], {
328
- stdio: ["ignore", "ignore", "pipe"],
329
- env: process.env,
330
- });
331
- let stderr = "";
332
- child.stderr.setEncoding("utf8");
333
- child.stderr.on("data", (chunk) => {
334
- stderr += String(chunk);
342
+ const nodeBinary = await resolveEryxChildNodeBinary();
343
+ const child = spawn(
344
+ nodeBinary,
345
+ ["--experimental-wasm-jspi", fileURLToPath(import.meta.url), ERYX_CHILD_MODE_ARG, requestPath, responsePath],
346
+ {
347
+ stdio: ["ignore", "ignore", "pipe"],
348
+ env: process.env,
349
+ },
350
+ );
351
+ let stderr = "";
352
+ child.stderr.setEncoding("utf8");
353
+ child.stderr.on("data", (chunk) => {
354
+ stderr += String(chunk);
355
+ });
356
+ await new Promise((resolvePromise, reject) => {
357
+ const timer = setTimeout(() => {
358
+ child.kill("SIGKILL");
359
+ reject(new Error(`eryx-python child process timed out after ${timeoutMs}ms.`));
360
+ }, timeoutMs);
361
+ child.on("error", (error) => {
362
+ clearTimeout(timer);
363
+ reject(error);
335
364
  });
336
- await new Promise((resolvePromise, reject) => {
337
- const timer = setTimeout(() => {
338
- child.kill("SIGKILL");
339
- reject(new Error(`eryx-python child process timed out after ${timeoutMs}ms.`));
340
- }, timeoutMs);
341
- child.on("error", (error) => {
342
- clearTimeout(timer);
343
- reject(error);
344
- });
345
- child.on("close", (code) => {
346
- clearTimeout(timer);
347
- if (code === 0) {
348
- resolvePromise();
349
- }
350
- else {
351
- reject(new Error(`eryx-python child process ${nodeBinary} exited with code ${code}. ${stderr.trim()}`));
352
- }
353
- });
365
+ child.on("close", (code) => {
366
+ clearTimeout(timer);
367
+ if (code === 0) {
368
+ resolvePromise();
369
+ } else {
370
+ reject(new Error(`eryx-python child process ${nodeBinary} exited with code ${code}. ${stderr.trim()}`));
371
+ }
354
372
  });
373
+ });
355
374
  }
356
375
  async function resolveEryxChildNodeBinary() {
357
- const configured = defaultScriptTransformNodeBinary();
358
- if (await fileExists(configured)) {
359
- return configured;
360
- }
361
- return process.execPath;
376
+ const configured = defaultScriptTransformNodeBinary();
377
+ if (await fileExists(configured)) {
378
+ return configured;
379
+ }
380
+ return process.execPath;
362
381
  }
363
382
  async function fileExists(path) {
364
- try {
365
- await access(path);
366
- return true;
367
- }
368
- catch {
369
- return false;
370
- }
383
+ try {
384
+ await access(path);
385
+ return true;
386
+ } catch {
387
+ return false;
388
+ }
371
389
  }
372
390
  function childTimeoutMsForProbe(config) {
373
- return Math.max(ERYX_CHILD_TIMEOUT_FLOOR_MS, Math.min(config.limits.timeoutMs, DEFAULT_PROBE_TIMEOUT_MS) * SCRIPT_SANDBOX_REQUIRED_PROOFS.length * 8);
391
+ return Math.max(
392
+ ERYX_CHILD_TIMEOUT_FLOOR_MS,
393
+ Math.min(config.limits.timeoutMs, DEFAULT_PROBE_TIMEOUT_MS) * SCRIPT_SANDBOX_REQUIRED_PROOFS.length * 8,
394
+ );
374
395
  }
375
396
  function childTimeoutMsForExecution(request) {
376
- return Math.max(ERYX_CHILD_TIMEOUT_FLOOR_MS, request.limits.timeoutMs + 5_000);
397
+ return Math.max(ERYX_CHILD_TIMEOUT_FLOOR_MS, request.limits.timeoutMs + 5_000);
377
398
  }
378
399
  function unavailableProbeResult(reason, runtime) {
379
- return {
380
- status: "unavailable",
381
- reason,
382
- passedProofs: [],
383
- failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
384
- runtime: runtimeInfo(runtime),
385
- };
400
+ return {
401
+ status: "unavailable",
402
+ reason,
403
+ passedProofs: [],
404
+ failedProofs: [...SCRIPT_SANDBOX_REQUIRED_PROOFS],
405
+ runtime: runtimeInfo(runtime),
406
+ };
386
407
  }
387
408
  function isProbeResult(value) {
388
- return Array.isArray(value.passedProofs) && Array.isArray(value.failedProofs);
409
+ return Array.isArray(value.passedProofs) && Array.isArray(value.failedProofs);
389
410
  }
390
411
  function isExecutionResult(value) {
391
- return Array.isArray(value.outputFiles);
412
+ return Array.isArray(value.outputFiles);
392
413
  }
393
414
  async function runEryx(runtime, options) {
394
- const start = Date.now();
395
- const patched = await createPatchedPackageTree(runtime);
396
- try {
397
- const eryxEntryUrl = pathToFileURL(join(patched.eryxRoot, "index.js")).href;
398
- return await runEryxWorker({ eryxEntryUrl, code: options.code, timeoutMs: options.timeoutMs, outputBytes: options.outputBytes, startedAt: start });
399
- }
400
- finally {
401
- await rm(patched.root, { recursive: true, force: true });
402
- }
415
+ const start = Date.now();
416
+ const patched = await createPatchedPackageTree(runtime);
417
+ try {
418
+ const eryxEntryUrl = pathToFileURL(join(patched.eryxRoot, "index.js")).href;
419
+ return await runEryxWorker({
420
+ eryxEntryUrl,
421
+ code: options.code,
422
+ timeoutMs: options.timeoutMs,
423
+ outputBytes: options.outputBytes,
424
+ startedAt: start,
425
+ });
426
+ } finally {
427
+ await rm(patched.root, { recursive: true, force: true });
428
+ }
403
429
  }
404
430
  async function createPatchedPackageTree(runtime) {
405
- const root = await mkdtemp(join(tmpdir(), "freeflow-eryx-adapter-"));
406
- const eryxRoot = join(root, "node_modules", "@bsull", "eryx");
407
- const preview2ShimRoot = join(root, "node_modules", "@bytecodealliance", "preview2-shim");
408
- try {
409
- await mkdir(dirname(eryxRoot), { recursive: true });
410
- await mkdir(dirname(preview2ShimRoot), { recursive: true });
411
- await cp(runtime.packageRoot, eryxRoot, { recursive: true, dereference: false });
412
- await cp(runtime.preview2ShimRoot, preview2ShimRoot, { recursive: true, dereference: false });
413
- const copiedRuntimeHash = await hashEryxRuntime(eryxRoot, preview2ShimRoot);
414
- if (copiedRuntimeHash !== runtime.runtimeHash) {
415
- throw new Error("eryx-python explicit package root changed while preparing sandbox copy; refusing to execute unproven runtime files.");
416
- }
417
- for (const file of [join(eryxRoot, "index.js"), join(eryxRoot, "eryx-sandbox.js")]) {
418
- let text = await readFile(file, "utf8");
419
- for (const [from, to] of PREVIEW2_IMPORTS) {
420
- text = text.split(from).join(to);
421
- }
422
- await writeFile(file, text, "utf8");
423
- }
424
- await writeInstrumentedNetworkDenyShim(eryxRoot);
425
- return { root, eryxRoot };
426
- }
427
- catch (error) {
428
- await rm(root, { recursive: true, force: true });
429
- throw error;
431
+ const root = await mkdtemp(join(tmpdir(), "freeflow-eryx-adapter-"));
432
+ const eryxRoot = join(root, "node_modules", "@bsull", "eryx");
433
+ const preview2ShimRoot = join(root, "node_modules", "@bytecodealliance", "preview2-shim");
434
+ try {
435
+ await mkdir(dirname(eryxRoot), { recursive: true });
436
+ await mkdir(dirname(preview2ShimRoot), { recursive: true });
437
+ await cp(runtime.packageRoot, eryxRoot, { recursive: true, dereference: false });
438
+ await cp(runtime.preview2ShimRoot, preview2ShimRoot, { recursive: true, dereference: false });
439
+ const copiedRuntimeHash = await hashEryxRuntime(eryxRoot, preview2ShimRoot);
440
+ if (copiedRuntimeHash !== runtime.runtimeHash) {
441
+ throw new Error(
442
+ "eryx-python explicit package root changed while preparing sandbox copy; refusing to execute unproven runtime files.",
443
+ );
444
+ }
445
+ for (const file of [join(eryxRoot, "index.js"), join(eryxRoot, "eryx-sandbox.js")]) {
446
+ let text = await readFile(file, "utf8");
447
+ for (const [from, to] of PREVIEW2_IMPORTS) {
448
+ text = text.split(from).join(to);
449
+ }
450
+ await writeFile(file, text, "utf8");
430
451
  }
452
+ await writeInstrumentedNetworkDenyShim(eryxRoot);
453
+ return { root, eryxRoot };
454
+ } catch (error) {
455
+ await rm(root, { recursive: true, force: true });
456
+ throw error;
457
+ }
431
458
  }
432
459
  async function writeInstrumentedNetworkDenyShim(eryxRoot) {
433
- await writeFile(join(eryxRoot, "shims", "net.js"), `
460
+ await writeFile(
461
+ join(eryxRoot, "shims", "net.js"),
462
+ `
434
463
  const recordNetworkDeny = (kind, operation) => {
435
464
  globalThis.__freeflowEryxNetworkEvents ??= [];
436
465
  globalThis.__freeflowEryxNetworkEvents.push({ kind, operation, decision: "not-permitted" });
@@ -473,10 +502,12 @@ export const tls = {
473
502
  recordNetworkDeny("tls", "close");
474
503
  },
475
504
  };
476
- `, "utf8");
505
+ `,
506
+ "utf8",
507
+ );
477
508
  }
478
509
  async function runEryxWorker(options) {
479
- const workerSource = `
510
+ const workerSource = `
480
511
  import { parentPort, workerData } from 'node:worker_threads';
481
512
 
482
513
  let stdout = '';
@@ -544,254 +575,294 @@ async function runEryxWorker(options) {
544
575
  finish({ status: 'error', errorName: error?.name ?? 'Error', errorMessage: message, exitCode: 1 });
545
576
  }
546
577
  `;
547
- const worker = new Worker(workerSource, {
548
- eval: true,
549
- type: "module",
550
- workerData: { eryxEntryUrl: options.eryxEntryUrl, code: options.code, outputBytes: options.outputBytes },
551
- stdout: true,
552
- stderr: true,
553
- resourceLimits: {
554
- maxOldGenerationSizeMb: DEFAULT_WORKER_OLD_GENERATION_MB,
555
- maxYoungGenerationSizeMb: DEFAULT_WORKER_YOUNG_GENERATION_MB,
556
- },
557
- });
558
- let externalStdout = "";
559
- let externalStderr = "";
560
- let externalRawStdoutBytes = 0;
561
- let externalRawStderrBytes = 0;
562
- let externalTruncated = false;
563
- const appendExternal = (stream, chunk) => {
564
- const text = String(chunk ?? "");
565
- const bytes = Buffer.byteLength(text, "utf8");
566
- if (stream === "stderr")
567
- externalRawStderrBytes += bytes;
568
- else
569
- externalRawStdoutBytes += bytes;
570
- const currentBytes = Buffer.byteLength(externalStdout, "utf8") + Buffer.byteLength(externalStderr, "utf8");
571
- const remaining = options.outputBytes - currentBytes;
572
- if (remaining <= 0) {
573
- externalTruncated = externalTruncated || bytes > 0;
574
- return;
575
- }
576
- const buffer = Buffer.from(text, "utf8");
577
- const nextText = buffer.byteLength > remaining ? buffer.subarray(0, remaining).toString("utf8") : text;
578
- if (buffer.byteLength > remaining)
579
- externalTruncated = true;
580
- if (stream === "stderr")
581
- externalStderr += nextText;
582
- else
583
- externalStdout += nextText;
578
+ const worker = new Worker(workerSource, {
579
+ eval: true,
580
+ type: "module",
581
+ workerData: { eryxEntryUrl: options.eryxEntryUrl, code: options.code, outputBytes: options.outputBytes },
582
+ stdout: true,
583
+ stderr: true,
584
+ resourceLimits: {
585
+ maxOldGenerationSizeMb: DEFAULT_WORKER_OLD_GENERATION_MB,
586
+ maxYoungGenerationSizeMb: DEFAULT_WORKER_YOUNG_GENERATION_MB,
587
+ },
588
+ });
589
+ let externalStdout = "";
590
+ let externalStderr = "";
591
+ let externalRawStdoutBytes = 0;
592
+ let externalRawStderrBytes = 0;
593
+ let externalTruncated = false;
594
+ const appendExternal = (stream, chunk) => {
595
+ const text = String(chunk ?? "");
596
+ const bytes = Buffer.byteLength(text, "utf8");
597
+ if (stream === "stderr") externalRawStderrBytes += bytes;
598
+ else externalRawStdoutBytes += bytes;
599
+ const currentBytes = Buffer.byteLength(externalStdout, "utf8") + Buffer.byteLength(externalStderr, "utf8");
600
+ const remaining = options.outputBytes - currentBytes;
601
+ if (remaining <= 0) {
602
+ externalTruncated = externalTruncated || bytes > 0;
603
+ return;
604
+ }
605
+ const buffer = Buffer.from(text, "utf8");
606
+ const nextText = buffer.byteLength > remaining ? buffer.subarray(0, remaining).toString("utf8") : text;
607
+ if (buffer.byteLength > remaining) externalTruncated = true;
608
+ if (stream === "stderr") externalStderr += nextText;
609
+ else externalStdout += nextText;
610
+ };
611
+ worker.stdout?.on("data", (chunk) => appendExternal("stdout", chunk));
612
+ worker.stderr?.on("data", (chunk) => appendExternal("stderr", chunk));
613
+ return new Promise((resolve) => {
614
+ let settled = false;
615
+ const finish = (result) => {
616
+ if (settled) return;
617
+ settled = true;
618
+ clearTimeout(timer);
619
+ const merged = mergeWorkerResult(result, {
620
+ externalStdout,
621
+ externalStderr,
622
+ externalRawStdoutBytes,
623
+ externalRawStderrBytes,
624
+ externalTruncated,
625
+ outputBytes: options.outputBytes,
626
+ });
627
+ resolve({ ...merged, durationMs: Date.now() - options.startedAt });
584
628
  };
585
- worker.stdout?.on("data", (chunk) => appendExternal("stdout", chunk));
586
- worker.stderr?.on("data", (chunk) => appendExternal("stderr", chunk));
587
- return new Promise((resolve) => {
588
- let settled = false;
589
- const finish = (result) => {
590
- if (settled)
591
- return;
592
- settled = true;
593
- clearTimeout(timer);
594
- const merged = mergeWorkerResult(result, {
595
- externalStdout,
596
- externalStderr,
597
- externalRawStdoutBytes,
598
- externalRawStderrBytes,
599
- externalTruncated,
600
- outputBytes: options.outputBytes,
601
- });
602
- resolve({ ...merged, durationMs: Date.now() - options.startedAt });
603
- };
604
- const timer = setTimeout(() => {
605
- if (settled)
606
- return;
607
- finish({ status: "timed_out", stdout: "", stderr: "", exitCode: null, rawStdoutBytes: 0, rawStderrBytes: 0, stdoutBytes: 0, stderrBytes: 0, outputBytes: 0, truncated: false, outputFiles: [], networkEvents: [] });
608
- void worker.terminate();
609
- }, options.timeoutMs);
610
- worker.on("message", (message) => finish(message));
611
- worker.on("error", (error) => {
612
- const message = errorMessage(error);
613
- finish({ status: "error", stdout: "", stderr: message, exitCode: null, rawStdoutBytes: 0, rawStderrBytes: Buffer.byteLength(message, "utf8"), truncated: false, outputFiles: [], networkEvents: [], errorName: error.name, errorMessage: message });
614
- });
615
- worker.on("exit", (code) => {
616
- if (!settled && code !== 0) {
617
- finish({ status: "error", stdout: "", stderr: `worker exited with code ${code}`, exitCode: code, rawStdoutBytes: 0, rawStderrBytes: 0, truncated: false, outputFiles: [], networkEvents: [] });
618
- }
629
+ const timer = setTimeout(() => {
630
+ if (settled) return;
631
+ finish({
632
+ status: "timed_out",
633
+ stdout: "",
634
+ stderr: "",
635
+ exitCode: null,
636
+ rawStdoutBytes: 0,
637
+ rawStderrBytes: 0,
638
+ stdoutBytes: 0,
639
+ stderrBytes: 0,
640
+ outputBytes: 0,
641
+ truncated: false,
642
+ outputFiles: [],
643
+ networkEvents: [],
644
+ });
645
+ void worker.terminate();
646
+ }, options.timeoutMs);
647
+ worker.on("message", (message) => finish(message));
648
+ worker.on("error", (error) => {
649
+ const message = errorMessage(error);
650
+ finish({
651
+ status: "error",
652
+ stdout: "",
653
+ stderr: message,
654
+ exitCode: null,
655
+ rawStdoutBytes: 0,
656
+ rawStderrBytes: Buffer.byteLength(message, "utf8"),
657
+ truncated: false,
658
+ outputFiles: [],
659
+ networkEvents: [],
660
+ errorName: error.name,
661
+ errorMessage: message,
662
+ });
663
+ });
664
+ worker.on("exit", (code) => {
665
+ if (!settled && code !== 0) {
666
+ finish({
667
+ status: "error",
668
+ stdout: "",
669
+ stderr: `worker exited with code ${code}`,
670
+ exitCode: code,
671
+ rawStdoutBytes: 0,
672
+ rawStderrBytes: 0,
673
+ truncated: false,
674
+ outputFiles: [],
675
+ networkEvents: [],
619
676
  });
677
+ }
620
678
  });
679
+ });
621
680
  }
622
681
  function mergeWorkerResult(result, external) {
623
- let stdout = "";
624
- let stderr = "";
625
- let truncated = Boolean(result.truncated || external.externalTruncated);
626
- const append = (stream, value) => {
627
- const currentBytes = Buffer.byteLength(stdout, "utf8") + Buffer.byteLength(stderr, "utf8");
628
- const remaining = external.outputBytes - currentBytes;
629
- if (remaining <= 0) {
630
- truncated = truncated || Buffer.byteLength(value, "utf8") > 0;
631
- return;
632
- }
633
- const buffer = Buffer.from(value, "utf8");
634
- const nextText = buffer.byteLength > remaining ? buffer.subarray(0, remaining).toString("utf8") : value;
635
- if (buffer.byteLength > remaining)
636
- truncated = true;
637
- if (stream === "stderr")
638
- stderr += nextText;
639
- else
640
- stdout += nextText;
641
- };
642
- append("stdout", external.externalStdout);
643
- append("stderr", external.externalStderr);
644
- append("stdout", result.stdout ?? "");
645
- append("stderr", result.stderr ?? "");
646
- const rawStdoutBytes = (result.rawStdoutBytes ?? 0) + external.externalRawStdoutBytes;
647
- const rawStderrBytes = (result.rawStderrBytes ?? 0) + external.externalRawStderrBytes;
648
- const merged = {
649
- status: result.status ?? "error",
650
- stdout,
651
- stderr,
652
- rawStdoutBytes,
653
- rawStderrBytes,
654
- stdoutBytes: Buffer.byteLength(stdout, "utf8"),
655
- stderrBytes: Buffer.byteLength(stderr, "utf8"),
656
- outputBytes: Buffer.byteLength(stdout, "utf8") + Buffer.byteLength(stderr, "utf8"),
657
- truncated,
658
- exitCode: result.exitCode ?? null,
659
- durationMs: result.durationMs ?? 0,
660
- outputFiles: result.outputFiles ?? [],
661
- networkEvents: result.networkEvents ?? [],
662
- };
663
- if (result.errorName !== undefined) {
664
- merged.errorName = result.errorName;
665
- }
666
- if (result.errorMessage !== undefined) {
667
- merged.errorMessage = result.errorMessage;
668
- }
669
- return merged;
682
+ let stdout = "";
683
+ let stderr = "";
684
+ let truncated = Boolean(result.truncated || external.externalTruncated);
685
+ const append = (stream, value) => {
686
+ const currentBytes = Buffer.byteLength(stdout, "utf8") + Buffer.byteLength(stderr, "utf8");
687
+ const remaining = external.outputBytes - currentBytes;
688
+ if (remaining <= 0) {
689
+ truncated = truncated || Buffer.byteLength(value, "utf8") > 0;
690
+ return;
691
+ }
692
+ const buffer = Buffer.from(value, "utf8");
693
+ const nextText = buffer.byteLength > remaining ? buffer.subarray(0, remaining).toString("utf8") : value;
694
+ if (buffer.byteLength > remaining) truncated = true;
695
+ if (stream === "stderr") stderr += nextText;
696
+ else stdout += nextText;
697
+ };
698
+ append("stdout", external.externalStdout);
699
+ append("stderr", external.externalStderr);
700
+ append("stdout", result.stdout ?? "");
701
+ append("stderr", result.stderr ?? "");
702
+ const rawStdoutBytes = (result.rawStdoutBytes ?? 0) + external.externalRawStdoutBytes;
703
+ const rawStderrBytes = (result.rawStderrBytes ?? 0) + external.externalRawStderrBytes;
704
+ const merged = {
705
+ status: result.status ?? "error",
706
+ stdout,
707
+ stderr,
708
+ rawStdoutBytes,
709
+ rawStderrBytes,
710
+ stdoutBytes: Buffer.byteLength(stdout, "utf8"),
711
+ stderrBytes: Buffer.byteLength(stderr, "utf8"),
712
+ outputBytes: Buffer.byteLength(stdout, "utf8") + Buffer.byteLength(stderr, "utf8"),
713
+ truncated,
714
+ exitCode: result.exitCode ?? null,
715
+ durationMs: result.durationMs ?? 0,
716
+ outputFiles: result.outputFiles ?? [],
717
+ networkEvents: result.networkEvents ?? [],
718
+ };
719
+ if (result.errorName !== undefined) {
720
+ merged.errorName = result.errorName;
721
+ }
722
+ if (result.errorMessage !== undefined) {
723
+ merged.errorMessage = result.errorMessage;
724
+ }
725
+ return merged;
670
726
  }
671
727
  function eryxRunToExecutionResult(run) {
672
- if (run.status === "timed_out") {
673
- return {
674
- status: "timed_out",
675
- stdout: run.stdout,
676
- stderr: run.stderr,
677
- outputFiles: [],
678
- exitCode: null,
679
- durationMs: run.durationMs,
680
- reason: "Eryx Python execution exceeded timeoutMs.",
681
- };
682
- }
683
- if (run.truncated || run.status === "output_limit_exceeded") {
684
- return {
685
- status: "failed",
686
- stdout: run.stdout,
687
- stderr: run.stderr,
688
- outputFiles: [],
689
- exitCode: run.exitCode,
690
- durationMs: run.durationMs,
691
- reason: "Eryx Python execution exceeded maxOutputBytes.",
692
- };
693
- }
694
- if (run.status === "error") {
695
- return {
696
- status: "failed",
697
- stdout: run.stdout,
698
- stderr: run.stderr || run.errorMessage || "Eryx Python execution failed.",
699
- outputFiles: [],
700
- exitCode: run.exitCode,
701
- durationMs: run.durationMs,
702
- reason: "Eryx Python execution failed.",
703
- };
704
- }
728
+ if (run.status === "timed_out") {
705
729
  return {
706
- status: "success",
707
- stdout: run.stdout,
708
- stderr: run.stderr,
709
- outputFiles: [],
710
- exitCode: 0,
711
- durationMs: run.durationMs,
730
+ status: "timed_out",
731
+ stdout: run.stdout,
732
+ stderr: run.stderr,
733
+ outputFiles: [],
734
+ exitCode: null,
735
+ durationMs: run.durationMs,
736
+ reason: "Eryx Python execution exceeded timeoutMs.",
737
+ };
738
+ }
739
+ if (run.truncated || run.status === "output_limit_exceeded") {
740
+ return {
741
+ status: "failed",
742
+ stdout: run.stdout,
743
+ stderr: run.stderr,
744
+ outputFiles: [],
745
+ exitCode: run.exitCode,
746
+ durationMs: run.durationMs,
747
+ reason: "Eryx Python execution exceeded maxOutputBytes.",
712
748
  };
749
+ }
750
+ if (run.status === "error") {
751
+ return {
752
+ status: "failed",
753
+ stdout: run.stdout,
754
+ stderr: run.stderr || run.errorMessage || "Eryx Python execution failed.",
755
+ outputFiles: [],
756
+ exitCode: run.exitCode,
757
+ durationMs: run.durationMs,
758
+ reason: "Eryx Python execution failed.",
759
+ };
760
+ }
761
+ return {
762
+ status: "success",
763
+ stdout: run.stdout,
764
+ stderr: run.stderr,
765
+ outputFiles: [],
766
+ exitCode: 0,
767
+ durationMs: run.durationMs,
768
+ };
713
769
  }
714
770
  function assessEryxProof(proof, run, timeoutMs, outputBytes) {
715
- const combined = `${run.stdout ?? ""}\n${run.stderr ?? ""}\n${run.errorMessage ?? ""}`;
716
- switch (proof) {
717
- case "env_access_denied":
718
- return !combined.includes(SECRET_SENTINEL) && !combined.includes(HOST_HOME) && !combined.includes("process.env") && !/AWS_|GITHUB_|TOKEN|SECRET/i.test(combined);
719
- case "home_access_denied":
720
- return !combined.includes(HOST_HOME) && !/PRIVATE KEY|FREEFLOW_SANDBOX_SECRET/.test(combined);
721
- case "repo_access_denied":
722
- return !combined.includes("@hassangameryt/freeflow") && !combined.includes("@earendil-works/freeflow") && !combined.includes('"scripts"');
723
- case "vault_access_denied":
724
- return !combined.includes("ffout_") && !combined.includes("ffrec_");
725
- case "network_access_denied":
726
- return run.status !== "success" && networkDeniedByShim(run) && !combined.includes("Example Domain");
727
- case "input_read_only":
728
- return run.status !== "success" && !combined.includes("mutated");
729
- case "output_escape_denied":
730
- return !combined.includes("/etc/passwd") && run.outputFiles.length === 0;
731
- case "stdout_stderr_bounded":
732
- return run.status !== "error" && run.truncated && run.outputBytes <= outputBytes && run.rawStdoutBytes > outputBytes && run.rawStderrBytes > outputBytes;
733
- case "timeout_enforced":
734
- return run.status === "timed_out" && run.durationMs < timeoutMs * 5;
735
- default:
736
- return false;
737
- }
771
+ const combined = `${run.stdout ?? ""}\n${run.stderr ?? ""}\n${run.errorMessage ?? ""}`;
772
+ switch (proof) {
773
+ case "env_access_denied":
774
+ return (
775
+ !combined.includes(SECRET_SENTINEL) &&
776
+ !combined.includes(HOST_HOME) &&
777
+ !combined.includes("process.env") &&
778
+ !/AWS_|GITHUB_|TOKEN|SECRET/i.test(combined)
779
+ );
780
+ case "home_access_denied":
781
+ return !combined.includes(HOST_HOME) && !/PRIVATE KEY|FREEFLOW_SANDBOX_SECRET/.test(combined);
782
+ case "repo_access_denied":
783
+ return (
784
+ !combined.includes("@hassangameryt/freeflow") &&
785
+ !combined.includes("@earendil-works/freeflow") &&
786
+ !combined.includes('"scripts"')
787
+ );
788
+ case "vault_access_denied":
789
+ return !combined.includes("ffout_") && !combined.includes("ffrec_");
790
+ case "network_access_denied":
791
+ return run.status !== "success" && networkDeniedByShim(run) && !combined.includes("Example Domain");
792
+ case "input_read_only":
793
+ return run.status !== "success" && !combined.includes("mutated");
794
+ case "output_escape_denied":
795
+ return !combined.includes("/etc/passwd") && run.outputFiles.length === 0;
796
+ case "stdout_stderr_bounded":
797
+ return (
798
+ run.status !== "error" &&
799
+ run.truncated &&
800
+ run.outputBytes <= outputBytes &&
801
+ run.rawStdoutBytes > outputBytes &&
802
+ run.rawStderrBytes > outputBytes
803
+ );
804
+ case "timeout_enforced":
805
+ return run.status === "timed_out" && run.durationMs < timeoutMs * 5;
806
+ default:
807
+ return false;
808
+ }
738
809
  }
739
810
  function networkDeniedByShim(run) {
740
- return run.networkEvents.some((event) => event?.decision === "not-permitted" && (event?.kind === "tcp" || event?.kind === "tls"));
811
+ return run.networkEvents.some(
812
+ (event) => event?.decision === "not-permitted" && (event?.kind === "tcp" || event?.kind === "tls"),
813
+ );
741
814
  }
742
815
  function pythonPrelude(inputs) {
743
- const encodedInputs = JSON.stringify(inputs).replaceAll("</", "<\\/");
744
- return [
745
- "# Freeflow injected input/output helpers.",
746
- "import json as __freeflow_json",
747
- `__freeflow_sources = __freeflow_json.loads(${JSON.stringify(encodedInputs)})`,
748
- "sources = dict(__freeflow_sources)",
749
- "def read_text(alias):",
750
- " return __freeflow_sources[alias]",
751
- "def write_text(text):",
752
- " print(str(text), end='')",
753
- "",
754
- ].join("\n");
816
+ const encodedInputs = JSON.stringify(inputs).replaceAll("</", "<\\/");
817
+ return [
818
+ "# Freeflow injected input/output helpers.",
819
+ "import json as __freeflow_json",
820
+ `__freeflow_sources = __freeflow_json.loads(${JSON.stringify(encodedInputs)})`,
821
+ "sources = dict(__freeflow_sources)",
822
+ "def read_text(alias):",
823
+ " return __freeflow_sources[alias]",
824
+ "def write_text(text):",
825
+ " print(str(text), end='')",
826
+ "",
827
+ ].join("\n");
755
828
  }
756
829
  function cloneProbeResult(result) {
757
- const cloned = {
758
- ...result,
759
- passedProofs: [...result.passedProofs],
760
- failedProofs: [...result.failedProofs],
761
- };
762
- if (result.runtime !== undefined) {
763
- cloned.runtime = { ...result.runtime };
764
- }
765
- return cloned;
830
+ const cloned = {
831
+ ...result,
832
+ passedProofs: [...result.passedProofs],
833
+ failedProofs: [...result.failedProofs],
834
+ };
835
+ if (result.runtime !== undefined) {
836
+ cloned.runtime = { ...result.runtime };
837
+ }
838
+ return cloned;
766
839
  }
767
840
  async function runEryxChildCli(argv) {
768
- const requestPath = argv[0];
769
- const responsePath = argv[1];
770
- if (!requestPath || !responsePath) {
771
- throw new Error("eryx-python child mode requires request and response paths.");
772
- }
773
- const payload = JSON.parse(await readFile(requestPath, "utf8"));
774
- let response;
775
- try {
776
- const adapter = await createEryxPythonSandboxAdapter({ packageRoot: payload.packageRoot });
777
- if (payload.kind === "probe") {
778
- response = { ok: true, result: await adapter.probe("python", payload.config) };
779
- }
780
- else {
781
- response = { ok: true, result: await adapter.execute(payload.request) };
782
- }
783
- }
784
- catch (error) {
785
- response = { ok: false, message: errorMessage(error) };
786
- }
787
- await writeFile(responsePath, JSON.stringify(response), "utf8");
841
+ const requestPath = argv[0];
842
+ const responsePath = argv[1];
843
+ if (!requestPath || !responsePath) {
844
+ throw new Error("eryx-python child mode requires request and response paths.");
845
+ }
846
+ const payload = JSON.parse(await readFile(requestPath, "utf8"));
847
+ let response;
848
+ try {
849
+ const adapter = await createEryxPythonSandboxAdapter({ packageRoot: payload.packageRoot });
850
+ if (payload.kind === "probe") {
851
+ response = { ok: true, result: await adapter.probe("python", payload.config) };
852
+ } else {
853
+ response = { ok: true, result: await adapter.execute(payload.request) };
854
+ }
855
+ } catch (error) {
856
+ response = { ok: false, message: errorMessage(error) };
857
+ }
858
+ await writeFile(responsePath, JSON.stringify(response), "utf8");
788
859
  }
789
860
  function errorMessage(error) {
790
- return error instanceof Error ? error.message : String(error);
861
+ return error instanceof Error ? error.message : String(error);
791
862
  }
792
863
  if (process.argv[2] === ERYX_CHILD_MODE_ARG) {
793
- runEryxChildCli(process.argv.slice(3)).catch((error) => {
794
- console.error(errorMessage(error));
795
- process.exit(1);
796
- });
864
+ runEryxChildCli(process.argv.slice(3)).catch((error) => {
865
+ console.error(errorMessage(error));
866
+ process.exit(1);
867
+ });
797
868
  }