failproofai 1.0.7-beta.2 → 1.0.7

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 (252) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +4 -4
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page.js +4 -4
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  11. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  12. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page.js +4 -4
  16. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  20. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  21. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
  22. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/audit/run/route.js +7 -8
  25. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  33. package/.next/standalone/.next/server/app/audit/page.js +5 -7
  34. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  36. package/.next/standalone/.next/server/app/index.html +1 -1
  37. package/.next/standalone/.next/server/app/index.rsc +15 -15
  38. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
  39. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  40. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  41. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  42. package/.next/standalone/.next/server/app/page.js +6 -6
  43. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  46. package/.next/standalone/.next/server/app/policies/page.js +11 -13
  47. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  50. package/.next/standalone/.next/server/app/project/[name]/page.js +7 -8
  51. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  54. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  55. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +7 -7
  56. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  59. package/.next/standalone/.next/server/app/projects/page.js +6 -7
  60. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  61. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -41
  63. package/.next/standalone/.next/server/app/settings/page.js +9 -12
  64. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/chunks/{[externals]__1j-zsg5._.js → [externals]__1_bftcl._.js} +1 -1
  67. package/.next/standalone/.next/server/chunks/{[externals]__19_pzeq._.js → [externals]__1msfs-h._.js} +1 -1
  68. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l3yhx4._.js +2 -2
  69. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  70. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1bf34x4._.js → [root-of-the-server]__1_r2rbg._.js} +7 -5
  71. package/.next/standalone/.next/server/chunks/_09dz7xv._.js +21 -21
  72. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  73. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  74. package/.next/standalone/.next/server/chunks/{_1q5i8mb._.js → _1c3k-8x._.js} +2 -2
  75. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +16 -16
  76. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  77. package/.next/standalone/.next/server/chunks/src_hooks_0iu54mz._.js +3 -0
  78. package/.next/standalone/.next/server/chunks/src_hooks_custom-hooks-loader_ts_0lnb3n3._.js +2 -4
  79. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-_ki57._.js +4 -0
  80. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +4 -0
  81. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +4 -0
  82. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +4 -0
  83. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0l44ual._.js → [root-of-the-server]__0bd3mje._.js} +2 -2
  84. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cg-bgc._.js +5 -0
  85. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cpu_mj._.js +3 -0
  86. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1mf3zp6._.js → [root-of-the-server]__0cxe_2_._.js} +3 -3
  87. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +4 -0
  88. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +4 -0
  89. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +4 -0
  90. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u3w0ll._.js +22 -0
  91. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17d_ffl._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19d9tgz._.js +5 -0
  93. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1jiwfsj._.js +3 -0
  95. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +4 -0
  96. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1phc187._.js +3 -0
  97. package/.next/standalone/.next/server/chunks/ssr/_06imw3p._.js +5 -0
  98. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/ssr/{_1w_5l7t._.js → _0h_douw._.js} +1 -1
  100. package/.next/standalone/.next/server/chunks/ssr/{_1mel6y1._.js → _1-i_gzc._.js} +2 -2
  101. package/.next/standalone/.next/server/chunks/ssr/{_1v-jvrv._.js → _166t73i._.js} +1 -1
  102. package/.next/standalone/.next/server/chunks/ssr/{_1q46vxx._.js → _1_qswah._.js} +2 -2
  103. package/.next/standalone/.next/server/chunks/ssr/{_1gb0ifp._.js → _1es2j7i._.js} +5 -5
  104. package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +3 -0
  105. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  106. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
  107. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  110. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +3 -0
  111. package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_0w6mzq5._.js → node_modules_next_dist_0drixxt._.js} +4 -4
  112. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1cv9_c4._.js +10 -0
  113. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
  114. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
  115. package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me65._.js +1 -1
  116. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  117. package/.next/standalone/.next/server/pages/404.html +1 -1
  118. package/.next/standalone/.next/server/pages/500.html +1 -1
  119. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  120. package/.next/standalone/.next/server/server-reference-manifest.json +23 -56
  121. package/.next/standalone/.next/static/chunks/094xgi4owxaqf.js +1 -0
  122. package/.next/standalone/.next/static/chunks/{129ag2bw93bdh.js → 0__8a7m868fvf.js} +1 -1
  123. package/.next/standalone/.next/static/chunks/{3ugmd_7dyn0id.js → 0o6qlkgubtoex.js} +1 -1
  124. package/.next/standalone/.next/static/chunks/{0fqd7m_u81mi5.js → 13i7-9is-vhys.js} +1 -1
  125. package/.next/standalone/.next/static/chunks/1rz20_pz828f3.js +6 -0
  126. package/.next/standalone/.next/static/chunks/2k9f4tyv04809.css +1 -0
  127. package/.next/standalone/.next/static/chunks/{2_pltstd8-xgs.js → 2klitrtzpaoe0.js} +1 -1
  128. package/.next/standalone/.next/static/chunks/{3brze37td_wnc.js → 2mdh397ghgnvv.js} +1 -1
  129. package/.next/standalone/.next/static/chunks/2rshywgeqsyzk.css +2 -0
  130. package/.next/standalone/.next/static/chunks/3pzx4chkhko9k.js +1 -0
  131. package/.next/standalone/.next/static/chunks/3rh5o7e16irrm.js +69 -0
  132. package/.next/standalone/.next/static/chunks/{1qd741hzlmjbo.js → 43ufqrz8qo3h-.js} +1 -1
  133. package/.next/standalone/SECURITY.md +53 -0
  134. package/.next/standalone/app/actions/pack-actions.ts +0 -12
  135. package/.next/standalone/app/policies/hooks-client.tsx +0 -9
  136. package/.next/standalone/app/settings/page.tsx +1 -20
  137. package/.next/standalone/app/settings/settings-client.tsx +1 -27
  138. package/.next/standalone/app/settings/settings.css +0 -79
  139. package/.next/standalone/package.json +10 -10
  140. package/.next/standalone/sdk/typescript/CHANGELOG.md +15 -1
  141. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package-lock.json +10 -30
  142. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package.json +3 -0
  143. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +4 -16
  144. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +3 -0
  145. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package-lock.json +13 -132
  146. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package.json +4 -0
  147. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package-lock.json +4 -142
  148. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package.json +4 -0
  149. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +1396 -1016
  150. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +9 -0
  151. package/.next/standalone/server.js +1 -1
  152. package/README.md +2 -2
  153. package/bin/failproofai.mjs +2 -115
  154. package/dist/cli.mjs +6543 -13872
  155. package/dist/index.js +1 -19
  156. package/dist/worker.mjs +2022 -8055
  157. package/package.json +10 -10
  158. package/pi-extension/index.ts +0 -11
  159. package/scripts/build-policy-pack.mjs +2 -53
  160. package/src/audit/features.ts +2 -3
  161. package/src/hooks/builtin-policies.ts +8 -177
  162. package/src/hooks/cloud-enrollment-cli.ts +1 -1
  163. package/src/hooks/cloud-managed-policies.ts +0 -22
  164. package/src/hooks/custom-hooks-loader.ts +7 -45
  165. package/src/hooks/custom-hooks-registry.ts +1 -45
  166. package/src/hooks/first-run-gate.ts +0 -5
  167. package/src/hooks/fp-home.ts +0 -23
  168. package/src/hooks/handler.ts +6 -265
  169. package/src/hooks/hook-activity-store.ts +1 -105
  170. package/src/hooks/hook-telemetry.ts +0 -41
  171. package/src/hooks/loader-utils.ts +0 -6
  172. package/src/hooks/manager.ts +1 -1
  173. package/src/hooks/pack-cli.ts +19 -412
  174. package/src/hooks/pack-manifest.ts +7 -479
  175. package/src/hooks/pack-store.ts +11 -157
  176. package/src/hooks/policy-catalog.ts +0 -204
  177. package/src/hooks/policy-evaluator.ts +796 -940
  178. package/src/hooks/policy-registry.ts +0 -25
  179. package/src/hooks/policy-types.ts +0 -126
  180. package/src/hooks/types.ts +1 -1
  181. package/src/hooks/worker-server.ts +26 -119
  182. package/src/index.ts +0 -6
  183. package/.next/standalone/.next/server/chunks/src_hooks_01frwmb._.js +0 -5
  184. package/.next/standalone/.next/server/chunks/src_hooks_18qtd42._.js +0 -3
  185. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01bmjsj._.js +0 -3
  186. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +0 -4
  187. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +0 -4
  188. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__059yza8._.js +0 -3
  189. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0eip4_k._.js +0 -22
  190. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +0 -4
  191. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qcb0mg._.js +0 -3
  192. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qxnccm._.js +0 -5
  193. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +0 -4
  194. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s_yomn._.js +0 -4
  195. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0soxz2z._.js +0 -3
  196. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0yrsbd_._.js +0 -3
  197. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +0 -4
  198. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__13d-wb6._.js +0 -3
  199. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1dinjii._.js +0 -3
  200. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +0 -4
  201. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +0 -4
  202. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qiz0e4._.js +0 -3
  203. package/.next/standalone/.next/server/chunks/ssr/_042cgl1._.js +0 -3
  204. package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +0 -3
  205. package/.next/standalone/.next/server/chunks/ssr/_0uyu3jf._.js +0 -3
  206. package/.next/standalone/.next/server/chunks/ssr/_1feuvhb._.js +0 -5
  207. package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +0 -3
  208. package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +0 -3
  209. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_18_d8l1._.js +0 -151
  210. package/.next/standalone/.next/server/chunks/ssr/src_hooks_095a_79._.js +0 -5
  211. package/.next/standalone/.next/server/chunks/ssr/src_hooks_15t8kqj._.js +0 -3
  212. package/.next/standalone/.next/server/chunks/ssr/src_hooks_18k8rl0._.js +0 -12
  213. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1fm2w5z._.js +0 -3
  214. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1j0zy3v._.js +0 -3
  215. package/.next/standalone/.next/static/chunks/043j99m8ykg__.css +0 -2
  216. package/.next/standalone/.next/static/chunks/2c8j9l6j_b1ci.js +0 -1
  217. package/.next/standalone/.next/static/chunks/2qv4hshejedtx.css +0 -1
  218. package/.next/standalone/.next/static/chunks/3-k569wzcli8q.js +0 -1
  219. package/.next/standalone/.next/static/chunks/3otmypm6j_xfo.js +0 -6
  220. package/.next/standalone/.next/static/chunks/3yxro_r2_o9ad.js +0 -69
  221. package/.next/standalone/PROBE-FOLLOWUP.md +0 -186
  222. package/.next/standalone/app/actions/get-jev-config.ts +0 -424
  223. package/.next/standalone/app/actions/update-jev-config.ts +0 -420
  224. package/.next/standalone/app/components/jev-notices.tsx +0 -96
  225. package/.next/standalone/app/settings/jev-panel.tsx +0 -473
  226. package/src/hooks/effective-reviewers.ts +0 -79
  227. package/src/hooks/jev-activity.ts +0 -385
  228. package/src/hooks/jev-cli.ts +0 -1249
  229. package/src/hooks/policy-authority.ts +0 -333
  230. package/src/hooks/policy-reviewability.ts +0 -229
  231. package/src/hooks/semantic/combine.ts +0 -541
  232. package/src/hooks/semantic/compile.ts +0 -176
  233. package/src/hooks/semantic/decide.ts +0 -392
  234. package/src/hooks/semantic/envelope.ts +0 -1296
  235. package/src/hooks/semantic/evaluator.ts +0 -547
  236. package/src/hooks/semantic/facts.ts +0 -292
  237. package/src/hooks/semantic/intent.ts +0 -1190
  238. package/src/hooks/semantic/jev-client.ts +0 -643
  239. package/src/hooks/semantic/jev-config.ts +0 -594
  240. package/src/hooks/semantic/jev-review.ts +0 -374
  241. package/src/hooks/semantic/jev-stats.ts +0 -289
  242. package/src/hooks/semantic/jev-throttle.ts +0 -421
  243. package/src/hooks/semantic/pack-policies.ts +0 -251
  244. package/src/hooks/semantic/policies.ts +0 -596
  245. package/src/hooks/semantic/precondition-names.ts +0 -60
  246. package/src/hooks/semantic/preconditions.ts +0 -58
  247. package/src/hooks/semantic/redact.ts +0 -2910
  248. package/src/hooks/semantic/types.ts +0 -145
  249. package/src/hooks/semver-precedence.ts +0 -128
  250. /package/.next/standalone/.next/static/{gbEOjBgZAxF2UIUwZVHNu → PgeWCHmyVbjRznv2VO7KF}/_buildManifest.js +0 -0
  251. /package/.next/standalone/.next/static/{gbEOjBgZAxF2UIUwZVHNu → PgeWCHmyVbjRznv2VO7KF}/_clientMiddlewareManifest.js +0 -0
  252. /package/.next/standalone/.next/static/{gbEOjBgZAxF2UIUwZVHNu → PgeWCHmyVbjRznv2VO7KF}/_ssgManifest.js +0 -0
@@ -1,292 +0,0 @@
1
- /**
2
- * Deterministic facts about a tool call, computed locally before Jev is asked.
3
- *
4
- * TypeSafe's own jaggedness notes say Jev cannot count, resolve paths or do
5
- * arithmetic, and answers the question you wrote rather than the one you
6
- * meant. So anything with one right answer — which directory `*` expands in
7
- * after a `cd`, whether a path is inside the project, which branch is checked
8
- * out — is worked out here and handed to Jev as a fact rather than a question.
9
- *
10
- * Everything in this file is linear in the input and never spawns a process:
11
- * it runs on the hook's hot path, inside the daemon worker's serialised chain.
12
- */
13
- import { existsSync, readFileSync, statSync } from "node:fs";
14
- import { homedir } from "node:os";
15
- import { dirname, isAbsolute, resolve } from "node:path";
16
- import type { Facts, PathFact, ToolClass } from "./types";
17
-
18
- const SHELL_TOOLS = new Set(["Bash", "BashOutput"]);
19
- const WRITE_TOOLS = new Set(["Write", "Edit", "MultiEdit", "NotebookEdit"]);
20
- const READ_TOOLS = new Set(["Read", "Glob", "Grep", "LS"]);
21
- const NETWORK_TOOLS = new Set(["WebFetch", "WebSearch"]);
22
- /** Known tools with no side effects worth judging. They never cost a Jev call. */
23
- const INERT_TOOLS = new Set([
24
- "TodoWrite", "TodoRead", "ExitPlanMode", "EnterPlanMode", "Task", "Agent",
25
- "AskUserQuestion", "ToolSearch", "KillShell", "SlashCommand", "Skill",
26
- ]);
27
-
28
- export function classifyTool(toolName: string): { toolClass: ToolClass; toolIsKnown: boolean } {
29
- if (SHELL_TOOLS.has(toolName)) return { toolClass: "shell", toolIsKnown: true };
30
- if (WRITE_TOOLS.has(toolName)) return { toolClass: "write", toolIsKnown: true };
31
- if (READ_TOOLS.has(toolName)) return { toolClass: "read", toolIsKnown: true };
32
- if (NETWORK_TOOLS.has(toolName)) return { toolClass: "network", toolIsKnown: true };
33
- if (INERT_TOOLS.has(toolName)) return { toolClass: "other", toolIsKnown: true };
34
- // MCP tools (`mcp__server__tool`), skills that shell out, and anything a
35
- // harness names that no canonical map covers. These are exactly the calls
36
- // the regex engine never sees, because every builtin opens with a toolName
37
- // check.
38
- return { toolClass: "other", toolIsKnown: false };
39
- }
40
-
41
- /** Upper bound on command text the scanner will look at. Linear, but bounded. */
42
- export const MAX_SCAN_CHARS = 8_192;
43
-
44
- export interface ScannedCommand {
45
- /** Simple-command segments, split on `&&`, `||`, `;`, `|` and newlines. */
46
- segments: string[][];
47
- /** The command with shell comments removed (quote-aware). */
48
- withoutComments: string;
49
- commentsRemoved: boolean;
50
- /** The removed comment text, so the injection probe can still see it. */
51
- comments: string[];
52
- }
53
-
54
- /**
55
- * A single left-to-right pass over a shell command: quote-aware tokenising,
56
- * operator splitting and comment removal. It is deliberately not a full shell
57
- * parser — it only needs to find words, segment boundaries and comments, and
58
- * it must stay linear no matter what the agent sends.
59
- */
60
- export function scanCommand(command: string): ScannedCommand {
61
- const text = command.length > MAX_SCAN_CHARS ? command.slice(0, MAX_SCAN_CHARS) : command;
62
- const segments: string[][] = [];
63
- let tokens: string[] = [];
64
- let word = "";
65
- let inWord = false;
66
- let quote: "'" | '"' | null = null;
67
- let out = "";
68
- let commentsRemoved = false;
69
- const comments: string[] = [];
70
-
71
- const endWord = () => {
72
- if (inWord) tokens.push(word);
73
- word = "";
74
- inWord = false;
75
- };
76
- const endSegment = () => {
77
- endWord();
78
- if (tokens.length > 0) segments.push(tokens);
79
- tokens = [];
80
- };
81
-
82
- for (let i = 0; i < text.length; i++) {
83
- const c = text[i];
84
- if (quote) {
85
- out += c;
86
- if (c === quote) {
87
- quote = null;
88
- } else if (c === "\\" && quote === '"' && i + 1 < text.length) {
89
- word += text[++i];
90
- out += text[i];
91
- } else {
92
- word += c;
93
- }
94
- continue;
95
- }
96
- if (c === "'" || c === '"') {
97
- quote = c;
98
- inWord = true;
99
- out += c;
100
- continue;
101
- }
102
- if (c === "\\" && i + 1 < text.length) {
103
- word += text[i + 1];
104
- inWord = true;
105
- out += c + text[++i];
106
- continue;
107
- }
108
- if (c === "#" && !inWord) {
109
- // A comment runs to end of line. Classic place to hide "approved by
110
- // security" in a command that is about to be judged by a language model.
111
- const nl = text.indexOf("\n", i);
112
- commentsRemoved = true;
113
- comments.push(text.slice(i, nl === -1 ? text.length : nl));
114
- if (nl === -1) break;
115
- i = nl - 1;
116
- continue;
117
- }
118
- if (c === "\n" || c === ";") {
119
- endSegment();
120
- out += c;
121
- continue;
122
- }
123
- if (c === "&" || c === "|") {
124
- endSegment();
125
- out += c;
126
- if (text[i + 1] === c) out += text[++i];
127
- continue;
128
- }
129
- if (c === " " || c === "\t") {
130
- endWord();
131
- out += c;
132
- continue;
133
- }
134
- word += c;
135
- inWord = true;
136
- out += c;
137
- }
138
- endSegment();
139
- return { segments, withoutComments: out.trimEnd(), commentsRemoved, comments };
140
- }
141
-
142
- const PATH_LIKE = /^(?:\/|~|\.\.?(?:\/|$)|[^:]*\/)/;
143
- const GLOB_CHARS = /[*?[]/;
144
-
145
- function expandHome(token: string, home: string): string {
146
- if (token === "~") return home;
147
- if (token.startsWith("~/")) return home + token.slice(1);
148
- if (token.startsWith("$HOME/")) return home + token.slice(5);
149
- if (token === "$HOME") return home;
150
- return token;
151
- }
152
-
153
- function relationOf(resolved: string, projectRoot: string | null, home: string): PathFact["relation"] {
154
- if (resolved === "/") return "root";
155
- if (projectRoot) {
156
- if (resolved === projectRoot) return "project_root";
157
- if (resolved.startsWith(projectRoot + "/")) return "inside_project";
158
- }
159
- if (resolved === home) return "home_root";
160
- if (resolved.startsWith(home + "/")) return "outside_project_in_home";
161
- return "system";
162
- }
163
-
164
- function pathFact(token: string, base: string, projectRoot: string | null, home: string): PathFact | null {
165
- if (token.includes("://")) return null;
166
- let t = expandHome(token, home);
167
- // A glob names the contents of its directory: `*` after `cd /` is the root.
168
- if (GLOB_CHARS.test(t)) {
169
- const slash = t.lastIndexOf("/");
170
- t = slash === -1 ? "." : slash === 0 ? "/" : t.slice(0, slash);
171
- }
172
- const resolved = isAbsolute(t) ? resolve(t) : resolve(base, t);
173
- return { asWritten: token, resolved, relation: relationOf(resolved, projectRoot, home) };
174
- }
175
-
176
- const MAX_PATHS = 12;
177
-
178
- /** Paths a tool call touches, resolved against the cwd and any `cd` along the way. */
179
- export function extractPaths(
180
- toolInput: Record<string, unknown>,
181
- cwd: string | null,
182
- projectRoot: string | null,
183
- scanned: ScannedCommand | null,
184
- home: string = homedir(),
185
- ): PathFact[] {
186
- const base0 = cwd ?? home;
187
- const facts: PathFact[] = [];
188
- const seen = new Set<string>();
189
- const add = (f: PathFact | null) => {
190
- if (!f || seen.has(f.resolved + "\0" + f.asWritten) || facts.length >= MAX_PATHS) return;
191
- seen.add(f.resolved + "\0" + f.asWritten);
192
- facts.push(f);
193
- };
194
-
195
- for (const key of ["file_path", "path", "notebook_path"]) {
196
- const v = toolInput[key];
197
- if (typeof v === "string" && v.length > 0) add(pathFact(v, base0, projectRoot, home));
198
- }
199
-
200
- if (scanned) {
201
- let base = base0;
202
- for (const seg of scanned.segments) {
203
- if (seg[0] === "cd") {
204
- // A `cd` does two things and only one of them used to be recorded. Its
205
- // target rebases every relative path after it — that is the `base`
206
- // assignment, unchanged — but it is also a directory the call names in
207
- // its own right. Consuming it silently left `facts.paths` empty on
208
- // `cd ../other-repo && ./node_modules/.bin/tsc`, while the regex
209
- // partner reads the same text, resolves the target against the session
210
- // cwd and denies it. A deny whose paired question was never asked can
211
- // never clear, so the target is emitted as a path too.
212
- const written = seg[1];
213
- const f = pathFact(written ?? "~", base, projectRoot, home);
214
- if (!f) continue;
215
- base = f.resolved;
216
- // Only when the agent wrote a target. A bare `cd` (or `cd -`) leaves
217
- // the partner no token to deny, so there is no verdict to pair with,
218
- // and naming a directory nobody wrote would ask about it for nothing.
219
- if (written !== undefined && !written.startsWith("-")) add(f);
220
- continue;
221
- }
222
- // Skip argv[0]: `/usr/local/bin/kubectl` is the program, not its target.
223
- for (const tok of seg.slice(1)) {
224
- if (tok.startsWith("-")) continue;
225
- if (tok === "*" || tok === "." || tok === ".." || PATH_LIKE.test(tok) || tok.startsWith("$HOME")) {
226
- add(pathFact(tok, base, projectRoot, home));
227
- }
228
- }
229
- }
230
- }
231
- return facts;
232
- }
233
-
234
- function findGitDir(start: string): string | null {
235
- let dir = start;
236
- for (let i = 0; i < 40; i++) {
237
- const candidate = resolve(dir, ".git");
238
- if (existsSync(candidate)) return candidate;
239
- const parent = dirname(dir);
240
- if (parent === dir) return null;
241
- dir = parent;
242
- }
243
- return null;
244
- }
245
-
246
- export function findProjectRoot(cwd: string | null): string | null {
247
- if (!cwd) return null;
248
- const gitDir = findGitDir(cwd);
249
- return gitDir ? dirname(gitDir) : cwd;
250
- }
251
-
252
- /** Current branch from `.git/HEAD`, following a worktree's `gitdir:` pointer. No subprocess. */
253
- export function readCurrentBranch(cwd: string | null): string | null {
254
- if (!cwd) return null;
255
- try {
256
- const gitPath = findGitDir(cwd);
257
- if (!gitPath) return null;
258
- let headFile = resolve(gitPath, "HEAD");
259
- if (statSync(gitPath).isFile()) {
260
- const pointer = readFileSync(gitPath, "utf8").trim();
261
- const m = /^gitdir:\s*(.+)$/.exec(pointer);
262
- if (!m) return null;
263
- headFile = resolve(dirname(gitPath), m[1], "HEAD");
264
- }
265
- const head = readFileSync(headFile, "utf8").trim();
266
- const ref = /^ref:\s*refs\/heads\/(.+)$/.exec(head);
267
- return ref ? ref[1] : null;
268
- } catch {
269
- return null;
270
- }
271
- }
272
-
273
- export function computeFacts(
274
- toolName: string,
275
- toolInput: Record<string, unknown>,
276
- cwd: string | null,
277
- permissionMode: string | null,
278
- scanned: ScannedCommand | null,
279
- ): Facts {
280
- const { toolClass, toolIsKnown } = classifyTool(toolName);
281
- const projectRoot = findProjectRoot(cwd);
282
- return {
283
- toolName,
284
- toolClass,
285
- toolIsKnown,
286
- cwd,
287
- projectRoot,
288
- currentGitBranch: readCurrentBranch(cwd),
289
- paths: extractPaths(toolInput, cwd, projectRoot, scanned),
290
- permissionMode,
291
- };
292
- }