hex-audit 0.7.0 → 0.8.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 (584) hide show
  1. package/CLAUDE.md +137 -77
  2. package/DEMO.md +40 -117
  3. package/README.md +200 -402
  4. package/dashboard/.next/BUILD_ID +1 -1
  5. package/dashboard/.next/app-build-manifest.json +56 -101
  6. package/dashboard/.next/app-path-routes-manifest.json +1 -1
  7. package/dashboard/.next/build-manifest.json +9 -9
  8. package/dashboard/.next/next-server.js.nft.json +1 -1
  9. package/dashboard/.next/prerender-manifest.json +1 -1
  10. package/dashboard/.next/react-loadable-manifest.json +436 -15
  11. package/dashboard/.next/routes-manifest.json +1 -1
  12. package/dashboard/.next/server/app/_not-found/page.js +1 -1
  13. package/dashboard/.next/server/app/_not-found/page.js.nft.json +1 -1
  14. package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/dashboard/.next/server/app/api/code/route.js +1 -1
  16. package/dashboard/.next/server/app/api/code/route.js.nft.json +1 -1
  17. package/dashboard/.next/server/app/api/comments/route.js +1 -0
  18. package/dashboard/.next/server/app/api/comments/route.js.nft.json +1 -0
  19. package/dashboard/.next/server/app/api/diagrams/[name]/export/route.js +1 -0
  20. package/dashboard/.next/server/app/api/diagrams/[name]/export/route.js.nft.json +1 -0
  21. package/dashboard/.next/server/app/api/diagrams/[name]/resolve/route.js +1 -0
  22. package/dashboard/.next/server/app/api/diagrams/[name]/resolve/route.js.nft.json +1 -0
  23. package/dashboard/.next/server/app/api/diagrams/[name]/route.js +1 -0
  24. package/dashboard/.next/server/app/api/diagrams/[name]/route.js.nft.json +1 -0
  25. package/dashboard/.next/server/app/api/figures/[name]/route.js +1 -0
  26. package/dashboard/.next/server/app/api/figures/[name]/route.js.nft.json +1 -0
  27. package/dashboard/.next/server/app/api/focus/route.js +1 -0
  28. package/dashboard/.next/server/app/api/focus/route.js.nft.json +1 -0
  29. package/dashboard/.next/server/app/api/github-status/route.js +1 -1
  30. package/dashboard/.next/server/app/api/invariants/[id]/route.js +1 -0
  31. package/dashboard/.next/server/app/api/invariants/[id]/route.js.nft.json +1 -0
  32. package/dashboard/.next/server/app/api/issues/[id]/revert-auto/route.js +1 -0
  33. package/dashboard/.next/server/app/api/issues/[id]/revert-auto/route.js.nft.json +1 -0
  34. package/dashboard/.next/server/app/api/nav/route.js +1 -0
  35. package/dashboard/.next/server/app/api/nav/route.js.nft.json +1 -0
  36. package/dashboard/.next/server/app/api/notes/done/route.js +1 -1
  37. package/dashboard/.next/server/app/api/notes/done/route.js.nft.json +1 -1
  38. package/dashboard/.next/server/app/api/notes/lead/route.js +1 -1
  39. package/dashboard/.next/server/app/api/notes/lead/route.js.nft.json +1 -1
  40. package/dashboard/.next/server/app/api/notes/question/route.js +1 -1
  41. package/dashboard/.next/server/app/api/notes/question/route.js.nft.json +1 -1
  42. package/dashboard/.next/server/app/api/notes/record/route.js +3 -3
  43. package/dashboard/.next/server/app/api/notes/route.js +2 -2
  44. package/dashboard/.next/server/app/api/palette/route.js +1 -0
  45. package/dashboard/.next/server/app/api/palette/route.js.nft.json +1 -0
  46. package/dashboard/.next/server/app/api/progress/route.js +1 -1
  47. package/dashboard/.next/server/app/api/progress/route.js.nft.json +1 -1
  48. package/dashboard/.next/server/app/api/watch/route.js +2 -2
  49. package/dashboard/.next/server/app/api/watch/route.js.nft.json +1 -1
  50. package/dashboard/.next/server/app/api/xref/route.js +1 -0
  51. package/dashboard/.next/server/app/changes/page.js +1 -20
  52. package/dashboard/.next/server/app/changes/page.js.nft.json +1 -1
  53. package/dashboard/.next/server/app/changes/page_client-reference-manifest.js +1 -1
  54. package/dashboard/.next/server/app/excalidraw-assets/[...path]/route.js +1 -0
  55. package/dashboard/.next/server/app/issues/page.js +5 -28
  56. package/dashboard/.next/server/app/issues/page.js.nft.json +1 -1
  57. package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -1
  58. package/dashboard/.next/server/app/model/page.js +1 -0
  59. package/dashboard/.next/server/app/{calls → model}/page.js.nft.json +1 -1
  60. package/dashboard/.next/server/app/model/page_client-reference-manifest.js +1 -0
  61. package/dashboard/.next/server/app/page.js +1 -20
  62. package/dashboard/.next/server/app/page.js.nft.json +1 -1
  63. package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
  64. package/dashboard/.next/server/app/report/page.js +1 -1
  65. package/dashboard/.next/server/app/report/page.js.nft.json +1 -1
  66. package/dashboard/.next/server/app/report/page_client-reference-manifest.js +1 -1
  67. package/dashboard/.next/server/app/review/page.js +1 -0
  68. package/dashboard/.next/server/app/{access → review}/page.js.nft.json +1 -1
  69. package/dashboard/.next/server/app/review/page_client-reference-manifest.js +1 -0
  70. package/dashboard/.next/server/app-paths-manifest.json +19 -16
  71. package/dashboard/.next/server/chunks/310.js +4 -0
  72. package/dashboard/.next/server/chunks/370.js +1 -0
  73. package/dashboard/.next/server/chunks/42.js +1 -1
  74. package/dashboard/.next/server/chunks/624.js +14 -0
  75. package/dashboard/.next/server/chunks/645.js +1 -1
  76. package/dashboard/.next/server/chunks/649.js +1 -1
  77. package/dashboard/.next/server/chunks/653.js +1 -0
  78. package/dashboard/.next/server/functions-config-manifest.json +1 -1
  79. package/dashboard/.next/server/middleware-build-manifest.js +1 -1
  80. package/dashboard/.next/server/middleware-react-loadable-manifest.js +1 -1
  81. package/dashboard/.next/server/pages/500.html +1 -1
  82. package/dashboard/.next/server/pages/_error.js +1 -1
  83. package/dashboard/.next/server/server-reference-manifest.js +1 -1
  84. package/dashboard/.next/server/server-reference-manifest.json +1 -1
  85. package/dashboard/.next/static/chunks/0bbe10ee.8e7ffa06d2170dfe.js +84 -0
  86. package/dashboard/.next/static/chunks/1026.0ef689a305302427.js +1 -0
  87. package/dashboard/.next/static/chunks/1164.34eb76767ebea46f.js +8 -0
  88. package/dashboard/.next/static/chunks/119.a9a79633900a235f.js +5 -0
  89. package/dashboard/.next/static/chunks/1291.6c486c9b1d4b1b3a.js +1 -0
  90. package/dashboard/.next/static/chunks/139.4691848fc5a46253.js +10 -0
  91. package/dashboard/.next/static/chunks/145.1bf74fecdb4022e3.js +11 -0
  92. package/dashboard/.next/static/chunks/1517.8e7075f78e22b3a0.js +8 -0
  93. package/dashboard/.next/static/chunks/165.6f174060a0ce2db4.js +6 -0
  94. package/dashboard/.next/static/chunks/1741.5c370b7702d2eb40.js +8 -0
  95. package/dashboard/.next/static/chunks/1e36816c.5748c83adc8a6bd6.js +108 -0
  96. package/dashboard/.next/static/chunks/2061.eab75b3c1dfa068a.js +1 -0
  97. package/dashboard/.next/static/chunks/2148.3ce718f62d1b2f7c.js +10 -0
  98. package/dashboard/.next/static/chunks/217-1d5b680ffd10e3f9.js +1 -0
  99. package/dashboard/.next/static/chunks/2208.fb884379aa3ae968.js +1 -0
  100. package/dashboard/.next/static/chunks/2276.112c7855333fca5f.js +6 -0
  101. package/dashboard/.next/static/chunks/2374-8c6f137938f8518a.js +1 -0
  102. package/dashboard/.next/static/chunks/2445.18a86507d2996b95.js +1 -0
  103. package/dashboard/.next/static/chunks/2712.15dd8577973baf22.js +10 -0
  104. package/dashboard/.next/static/chunks/2759.533dec5317e0a1d1.js +1 -0
  105. package/dashboard/.next/static/chunks/2812.62b213bef580b69a.js +1 -0
  106. package/dashboard/.next/static/chunks/2895.bb57cacb7aaf42a1.js +9 -0
  107. package/dashboard/.next/static/chunks/2972.e5a9251b538dcf19.js +9 -0
  108. package/dashboard/.next/static/chunks/3206.8d9a10db2b04b93f.js +1 -0
  109. package/dashboard/.next/static/chunks/3485.36766504793b7237.js +9 -0
  110. package/dashboard/.next/static/chunks/3725.de9376dc994735d4.js +9 -0
  111. package/dashboard/.next/static/chunks/3774.1df377928e8387f7.js +9 -0
  112. package/dashboard/.next/static/chunks/3963.39d72b3875dfe2e9.js +13 -0
  113. package/dashboard/.next/static/chunks/4013.73884b23bfaebdde.js +11 -0
  114. package/dashboard/.next/static/chunks/4117.278aff1fa23fd36e.js +6 -0
  115. package/dashboard/.next/static/chunks/4210.cc8594110017c579.js +11 -0
  116. package/dashboard/.next/static/chunks/4282.28485875540886cc.js +7 -0
  117. package/dashboard/.next/static/chunks/4318.a2f469a88d88f6d0.js +8 -0
  118. package/dashboard/.next/static/chunks/4363.8999a6e727c48003.js +1 -0
  119. package/dashboard/.next/static/chunks/4641.e03d118fffebd580.js +5 -0
  120. package/dashboard/.next/static/chunks/483.a910dab7734a1074.js +8 -0
  121. package/dashboard/.next/static/chunks/4926.76693f542e9cc062.js +6 -0
  122. package/dashboard/.next/static/chunks/4938.03f6d04dabf38745.js +10 -0
  123. package/dashboard/.next/static/chunks/5112.0757c2b0c285e62e.js +1 -0
  124. package/dashboard/.next/static/chunks/5199.c83ea7efb0eec705.js +11 -0
  125. package/dashboard/.next/static/chunks/530.849957a8907eb288.js +1 -0
  126. package/dashboard/.next/static/chunks/5424.4e8ca0711a32bccf.js +7 -0
  127. package/dashboard/.next/static/chunks/55.a593a78be9714679.js +1 -0
  128. package/dashboard/.next/static/chunks/5535.6cd0bd8d368d8902.js +4 -0
  129. package/dashboard/.next/static/chunks/5626.7d4e93d7acbeffc9.js +10 -0
  130. package/dashboard/.next/static/chunks/5775.a0d7c1b1e89b9a93.js +9 -0
  131. package/dashboard/.next/static/chunks/6118.266956b3333b1d7a.js +9 -0
  132. package/dashboard/.next/static/chunks/6121.a2e6d93720b1205e.js +77 -0
  133. package/dashboard/.next/static/chunks/6853.d3ad43614e8ca0ab.js +1 -0
  134. package/dashboard/.next/static/chunks/6951.02a3a158d02158c9.js +5 -0
  135. package/dashboard/.next/static/chunks/6970.013f24568c87d918.js +11 -0
  136. package/dashboard/.next/static/chunks/7013.39d41e82b37be63b.js +9 -0
  137. package/dashboard/.next/static/chunks/7107.1c5412197912b8ed.js +8 -0
  138. package/dashboard/.next/static/chunks/7508.dd60e2d06d149f5f.js +9 -0
  139. package/dashboard/.next/static/chunks/7524.0fde4c61553d1491.js +3 -0
  140. package/dashboard/.next/static/chunks/7834-47f318a04a05688f.js +1 -0
  141. package/dashboard/.next/static/chunks/8317.d0b3eddef4cae0d5.js +1 -0
  142. package/dashboard/.next/static/chunks/838.2b2aa006519ba44c.js +10 -0
  143. package/dashboard/.next/static/chunks/8398.924fd8f4c83417c0.js +7 -0
  144. package/dashboard/.next/static/chunks/8428b36f.8ac4e67061c01307.js +34 -0
  145. package/dashboard/.next/static/chunks/8514.85ccbbea8ab21d04.js +5 -0
  146. package/dashboard/.next/static/chunks/8538.5f7ebe76c4b63162.js +1 -0
  147. package/dashboard/.next/static/chunks/8687.9406baa8b5601fd0.js +1 -0
  148. package/dashboard/.next/static/chunks/8721.47346e2cb6412376.js +10 -0
  149. package/dashboard/.next/static/chunks/8770.4f544bd1a6f03a62.js +8 -0
  150. package/dashboard/.next/static/chunks/8812.3d96fd54dba566f8.js +9 -0
  151. package/dashboard/.next/static/chunks/8962.d22aa67a97970dd8.js +1 -0
  152. package/dashboard/.next/static/chunks/8986.b327224b83f4399a.js +5 -0
  153. package/dashboard/.next/static/chunks/9271.5f66c19a8ee1ff36.js +10 -0
  154. package/dashboard/.next/static/chunks/9282.f8d01442bab4c0da.js +2 -0
  155. package/dashboard/.next/static/chunks/9366.0ec24a0791b9b00f.js +1 -0
  156. package/dashboard/.next/static/chunks/9707.5cd7d2ee933a4af5.js +6 -0
  157. package/dashboard/.next/static/chunks/9716.15fffc0b0038601d.js +4 -0
  158. package/dashboard/.next/static/chunks/9791.e3b3f5a367f63c8a.js +1 -0
  159. package/dashboard/.next/static/chunks/9820.8c1efad5260e8137.js +1 -0
  160. package/dashboard/.next/static/chunks/985.50150e9eaa4bde33.js +39 -0
  161. package/dashboard/.next/static/chunks/997.56901b86e1b8a87b.js +8 -0
  162. package/dashboard/.next/static/chunks/app/changes/page-f8a860034221cad4.js +1 -0
  163. package/dashboard/.next/static/chunks/app/issues/page-da4da93188c414a6.js +1 -0
  164. package/dashboard/.next/static/chunks/app/layout-27a9da4610423c1e.js +1 -0
  165. package/dashboard/.next/static/chunks/app/model/page-9680e22fdd6ddb81.js +1 -0
  166. package/dashboard/.next/static/chunks/app/page-0e67750d99fb2836.js +1 -0
  167. package/dashboard/.next/static/chunks/app/report/page-b56b1db9b9dcf2b6.js +1 -0
  168. package/dashboard/.next/static/chunks/app/review/page-3ef69f0e0badd333.js +1 -0
  169. package/dashboard/.next/static/chunks/c75e29e3.d91220f782934d80.js +1 -0
  170. package/dashboard/.next/static/chunks/{main-cc3a889b25e9aa68.js → main-9c95a7ffedc7afb4.js} +1 -1
  171. package/dashboard/.next/static/chunks/webpack-6da70e4f9fcf1799.js +1 -0
  172. package/dashboard/.next/static/css/ceafd91ca8dd753d.css +3 -0
  173. package/dashboard/.next/static/css/e4aad1f9c715b79a.css +1 -0
  174. package/dashboard/.next/static/media/Assistant-Bold.c8f39f24.woff2 +0 -0
  175. package/dashboard/.next/static/media/Assistant-Medium.1e75d8e6.woff2 +0 -0
  176. package/dashboard/.next/static/media/Assistant-Regular.7acbabb8.woff2 +0 -0
  177. package/dashboard/.next/static/media/Assistant-SemiBold.167acbf8.woff2 +0 -0
  178. package/dashboard/app/api/code/route.ts +26 -20
  179. package/dashboard/app/api/comments/route.ts +158 -0
  180. package/dashboard/app/api/diagrams/[name]/export/route.ts +26 -0
  181. package/dashboard/app/api/diagrams/[name]/resolve/route.ts +25 -0
  182. package/dashboard/app/api/diagrams/[name]/route.ts +37 -0
  183. package/dashboard/app/api/figures/[name]/route.ts +15 -0
  184. package/dashboard/app/api/focus/route.ts +35 -0
  185. package/dashboard/app/api/invariants/[id]/route.ts +35 -0
  186. package/dashboard/app/api/issues/[id]/revert-auto/route.ts +18 -0
  187. package/dashboard/app/api/nav/route.ts +120 -0
  188. package/dashboard/app/api/palette/route.ts +68 -0
  189. package/dashboard/app/api/progress/route.ts +54 -23
  190. package/dashboard/app/api/xref/route.ts +30 -0
  191. package/dashboard/app/changes/ChangesClient.tsx +730 -356
  192. package/dashboard/app/changes/page.tsx +27 -19
  193. package/dashboard/app/excalidraw-assets/[...path]/route.ts +56 -0
  194. package/dashboard/app/globals.css +231 -77
  195. package/dashboard/app/issues/BoardClient.tsx +817 -0
  196. package/dashboard/app/issues/page.tsx +27 -272
  197. package/dashboard/app/layout.tsx +32 -17
  198. package/dashboard/app/model/ModelClient.tsx +1303 -0
  199. package/dashboard/app/model/page.tsx +98 -0
  200. package/dashboard/app/page.tsx +191 -277
  201. package/dashboard/app/report/ReportClient.tsx +147 -74
  202. package/dashboard/app/report/page.tsx +25 -14
  203. package/dashboard/app/review/ReviewClient.tsx +1180 -0
  204. package/dashboard/app/review/page.tsx +93 -0
  205. package/dashboard/components/AutoRefresh.tsx +22 -19
  206. package/dashboard/components/CodeComments.tsx +303 -0
  207. package/dashboard/components/CodeNav.tsx +523 -0
  208. package/dashboard/components/CodeReference.tsx +92 -99
  209. package/dashboard/components/CodeViewer.tsx +526 -0
  210. package/dashboard/components/CommandPalette.tsx +141 -66
  211. package/dashboard/components/DiagramCanvas.tsx +275 -0
  212. package/dashboard/components/DianeNote.tsx +244 -0
  213. package/dashboard/components/LiveStatus.tsx +30 -68
  214. package/dashboard/components/MarkdownRenderer.tsx +34 -32
  215. package/dashboard/components/RecordButton.tsx +132 -0
  216. package/dashboard/components/ui/Button.tsx +39 -0
  217. package/dashboard/components/ui/Chip.tsx +37 -0
  218. package/dashboard/components/ui/EmptyState.tsx +31 -0
  219. package/dashboard/components/ui/Icons.tsx +126 -0
  220. package/dashboard/components/ui/Inspector.tsx +122 -0
  221. package/dashboard/components/ui/Kbd.tsx +15 -0
  222. package/dashboard/components/ui/ListRow.tsx +92 -0
  223. package/dashboard/components/ui/LocalTime.tsx +14 -0
  224. package/dashboard/components/ui/ProgressRing.tsx +54 -0
  225. package/dashboard/components/ui/ResizeHandle.tsx +93 -0
  226. package/dashboard/components/ui/RiskMeter.tsx +27 -0
  227. package/dashboard/components/ui/SearchField.tsx +55 -0
  228. package/dashboard/components/ui/SegmentedControl.tsx +71 -0
  229. package/dashboard/components/ui/SeverityDot.tsx +57 -0
  230. package/dashboard/components/ui/Sidebar.tsx +236 -0
  231. package/dashboard/components/ui/SplitView.tsx +122 -0
  232. package/dashboard/components/ui/StateGlyph.tsx +66 -0
  233. package/dashboard/components/ui/Toast.tsx +91 -0
  234. package/dashboard/lib/api.ts +17 -0
  235. package/dashboard/lib/cn.ts +4 -0
  236. package/dashboard/lib/data.ts +2 -21
  237. package/dashboard/lib/finding-markdown.ts +1 -1
  238. package/dashboard/lib/focus.ts +42 -0
  239. package/dashboard/lib/hotkeys.ts +41 -0
  240. package/dashboard/lib/inline-markdown.test.ts +11 -0
  241. package/dashboard/lib/live.ts +32 -0
  242. package/dashboard/lib/pane-width.ts +36 -0
  243. package/dashboard/lib/server/board.ts +229 -0
  244. package/dashboard/lib/server/diagrams.ts +191 -0
  245. package/dashboard/lib/server/safe-path.ts +28 -0
  246. package/dashboard/lib/server/workspace.ts +113 -0
  247. package/dashboard/lib/server/xref.ts +42 -0
  248. package/dashboard/lib/solidity.test.ts +37 -0
  249. package/dashboard/lib/solidity.ts +191 -0
  250. package/dashboard/lib/source.ts +28 -0
  251. package/dashboard/lib/types.ts +164 -0
  252. package/dashboard/lib/url.ts +18 -0
  253. package/dashboard/lib/watcher.ts +31 -22
  254. package/dashboard/tailwind.config.ts +6 -3
  255. package/dist/analysis/code-model.d.ts.map +1 -1
  256. package/dist/analysis/code-model.js +4 -1
  257. package/dist/analysis/code-model.js.map +1 -1
  258. package/dist/analysis/diff.d.ts +12 -1
  259. package/dist/analysis/diff.d.ts.map +1 -1
  260. package/dist/analysis/diff.js +143 -0
  261. package/dist/analysis/diff.js.map +1 -1
  262. package/dist/commands/analyze.d.ts.map +1 -1
  263. package/dist/commands/analyze.js +17 -48
  264. package/dist/commands/analyze.js.map +1 -1
  265. package/dist/commands/claude.d.ts.map +1 -1
  266. package/dist/commands/claude.js +5 -0
  267. package/dist/commands/claude.js.map +1 -1
  268. package/dist/commands/dashboard.d.ts.map +1 -1
  269. package/dist/commands/dashboard.js +10 -2
  270. package/dist/commands/dashboard.js.map +1 -1
  271. package/dist/commands/diagram.d.ts +3 -0
  272. package/dist/commands/diagram.d.ts.map +1 -0
  273. package/dist/commands/diagram.js +71 -0
  274. package/dist/commands/diagram.js.map +1 -0
  275. package/dist/commands/diff.d.ts +4 -5
  276. package/dist/commands/diff.d.ts.map +1 -1
  277. package/dist/commands/diff.js +56 -17
  278. package/dist/commands/diff.js.map +1 -1
  279. package/dist/commands/doctor.d.ts.map +1 -1
  280. package/dist/commands/doctor.js +5 -18
  281. package/dist/commands/doctor.js.map +1 -1
  282. package/dist/commands/facts.d.ts +23 -0
  283. package/dist/commands/facts.d.ts.map +1 -0
  284. package/dist/commands/facts.js +121 -0
  285. package/dist/commands/facts.js.map +1 -0
  286. package/dist/commands/fix-review.d.ts +9 -0
  287. package/dist/commands/fix-review.d.ts.map +1 -0
  288. package/dist/commands/fix-review.js +367 -0
  289. package/dist/commands/fix-review.js.map +1 -0
  290. package/dist/commands/init.d.ts.map +1 -1
  291. package/dist/commands/init.js +51 -47
  292. package/dist/commands/init.js.map +1 -1
  293. package/dist/commands/issue.d.ts.map +1 -1
  294. package/dist/commands/issue.js +151 -2
  295. package/dist/commands/issue.js.map +1 -1
  296. package/dist/commands/mcp.d.ts +3 -0
  297. package/dist/commands/mcp.d.ts.map +1 -0
  298. package/dist/commands/mcp.js +11 -0
  299. package/dist/commands/mcp.js.map +1 -0
  300. package/dist/commands/model.d.ts +4 -0
  301. package/dist/commands/model.d.ts.map +1 -0
  302. package/dist/commands/model.js +275 -0
  303. package/dist/commands/model.js.map +1 -0
  304. package/dist/commands/note.d.ts.map +1 -1
  305. package/dist/commands/note.js +31 -1
  306. package/dist/commands/note.js.map +1 -1
  307. package/dist/commands/review.d.ts +4 -0
  308. package/dist/commands/review.d.ts.map +1 -0
  309. package/dist/commands/review.js +164 -0
  310. package/dist/commands/review.js.map +1 -0
  311. package/dist/core/comments.d.ts +59 -0
  312. package/dist/core/comments.d.ts.map +1 -0
  313. package/dist/core/comments.js +263 -0
  314. package/dist/core/comments.js.map +1 -0
  315. package/dist/core/config.d.ts.map +1 -1
  316. package/dist/core/config.js +0 -1
  317. package/dist/core/config.js.map +1 -1
  318. package/dist/core/dedup.d.ts +56 -0
  319. package/dist/core/dedup.d.ts.map +1 -0
  320. package/dist/core/dedup.js +208 -0
  321. package/dist/core/dedup.js.map +1 -0
  322. package/dist/core/errors.d.ts +1 -1
  323. package/dist/core/errors.d.ts.map +1 -1
  324. package/dist/core/errors.js +0 -15
  325. package/dist/core/errors.js.map +1 -1
  326. package/dist/core/external-tools.d.ts +0 -14
  327. package/dist/core/external-tools.d.ts.map +1 -1
  328. package/dist/core/external-tools.js +2 -52
  329. package/dist/core/external-tools.js.map +1 -1
  330. package/dist/core/fix-review.d.ts +54 -0
  331. package/dist/core/fix-review.d.ts.map +1 -0
  332. package/dist/core/fix-review.js +98 -0
  333. package/dist/core/fix-review.js.map +1 -0
  334. package/dist/core/fuzz-sync.d.ts +93 -0
  335. package/dist/core/fuzz-sync.d.ts.map +1 -0
  336. package/dist/core/fuzz-sync.js +516 -0
  337. package/dist/core/fuzz-sync.js.map +1 -0
  338. package/dist/core/git.d.ts +7 -0
  339. package/dist/core/git.d.ts.map +1 -1
  340. package/dist/core/git.js +42 -0
  341. package/dist/core/git.js.map +1 -1
  342. package/dist/core/issues.d.ts +32 -1
  343. package/dist/core/issues.d.ts.map +1 -1
  344. package/dist/core/issues.js +135 -3
  345. package/dist/core/issues.js.map +1 -1
  346. package/dist/core/mcp-config.d.ts +12 -0
  347. package/dist/core/mcp-config.d.ts.map +1 -0
  348. package/dist/core/mcp-config.js +29 -0
  349. package/dist/core/mcp-config.js.map +1 -0
  350. package/dist/core/model.d.ts +38 -0
  351. package/dist/core/model.d.ts.map +1 -0
  352. package/dist/core/model.js +160 -0
  353. package/dist/core/model.js.map +1 -0
  354. package/dist/core/notes.d.ts +2 -0
  355. package/dist/core/notes.d.ts.map +1 -1
  356. package/dist/core/notes.js +13 -3
  357. package/dist/core/notes.js.map +1 -1
  358. package/dist/core/review.d.ts +47 -0
  359. package/dist/core/review.d.ts.map +1 -1
  360. package/dist/core/review.js +177 -1
  361. package/dist/core/review.js.map +1 -1
  362. package/dist/core/rules.d.ts +12 -0
  363. package/dist/core/rules.d.ts.map +1 -0
  364. package/dist/core/rules.js +66 -0
  365. package/dist/core/rules.js.map +1 -0
  366. package/dist/core/schema.d.ts +4817 -2245
  367. package/dist/core/schema.d.ts.map +1 -1
  368. package/dist/core/schema.js +452 -113
  369. package/dist/core/schema.js.map +1 -1
  370. package/dist/core/scope.d.ts +8 -0
  371. package/dist/core/scope.d.ts.map +1 -0
  372. package/dist/core/scope.js +18 -0
  373. package/dist/core/scope.js.map +1 -0
  374. package/dist/diagrams/build.d.ts +18 -0
  375. package/dist/diagrams/build.d.ts.map +1 -0
  376. package/dist/diagrams/build.js +135 -0
  377. package/dist/diagrams/build.js.map +1 -0
  378. package/dist/diagrams/excalidraw.d.ts +27 -0
  379. package/dist/diagrams/excalidraw.d.ts.map +1 -0
  380. package/dist/diagrams/excalidraw.js +219 -0
  381. package/dist/diagrams/excalidraw.js.map +1 -0
  382. package/dist/diagrams/layout.d.ts +48 -0
  383. package/dist/diagrams/layout.d.ts.map +1 -0
  384. package/dist/diagrams/layout.js +686 -0
  385. package/dist/diagrams/layout.js.map +1 -0
  386. package/dist/facts/build.d.ts +23 -0
  387. package/dist/facts/build.d.ts.map +1 -0
  388. package/dist/facts/build.js +112 -0
  389. package/dist/facts/build.js.map +1 -0
  390. package/dist/facts/extract.d.ts +53 -0
  391. package/dist/facts/extract.d.ts.map +1 -0
  392. package/dist/facts/extract.js +635 -0
  393. package/dist/facts/extract.js.map +1 -0
  394. package/dist/facts/fallback.d.ts +7 -0
  395. package/dist/facts/fallback.d.ts.map +1 -0
  396. package/dist/facts/fallback.js +156 -0
  397. package/dist/facts/fallback.js.map +1 -0
  398. package/dist/facts/implementations.d.ts +29 -0
  399. package/dist/facts/implementations.d.ts.map +1 -0
  400. package/dist/facts/implementations.js +43 -0
  401. package/dist/facts/implementations.js.map +1 -0
  402. package/dist/facts/query.d.ts +35 -0
  403. package/dist/facts/query.d.ts.map +1 -0
  404. package/dist/facts/query.js +157 -0
  405. package/dist/facts/query.js.map +1 -0
  406. package/dist/facts/xref.d.ts +53 -0
  407. package/dist/facts/xref.d.ts.map +1 -0
  408. package/dist/facts/xref.js +282 -0
  409. package/dist/facts/xref.js.map +1 -0
  410. package/dist/index.js +14 -16
  411. package/dist/index.js.map +1 -1
  412. package/dist/mcp/server.d.ts +3 -0
  413. package/dist/mcp/server.d.ts.map +1 -0
  414. package/dist/mcp/server.js +400 -0
  415. package/dist/mcp/server.js.map +1 -0
  416. package/dist/skills/ai-audit/SKILL.md +16 -6
  417. package/dist/skills/ai-audit/UPSTREAM.md +9 -4
  418. package/dist/skills/ai-audit/references/hex-board.md +34 -46
  419. package/dist/skills/diane.md +26 -12
  420. package/dist/skills/fix-review.md +58 -0
  421. package/dist/skills/fuzz/LICENSE +21 -0
  422. package/dist/skills/fuzz/SKILL.md +655 -0
  423. package/dist/skills/fuzz/UPSTREAM.md +119 -0
  424. package/dist/skills/fuzz/agents/implementers/global-property-implementer.md +81 -0
  425. package/dist/skills/fuzz/agents/implementers/specific-property-implementer.md +121 -0
  426. package/dist/skills/fuzz/agents/invariant-discovery/adversarial-profit-maximizer.md +123 -0
  427. package/dist/skills/fuzz/agents/invariant-discovery/conservation-auditor.md +92 -0
  428. package/dist/skills/fuzz/agents/invariant-discovery/protocol-type-specialist.md +173 -0
  429. package/dist/skills/fuzz/agents/invariant-discovery/roundtrip-rounding-analyst.md +164 -0
  430. package/dist/skills/fuzz/agents/invariant-discovery/state-transition-mapper.md +92 -0
  431. package/dist/skills/fuzz/agents/invariant-discovery/synthesizer.md +261 -0
  432. package/dist/skills/fuzz/agents/protocol-analyzer.md +80 -0
  433. package/dist/skills/fuzz/agents/report-writer.md +135 -0
  434. package/dist/skills/fuzz/references/handler-patterns.md +222 -0
  435. package/dist/skills/fuzz/references/hex-invariants.md +102 -0
  436. package/dist/skills/fuzz/references/property-generation.md +149 -0
  437. package/dist/skills/fuzz/references/selection-policy.md +49 -0
  438. package/dist/skills/fuzz/references/setup-playbook.md +92 -0
  439. package/dist/skills/fuzz/references/template-map.md +121 -0
  440. package/dist/skills/fuzz/scripts/ensure_foundry.sh +125 -0
  441. package/dist/skills/fuzz/scripts/estimate_cost.js +157 -0
  442. package/dist/skills/fuzz/scripts/extract_abis.js +303 -0
  443. package/dist/skills/fuzz/scripts/fizz_sync.js +692 -0
  444. package/dist/skills/fuzz/scripts/generate_handlers.js +370 -0
  445. package/dist/skills/fuzz/scripts/generate_suite.js +254 -0
  446. package/dist/skills/fuzz/scripts/lib/log-viewer.js +332 -0
  447. package/dist/skills/fuzz/scripts/run_echidna.js +192 -0
  448. package/dist/skills/fuzz/scripts/run_medusa.js +329 -0
  449. package/dist/skills/fuzz/scripts/select_functions.js +637 -0
  450. package/dist/skills/fuzz/scripts/setup_fuzz_profile.sh +142 -0
  451. package/dist/skills/fuzz/templates/Actor.sol +63 -0
  452. package/dist/skills/fuzz/templates/Base.sol +121 -0
  453. package/dist/skills/fuzz/templates/FoundryTester.sol +29 -0
  454. package/dist/skills/fuzz/templates/FuzzTester.sol +11 -0
  455. package/dist/skills/fuzz/templates/Properties.sol +17 -0
  456. package/dist/skills/fuzz/templates/README.md +56 -0
  457. package/dist/skills/fuzz/templates/Snapshots.sol +26 -0
  458. package/dist/skills/fuzz/templates/echidna.yaml +18 -0
  459. package/dist/skills/fuzz/templates/handlers/Handlers.sol +13 -0
  460. package/dist/skills/fuzz/templates/medusa.json +93 -0
  461. package/dist/skills/fuzz/templates/utils/Clamp.sol +223 -0
  462. package/dist/skills/fuzz/templates/utils/DecimalPrinter.sol +63 -0
  463. package/dist/skills/fuzz/templates/utils/Deployer.sol +17 -0
  464. package/dist/skills/fuzz/templates/utils/EnumerableSet.sol +206 -0
  465. package/dist/skills/fuzz/templates/utils/Hevm.sol +62 -0
  466. package/dist/skills/fuzz/templates/utils/Logger.sol +619 -0
  467. package/dist/skills/fuzz/templates/utils/Math.sol +52 -0
  468. package/dist/skills/fuzz/templates/utils/MockERC20.sol +279 -0
  469. package/dist/skills/fuzz/templates/utils/PropertiesAsserts.sol +238 -0
  470. package/dist/skills/fuzz/templates/utils/StringUtils.sol +85 -0
  471. package/dist/skills/fuzz-convert/SKILL.md +249 -0
  472. package/dist/skills/fuzz-sync/SKILL.md +342 -0
  473. package/dist/skills/generate-poc.md +8 -26
  474. package/dist/skills/generate-report.md +17 -5
  475. package/dist/skills/ingest-aa-report.md +11 -30
  476. package/dist/skills/init-audit/SKILL.md +155 -0
  477. package/dist/skills/init-audit/references/agents/conformance-checker.md +36 -0
  478. package/dist/skills/init-audit/references/agents/contract-reader.md +59 -0
  479. package/dist/skills/init-audit/references/agents/diagram-composer.md +48 -0
  480. package/dist/skills/init-audit/references/agents/docs-extractor.md +26 -0
  481. package/dist/skills/init-audit/references/agents/prior-audit.md +32 -0
  482. package/dist/skills/init-audit/references/agents/regression-checker.md +28 -0
  483. package/dist/skills/init-audit/references/agents/skeptic.md +31 -0
  484. package/dist/skills/init-audit/references/agents/standards-checker.md +39 -0
  485. package/dist/skills/init-audit/references/agents/synthesizer.md +50 -0
  486. package/dist/skills/prevalidate.md +62 -0
  487. package/dist/skills/sync-issues.md +11 -25
  488. package/dist/skills/validate-all-findings.md +2 -2
  489. package/dist/skills/validate-finding.md +25 -24
  490. package/dist/skills/write-finding.md +6 -5
  491. package/dist/types/index.d.ts +16 -12
  492. package/dist/types/index.d.ts.map +1 -1
  493. package/package.json +5 -4
  494. package/dashboard/.next/server/app/access/page.js +0 -1
  495. package/dashboard/.next/server/app/access/page_client-reference-manifest.js +0 -1
  496. package/dashboard/.next/server/app/api/flows/route.js +0 -1
  497. package/dashboard/.next/server/app/api/mermaid/route.js +0 -1
  498. package/dashboard/.next/server/app/calls/page.js +0 -1
  499. package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +0 -1
  500. package/dashboard/.next/server/app/conformance/page.js +0 -1
  501. package/dashboard/.next/server/app/conformance/page.js.nft.json +0 -1
  502. package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +0 -1
  503. package/dashboard/.next/server/app/diagram/page.js +0 -1
  504. package/dashboard/.next/server/app/diagram/page.js.nft.json +0 -1
  505. package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +0 -1
  506. package/dashboard/.next/server/app/flows/page.js +0 -1
  507. package/dashboard/.next/server/app/flows/page.js.nft.json +0 -1
  508. package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +0 -1
  509. package/dashboard/.next/server/app/functions/page.js +0 -1
  510. package/dashboard/.next/server/app/functions/page.js.nft.json +0 -1
  511. package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +0 -1
  512. package/dashboard/.next/server/app/notes/page.js +0 -22
  513. package/dashboard/.next/server/app/notes/page.js.nft.json +0 -1
  514. package/dashboard/.next/server/app/notes/page_client-reference-manifest.js +0 -1
  515. package/dashboard/.next/server/app/progress/page.js +0 -1
  516. package/dashboard/.next/server/app/progress/page.js.nft.json +0 -1
  517. package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +0 -1
  518. package/dashboard/.next/server/app/stats/page.js +0 -1
  519. package/dashboard/.next/server/app/stats/page.js.nft.json +0 -1
  520. package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +0 -1
  521. package/dashboard/.next/server/chunks/530.js +0 -1
  522. package/dashboard/.next/server/chunks/622.js +0 -3
  523. package/dashboard/.next/server/chunks/665.js +0 -13
  524. package/dashboard/.next/server/chunks/939.js +0 -1
  525. package/dashboard/.next/static/chunks/3017.4a5312e3c20a173f.js +0 -1
  526. package/dashboard/.next/static/chunks/7397-37adf76cad543297.js +0 -1
  527. package/dashboard/.next/static/chunks/7973.e34032723285a616.js +0 -79
  528. package/dashboard/.next/static/chunks/8452-6d77fa353402422c.js +0 -13
  529. package/dashboard/.next/static/chunks/8928-fc049decdfbdaa6d.js +0 -1
  530. package/dashboard/.next/static/chunks/app/access/page-f8403cbdfc1c176b.js +0 -1
  531. package/dashboard/.next/static/chunks/app/calls/page-41f20d01e12382ef.js +0 -1
  532. package/dashboard/.next/static/chunks/app/changes/page-82bf8b6f48cdc506.js +0 -1
  533. package/dashboard/.next/static/chunks/app/conformance/page-6bb8e3b372e38098.js +0 -1
  534. package/dashboard/.next/static/chunks/app/diagram/page-469cd7a6f183efba.js +0 -1
  535. package/dashboard/.next/static/chunks/app/flows/page-7872dd9141ba0b07.js +0 -1
  536. package/dashboard/.next/static/chunks/app/functions/page-5847bcb77a8e7edf.js +0 -1
  537. package/dashboard/.next/static/chunks/app/issues/page-1ffc64fe40439002.js +0 -1
  538. package/dashboard/.next/static/chunks/app/layout-6c6d2a0fd7c989d3.js +0 -1
  539. package/dashboard/.next/static/chunks/app/notes/page-8bcaa52304500098.js +0 -1
  540. package/dashboard/.next/static/chunks/app/page-d63800ddb072b77b.js +0 -1
  541. package/dashboard/.next/static/chunks/app/progress/page-e26554f655a62eef.js +0 -1
  542. package/dashboard/.next/static/chunks/app/report/page-18c04fb2f193b020.js +0 -1
  543. package/dashboard/.next/static/chunks/app/stats/page-67ff59fd69bed651.js +0 -1
  544. package/dashboard/.next/static/chunks/webpack-4de0e79bdd6a0418.js +0 -1
  545. package/dashboard/.next/static/css/1112cea2260b3926.css +0 -3
  546. package/dashboard/app/access/AccessClient.tsx +0 -402
  547. package/dashboard/app/access/ReadOnlyFunctions.tsx +0 -114
  548. package/dashboard/app/access/page.tsx +0 -125
  549. package/dashboard/app/api/flows/route.ts +0 -32
  550. package/dashboard/app/api/mermaid/route.ts +0 -25
  551. package/dashboard/app/calls/CallsClient.tsx +0 -170
  552. package/dashboard/app/calls/page.tsx +0 -57
  553. package/dashboard/app/conformance/ConformanceTable.tsx +0 -214
  554. package/dashboard/app/conformance/page.tsx +0 -186
  555. package/dashboard/app/diagram/page.tsx +0 -65
  556. package/dashboard/app/flows/page.tsx +0 -102
  557. package/dashboard/app/functions/FunctionsClient.tsx +0 -167
  558. package/dashboard/app/functions/page.tsx +0 -178
  559. package/dashboard/app/issues/IssuesBoardClient.tsx +0 -813
  560. package/dashboard/app/notes/NotesClient.tsx +0 -706
  561. package/dashboard/app/notes/page.tsx +0 -47
  562. package/dashboard/app/progress/ProgressClient.tsx +0 -354
  563. package/dashboard/app/progress/page.tsx +0 -127
  564. package/dashboard/app/stats/StatsClient.tsx +0 -452
  565. package/dashboard/app/stats/page.tsx +0 -50
  566. package/dashboard/components/ConfidenceBadge.tsx +0 -53
  567. package/dashboard/components/DashboardLayout.tsx +0 -510
  568. package/dashboard/components/FilterableTable.tsx +0 -293
  569. package/dashboard/components/MermaidViewer.tsx +0 -267
  570. package/dashboard/components/NotYetGenerated.tsx +0 -32
  571. package/dashboard/components/SeverityBadge.tsx +0 -28
  572. package/dashboard/components/SignalBars.tsx +0 -27
  573. package/dashboard/components/SortableTable.tsx +0 -122
  574. package/dashboard/lib/conformance-tokens.ts +0 -49
  575. package/dist/skills/init-audit.md +0 -386
  576. /package/dashboard/.next/server/app/api/{flows → xref}/route.js.nft.json +0 -0
  577. /package/dashboard/.next/server/app/{api/mermaid → excalidraw-assets/[...path]}/route.js.nft.json +0 -0
  578. /package/dashboard/.next/static/{z5XBev05xDAkDrxWxAjNu → bGV1ry1vvIbM5b506eVBR}/_buildManifest.js +0 -0
  579. /package/dashboard/.next/static/{z5XBev05xDAkDrxWxAjNu → bGV1ry1vvIbM5b506eVBR}/_ssgManifest.js +0 -0
  580. /package/dashboard/.next/static/chunks/{3205-47d09be47325709f.js → 3205-fd963acf2fdfd080.js} +0 -0
  581. /package/dashboard/.next/static/chunks/{3924-88d849290406ee6f.js → 3924-f1f85ccc7d59d7ab.js} +0 -0
  582. /package/dashboard/.next/static/chunks/{618f8807-69fc7bb97c2b87c1.js → 618f8807-fbb1466bc29c17c6.js} +0 -0
  583. /package/dashboard/.next/static/chunks/{7498-d1814d68ba346d13.js → 7498-7cf464d8af69cd0a.js} +0 -0
  584. /package/dashboard/.next/static/chunks/app/_not-found/{page-c299b935209993df.js → page-5ff5d54b6fd6f17e.js} +0 -0
@@ -0,0 +1,370 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * generate_handlers.js
4
+ *
5
+ * Reads entry-point-selection.json and generates handler files with
6
+ * pre-populated function signatures (clamped + unclamped) for each
7
+ * selected contract. Replaces the empty stubs that generate_suite.js
8
+ * creates so the LLM only needs to fill in body logic — not discover
9
+ * signatures, types, or naming conventions.
10
+ *
11
+ * Usage:
12
+ * node generate_handlers.js <PROJECT_ROOT> [options]
13
+ *
14
+ * Options:
15
+ * --suite-dir <dir> Suite directory (default: test/fizz)
16
+ * --meta-dir <dir> Metadata directory (default: .hex/fuzz/fizz_data)
17
+ * --selection <path> Entry-point selection file
18
+ * --force Overwrite handlers that already contain user edits
19
+ */
20
+
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+
24
+ // ――――――――――――――――――――――――― Argument parsing ―――――――――――――――――――――――――
25
+
26
+ const args = process.argv.slice(2);
27
+ if (args.length === 0 || args[0] === '--help') {
28
+ console.log(
29
+ 'Usage: node generate_handlers.js <PROJECT_ROOT> ' +
30
+ '[--suite-dir <dir>] [--meta-dir <dir>] [--selection <path>] [--force]'
31
+ );
32
+ process.exit(0);
33
+ }
34
+
35
+ const projectRoot = path.resolve(args[0]);
36
+ let suiteRelDir = path.join('test', 'fizz');
37
+ let metaRelDir = '.hex/fuzz/fizz_data'; // Hex: was 'fizz_data'
38
+ let selectionPath = '';
39
+ let force = false;
40
+
41
+ for (let i = 1; i < args.length; i++) {
42
+ if (args[i] === '--suite-dir' && args[i + 1]) { suiteRelDir = args[++i]; }
43
+ else if (args[i] === '--meta-dir' && args[i + 1]) { metaRelDir = args[++i]; }
44
+ else if (args[i] === '--selection' && args[i + 1]) { selectionPath = path.resolve(args[++i]); }
45
+ else if (args[i] === '--force') { force = true; }
46
+ }
47
+
48
+ const suiteDir = path.join(projectRoot, suiteRelDir);
49
+ const metaDir = path.join(projectRoot, metaRelDir);
50
+ if (!selectionPath) {
51
+ selectionPath = path.join(metaDir, 'entry-point-selection.json');
52
+ }
53
+
54
+ // ――――――――――――――――――――――――― Type mapping ―――――――――――――――――――――――――
55
+
56
+ /**
57
+ * Reference-type keywords that require a `memory` data-location qualifier
58
+ * when used as function parameters in Solidity ≥0.5.
59
+ */
60
+ const MEMORY_TYPES = new Set(['bytes', 'string']);
61
+
62
+ /**
63
+ * Convert a contracts.json input descriptor to a Solidity parameter string.
64
+ *
65
+ * contracts.json stores:
66
+ * type – simplified ABI type ('array', 'contract', 'enum', or the raw type)
67
+ * internalType – Solidity-level type without 'struct '/'contract '/'enum ' prefix
68
+ * name – parameter name (may be empty)
69
+ */
70
+ function toSolidityParam(input, index) {
71
+ const name = input.name || `_arg${index}`;
72
+ const { type, internalType } = input;
73
+
74
+ // Contracts are address at the ABI level
75
+ if (type === 'contract') return `address ${name}`;
76
+
77
+ // Enums encode as uint8 at the ABI level
78
+ if (type === 'enum') return `uint8 ${name}`;
79
+
80
+ // Arrays — internalType has the real Solidity type (e.g. "uint256[]")
81
+ if (type === 'array') return `${internalType} memory ${name}`;
82
+
83
+ // Tuples (structs) — internalType has the struct path (e.g. "MyLib.MyStruct")
84
+ if (type === 'tuple') return `${internalType} memory ${name}`;
85
+
86
+ // Reference types that need 'memory'
87
+ if (MEMORY_TYPES.has(type)) return `${type} memory ${name}`;
88
+
89
+ // Value types — pass through (uint256, int128, address, bool, bytes32, …)
90
+ return `${type} ${name}`;
91
+ }
92
+
93
+ /**
94
+ * Return just the name portion of a parameter for use in call arguments.
95
+ */
96
+ function paramName(input, index) {
97
+ return input.name || `_arg${index}`;
98
+ }
99
+
100
+ // ――――――――――――――――――――――――― Helper utilities ―――――――――――――――――――――――――
101
+
102
+ /** Lowercase the first character of a string. */
103
+ function lcFirst(s) {
104
+ if (!s) return s;
105
+ return s.charAt(0).toLowerCase() + s.slice(1);
106
+ }
107
+
108
+ // ――――――――――――――――――――――――― Stub detection ―――――――――――――――――――――――――
109
+
110
+ /**
111
+ * Return true if the file looks like an unmodified stub from generate_suite.js:
112
+ * it has no function definitions between the Clamped / Unclamped markers.
113
+ */
114
+ function isStubHandler(filePath) {
115
+ if (!fs.existsSync(filePath)) return true; // treat missing as writable
116
+ const content = fs.readFileSync(filePath, 'utf8');
117
+ // Strip single-line comments to avoid matching "function" inside comments
118
+ const stripped = content.replace(/\/\/.*$/gm, '');
119
+ // If there are no `function ` keywords the file is still a bare stub
120
+ return !/\bfunction\s+\w+/.test(stripped);
121
+ }
122
+
123
+ // ――――――――――――――――――――――――― Handler generation ―――――――――――――――――――――――――
124
+
125
+ /**
126
+ * Build a complete handler Solidity file for a single contract from the
127
+ * entry-point-selection data.
128
+ */
129
+ const ADDRESS_TYPES = new Set(['address', 'contract']);
130
+
131
+ /**
132
+ * Build the dispatcher parameter list and a per-function arg-mapping for secondary functions.
133
+ *
134
+ * Strategy: numeric/bool/enum/other value types share a pool of uint256 slots; address/contract
135
+ * types share a separate pool of address slots. For each function the max pool usage across all
136
+ * secondary functions determines the total slot count. Slots are ordered: uint256 slots first,
137
+ * then address slots (matching the handler-patterns.md example).
138
+ *
139
+ * Returns:
140
+ * { paramStr, slotCount, funcArgExprs }
141
+ * - paramStr — Solidity parameter string for the dispatcher (after `uint8 selector, `)
142
+ * - slotCount — total number of generic args (uint256 + address)
143
+ * - funcArgExprs(func) — function that returns the call-argument expression array for a given func
144
+ */
145
+ function buildDispatcherSignature(secondaryFuncs) {
146
+ let maxUint256 = 0;
147
+ let maxAddress = 0;
148
+
149
+ // Count max slots of each kind needed by any single secondary function
150
+ for (const func of secondaryFuncs) {
151
+ let u = 0, a = 0;
152
+ for (const inp of func.inputs) {
153
+ if (ADDRESS_TYPES.has(inp.type)) a++;
154
+ else u++;
155
+ }
156
+ if (u > maxUint256) maxUint256 = u;
157
+ if (a > maxAddress) maxAddress = a;
158
+ }
159
+
160
+ // Build param list: arg0..argN-1 are uint256, argN..argM are address
161
+ const params = [];
162
+ for (let i = 0; i < maxUint256; i++) params.push(`uint256 arg${i}`);
163
+ for (let i = 0; i < maxAddress; i++) params.push(`address arg${maxUint256 + i}`);
164
+ const paramStr = params.join(', ');
165
+
166
+ function funcArgExprs(func) {
167
+ let uIdx = 0, aIdx = 0;
168
+ return func.inputs.map(inp => {
169
+ if (ADDRESS_TYPES.has(inp.type)) {
170
+ return `arg${maxUint256 + aIdx++}`;
171
+ }
172
+ const slot = `arg${uIdx++}`;
173
+ if (inp.type === 'bool') return `${slot} > 0`;
174
+ if (inp.type === 'enum') return `uint8(${slot})`;
175
+ if (/^uint\d+$/.test(inp.type) && inp.type !== 'uint256') return `${inp.type}(${slot})`;
176
+ return slot;
177
+ });
178
+ }
179
+
180
+ return { paramStr, funcArgExprs };
181
+ }
182
+
183
+ function buildHandler(contract) {
184
+ const contractName = contract.name;
185
+ const instanceName = lcFirst(contractName);
186
+ const functions = contract.functions || [];
187
+
188
+ const primaryFuncs = functions.filter(f => f.tier !== 'secondary');
189
+ const secondaryFuncs = functions.filter(f => f.tier === 'secondary');
190
+
191
+ const clampedLines = [];
192
+ const unclampedLines = [];
193
+
194
+ for (const func of primaryFuncs) {
195
+ const prefix = `${instanceName}_${func.name}`;
196
+ const isPayable = func.stateMutability === 'payable';
197
+
198
+ // --- Build parameter strings ---
199
+ const paramDecls = func.inputs.map((inp, i) => toSolidityParam(inp, i));
200
+ const paramNames = func.inputs.map((inp, i) => paramName(inp, i));
201
+ const paramStr = paramDecls.join(', ');
202
+ const argStr = paramNames.join(', ');
203
+
204
+ // --- Unclamped function ---
205
+ const payableKw = isPayable ? ' payable' : '';
206
+ const callValue = isPayable ? `{value: msg.value}` : '';
207
+ const callHint = `${instanceName}.${func.name}${callValue}(${argStr})`;
208
+
209
+ unclampedLines.push(
210
+ ` function ${prefix}(${paramStr}) public${payableKw} asActor {`,
211
+ ` // TODO: wire call — ${callHint};`,
212
+ ` }`,
213
+ '',
214
+ );
215
+
216
+ // --- Clamped function ---
217
+ const clampedParamStr = isPayable && func.inputs.length === 0
218
+ ? 'uint256 ethAmount'
219
+ : paramStr;
220
+
221
+ const forwardArgs = isPayable && func.inputs.length === 0
222
+ ? ''
223
+ : argStr;
224
+
225
+ clampedLines.push(
226
+ ` function ${prefix}_clamped(${clampedParamStr}) public {`,
227
+ );
228
+
229
+ // Add per-type clamping hints
230
+ for (const inp of func.inputs) {
231
+ const name = inp.name || `_arg${func.inputs.indexOf(inp)}`;
232
+ if (inp.type === 'uint256' || inp.type === 'uint128' || inp.type === 'uint64' || inp.type === 'uint32' || inp.type === 'uint8') {
233
+ clampedLines.push(` // TODO: clamp ${name} — e.g. ${name} = clampBetween(${name}, min, max);`);
234
+ } else if (inp.type === 'address') {
235
+ clampedLines.push(` // TODO: clamp ${name} — e.g. ${name} = toActor(${name});`);
236
+ }
237
+ }
238
+
239
+ if (isPayable && func.inputs.length === 0) {
240
+ clampedLines.push(
241
+ ` // TODO: clamp ethAmount and forward with value`,
242
+ ` ${prefix}();`,
243
+ );
244
+ } else {
245
+ clampedLines.push(
246
+ ` ${prefix}(${forwardArgs});`,
247
+ );
248
+ }
249
+
250
+ clampedLines.push(` }`, '');
251
+ }
252
+
253
+ // --- Secondary functions: individual unclamped stubs + dispatcher ---
254
+ if (secondaryFuncs.length > 0) {
255
+ const { paramStr: dispParamStr, funcArgExprs } = buildDispatcherSignature(secondaryFuncs);
256
+
257
+ // Individual unclamped stubs for secondary functions (internal, prefixed with _)
258
+ for (const func of secondaryFuncs) {
259
+ const prefix = `_${instanceName}_${func.name}`;
260
+ const isPayable = func.stateMutability === 'payable';
261
+ const paramDecls = func.inputs.map((inp, i) => toSolidityParam(inp, i));
262
+ const paramNames = func.inputs.map((inp, i) => paramName(inp, i));
263
+ const funcParamStr = paramDecls.join(', ');
264
+ const argStr = paramNames.join(', ');
265
+ const payableKw = isPayable ? ' payable' : '';
266
+ const callValue = isPayable ? `{value: msg.value}` : '';
267
+ const callHint = `${instanceName}.${func.name}${callValue}(${argStr})`;
268
+
269
+ unclampedLines.push(
270
+ ` function ${prefix}(${funcParamStr}) internal${payableKw} {`,
271
+ ` // TODO: wire call — ${callHint};`,
272
+ ` }`,
273
+ '',
274
+ );
275
+ }
276
+
277
+ // Dispatcher function — last in the clamped section
278
+ const dispatcherFullParams = dispParamStr ? `uint8 selector, ${dispParamStr}` : `uint8 selector`;
279
+ const n = secondaryFuncs.length;
280
+
281
+ clampedLines.push(
282
+ ` function ${instanceName}_secondary(${dispatcherFullParams}) public {`,
283
+ ` selector = uint8(selector % ${n});`,
284
+ );
285
+
286
+ secondaryFuncs.forEach((func, idx) => {
287
+ const prefix = `_${instanceName}_${func.name}`;
288
+ const args = funcArgExprs(func);
289
+ const callExpr = `${prefix}(${args.join(', ')})`;
290
+ if (idx === 0) {
291
+ clampedLines.push(` if (selector == 0) ${callExpr};`);
292
+ } else if (idx === n - 1) {
293
+ clampedLines.push(` else ${callExpr};`);
294
+ } else {
295
+ clampedLines.push(` else if (selector == ${idx}) ${callExpr};`);
296
+ }
297
+ });
298
+
299
+ clampedLines.push(` }`, '');
300
+ }
301
+
302
+ // Remove trailing blank line from each section
303
+ if (clampedLines.length && clampedLines[clampedLines.length - 1] === '') clampedLines.pop();
304
+ if (unclampedLines.length && unclampedLines[unclampedLines.length - 1] === '') unclampedLines.pop();
305
+
306
+ return `// SPDX-License-Identifier: MIT
307
+ pragma solidity >=0.6.2 <0.9.0;
308
+
309
+ import "../Base.sol";
310
+ import {Properties} from "../Properties.sol";
311
+
312
+ /// @notice Handles the interaction with ${contractName}
313
+ abstract contract ${contractName}Handler is Properties {
314
+
315
+ // ――――――――――――――――――――――――― Clamped ――――――――――――――――――――――――――
316
+
317
+ ${clampedLines.join('\n')}
318
+
319
+ // ―――――――――――――――――――――――― Unclamped ―――――――――――――――――――――――――
320
+
321
+ ${unclampedLines.join('\n')}
322
+ }
323
+ `;
324
+ }
325
+
326
+ // ――――――――――――――――――――――――――――― Main ――――――――――――――――――――――――――――――
327
+
328
+ function main() {
329
+ if (!fs.existsSync(selectionPath)) {
330
+ console.error(`Selection file not found: ${selectionPath}`);
331
+ console.error('Run select_functions.js first.');
332
+ process.exit(1);
333
+ }
334
+
335
+ const selection = JSON.parse(fs.readFileSync(selectionPath, 'utf8'));
336
+ if (!Array.isArray(selection) || selection.length === 0) {
337
+ console.error('No contracts in selection file.');
338
+ process.exit(1);
339
+ }
340
+
341
+ const handlersDir = path.join(suiteDir, 'handlers');
342
+ fs.mkdirSync(handlersDir, { recursive: true });
343
+
344
+ let written = 0;
345
+ let skipped = 0;
346
+
347
+ for (const contract of selection) {
348
+ if (!contract || !contract.name || !Array.isArray(contract.functions) || contract.functions.length === 0) {
349
+ continue;
350
+ }
351
+
352
+ const handlerPath = path.join(handlersDir, `${contract.name}Handler.sol`);
353
+ const relPath = path.relative(projectRoot, handlerPath);
354
+
355
+ if (!force && fs.existsSync(handlerPath) && !isStubHandler(handlerPath)) {
356
+ console.log(` [skip] ${relPath} (contains edits — use --force to overwrite)`);
357
+ skipped++;
358
+ continue;
359
+ }
360
+
361
+ const content = buildHandler(contract);
362
+ fs.writeFileSync(handlerPath, content);
363
+ console.log(` [wrote] ${relPath} (${contract.functions.length} functions)`);
364
+ written++;
365
+ }
366
+
367
+ console.log(`\nDone: ${written} handler(s) written, ${skipped} skipped.`);
368
+ }
369
+
370
+ main();
@@ -0,0 +1,254 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * generate_suite.js
4
+ *
5
+ * Copies the full template scaffold and fuzzer config into the target
6
+ * project's fuzzing directory, including static utility helpers such as
7
+ * MockERC20. The copied files are then modified by the LLM in later
8
+ * steps with full protocol context.
9
+ *
10
+ * Usage:
11
+ * node generate_suite.js <PROJECT_ROOT> [--suite-dir <path>] [--meta-dir <path>] [--templates <path>] [--selection <path>]
12
+ *
13
+ * Defaults:
14
+ * --suite-dir test/fizz (relative to project root)
15
+ * --meta-dir .hex/fuzz/fizz_data (relative to project root)
16
+ * --fuzzing-dir deprecated alias for --suite-dir
17
+ * --templates <script_dir>/../templates
18
+ * --selection <meta-dir>/entry-point-selection.json
19
+ */
20
+
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+
24
+ // ――――――――――――――――――――――――― Argument parsing ―――――――――――――――――――――――――
25
+
26
+ const args = process.argv.slice(2);
27
+ if (args.length === 0 || args[0] === '--help') {
28
+ console.log('Usage: node generate_suite.js <PROJECT_ROOT> [--suite-dir <dir>] [--meta-dir <dir>] [--templates <dir>] [--selection <path>]');
29
+ process.exit(0);
30
+ }
31
+
32
+ const projectRoot = path.resolve(args[0]);
33
+ const scriptDir = __dirname;
34
+ let suiteRelDir = path.join('test', 'fizz');
35
+ let metaRelDir = '.hex/fuzz/fizz_data'; // Hex: was 'fizz_data'
36
+ let templatesDir = path.join(scriptDir, '..', 'templates');
37
+ let selectionPath = '';
38
+
39
+ for (let i = 1; i < args.length; i++) {
40
+ if (args[i] === '--suite-dir' && args[i + 1]) { suiteRelDir = args[++i]; }
41
+ else if (args[i] === '--meta-dir' && args[i + 1]) { metaRelDir = args[++i]; }
42
+ else if (args[i] === '--fuzzing-dir' && args[i + 1]) { suiteRelDir = args[++i]; }
43
+ else if (args[i] === '--templates' && args[i + 1]) { templatesDir = path.resolve(args[++i]); }
44
+ else if (args[i] === '--selection' && args[i + 1]) { selectionPath = path.resolve(args[++i]); }
45
+ }
46
+
47
+ const suiteDir = path.join(projectRoot, suiteRelDir);
48
+ const metaDir = path.join(projectRoot, metaRelDir);
49
+ if (!selectionPath) {
50
+ selectionPath = path.join(metaDir, 'entry-point-selection.json');
51
+ }
52
+
53
+ // ――――――――――――――――――――――――― Template copying ―――――――――――――――――――――――――
54
+
55
+ /**
56
+ * Recursively copy template files from src to dst, skipping existing files.
57
+ * This includes static utility helpers such as utils/MockERC20.sol.
58
+ */
59
+ function copyTemplates(src, dst, isRoot = false) {
60
+ const copied = [];
61
+ if (!fs.existsSync(dst)) {
62
+ fs.mkdirSync(dst, { recursive: true });
63
+ }
64
+
65
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
66
+ const srcPath = path.join(src, entry.name);
67
+ const dstPath = path.join(dst, entry.name);
68
+ const relativeSrcPath = path.relative(templatesDir, srcPath);
69
+
70
+ // Skip config files at root level — handled separately
71
+ if (isRoot && (entry.name === 'echidna.yaml' || entry.name === 'medusa.json')) continue;
72
+ if (relativeSrcPath === path.join('handlers', 'Handlers.sol')) continue;
73
+
74
+ if (entry.isDirectory()) {
75
+ copied.push(...copyTemplates(srcPath, dstPath));
76
+ } else if (entry.isFile()) {
77
+ if (fs.existsSync(dstPath)) {
78
+ console.log(` [exists] ${path.relative(projectRoot, dstPath)}`);
79
+ } else {
80
+ // 'fizz_data' is the placeholder the templates use, not the default meta dir (Hex).
81
+ const needsSubstitution = metaRelDir !== 'fizz_data' && entry.name === 'README.md';
82
+ if (needsSubstitution) {
83
+ const content = fs.readFileSync(srcPath, 'utf8').replaceAll('fizz_data', metaRelDir);
84
+ fs.writeFileSync(dstPath, content);
85
+ } else {
86
+ fs.copyFileSync(srcPath, dstPath);
87
+ }
88
+ copied.push(dstPath);
89
+ console.log(` [new] ${path.relative(projectRoot, dstPath)}`);
90
+ }
91
+ }
92
+ }
93
+ return copied;
94
+ }
95
+
96
+ // ――――――――――――――――――――― Config file placement ―――――――――――――――――――――――
97
+
98
+ function copyRootConfigs() {
99
+ for (const filename of ['echidna.yaml', 'medusa.json']) {
100
+ const src = path.join(templatesDir, filename);
101
+ const dst = path.join(projectRoot, filename);
102
+ if (!fs.existsSync(src)) continue;
103
+
104
+ if (fs.existsSync(dst)) {
105
+ console.log(` [exists] ${path.relative(projectRoot, dst)}`);
106
+ } else {
107
+ let content = fs.readFileSync(src, 'utf8');
108
+ // 'fizz_data' is the placeholder the templates use (Hex: the default meta dir is .hex/fuzz/fizz_data).
109
+ if (metaRelDir !== 'fizz_data') {
110
+ content = content.replaceAll('fizz_data', metaRelDir);
111
+ }
112
+ fs.writeFileSync(dst, content);
113
+ console.log(` [new] ${path.relative(projectRoot, dst)}`);
114
+ }
115
+ }
116
+ }
117
+
118
+ // ――――――――――――――――――――― Selection-driven handler generation ――――――――――――――――――
119
+
120
+ function readSelectedContracts() {
121
+ if (!fs.existsSync(selectionPath)) {
122
+ console.error(`Selection file not found: ${selectionPath}`);
123
+ console.error('Run select_functions.js first.');
124
+ process.exit(1);
125
+ }
126
+
127
+ const selection = JSON.parse(fs.readFileSync(selectionPath, 'utf8'));
128
+ if (!Array.isArray(selection)) {
129
+ console.error(`Invalid selection file: ${selectionPath}`);
130
+ console.error('Expected a JSON array of selected contracts.');
131
+ process.exit(1);
132
+ }
133
+
134
+ const uniqueContracts = [];
135
+ const seen = new Set();
136
+
137
+ for (const contract of selection) {
138
+ if (!contract || typeof contract.name !== 'string' || contract.name.length === 0) continue;
139
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(contract.name)) {
140
+ console.warn(` [skip] Invalid Solidity identifier: "${contract.name}"`);
141
+ continue;
142
+ }
143
+ if (seen.has(contract.name)) continue;
144
+ seen.add(contract.name);
145
+ uniqueContracts.push(contract.name);
146
+ }
147
+
148
+ if (uniqueContracts.length === 0) {
149
+ console.error(`No selected contracts found in: ${selectionPath}`);
150
+ process.exit(1);
151
+ }
152
+
153
+ return uniqueContracts;
154
+ }
155
+
156
+ function buildHandlerTemplate(contractName) {
157
+ return `// SPDX-License-Identifier: MIT
158
+ pragma solidity >=0.6.2 <0.9.0;
159
+
160
+ import "../Base.sol";
161
+ import {Properties} from "../Properties.sol";
162
+
163
+ /// @notice Handles the interaction with ${contractName}
164
+ abstract contract ${contractName}Handler is Properties {
165
+
166
+ // ――――――――――――――――――――――――― Clamped ――――――――――――――――――――――――――
167
+
168
+ // ―――――――――――――――――――――――― Unclamped ―――――――――――――――――――――――――
169
+ }
170
+ `;
171
+ }
172
+
173
+ function buildHandlersAggregator(contractNames) {
174
+ const imports = contractNames
175
+ .map((contractName) => `import {${contractName}Handler} from "./${contractName}Handler.sol";`)
176
+ .join('\n');
177
+ const inheritance = contractNames
178
+ .map((contractName, index) => ` ${contractName}Handler${index < contractNames.length - 1 ? ',' : ''}`)
179
+ .join('\n');
180
+
181
+ return `// SPDX-License-Identifier: MIT
182
+ pragma solidity >=0.6.2 <0.9.0;
183
+
184
+ import "../Base.sol";
185
+ ${imports}
186
+
187
+ /// @notice Inherits from all the handlers to expose all entry points in a single contract.
188
+ /// Manages environment changes (e.g. current actor, current token, mocks setup, etc.).
189
+ abstract contract Handlers is
190
+ ${inheritance}
191
+ {
192
+ function setCurrentActor(uint256 entropy) public {
193
+ actor = actors[entropy % actors.length];
194
+ }
195
+ }
196
+ `;
197
+ }
198
+
199
+ function writeGeneratedHandlers(contractNames) {
200
+ const handlersDir = path.join(suiteDir, 'handlers');
201
+ fs.mkdirSync(handlersDir, { recursive: true });
202
+
203
+ for (const contractName of contractNames) {
204
+ const handlerPath = path.join(handlersDir, `${contractName}Handler.sol`);
205
+ if (fs.existsSync(handlerPath)) {
206
+ console.log(` [exists] ${path.relative(projectRoot, handlerPath)}`);
207
+ continue;
208
+ }
209
+
210
+ fs.writeFileSync(handlerPath, buildHandlerTemplate(contractName));
211
+ console.log(` [new] ${path.relative(projectRoot, handlerPath)}`);
212
+ }
213
+ }
214
+
215
+ function writeHandlersAggregator(contractNames) {
216
+ const handlersPath = path.join(suiteDir, 'handlers', 'Handlers.sol');
217
+ const generatedContent = buildHandlersAggregator(contractNames);
218
+
219
+ if (fs.existsSync(handlersPath)) {
220
+ console.log(` [exists] ${path.relative(projectRoot, handlersPath)}`);
221
+ return;
222
+ }
223
+
224
+ fs.writeFileSync(handlersPath, generatedContent);
225
+ console.log(` [new] ${path.relative(projectRoot, handlersPath)}`);
226
+ }
227
+
228
+ // ――――――――――――――――――――――――――――― Main ――――――――――――――――――――――――――――――
229
+
230
+ function main() {
231
+ if (!fs.existsSync(templatesDir)) {
232
+ console.error(`Templates directory not found: ${templatesDir}`);
233
+ process.exit(1);
234
+ }
235
+
236
+ const selectedContracts = readSelectedContracts();
237
+
238
+ console.log('Copying template scaffold...');
239
+ const copied = copyTemplates(templatesDir, suiteDir, true);
240
+
241
+ console.log('\nCopying config files...');
242
+ copyRootConfigs();
243
+
244
+ console.log('\nGenerating handler stubs...');
245
+ writeGeneratedHandlers(selectedContracts);
246
+ writeHandlersAggregator(selectedContracts);
247
+
248
+ console.log('\nScaffold complete.');
249
+ console.log(` new files: ${copied.length}`);
250
+ console.log('\nNext: the LLM modifies the copied scaffold in later steps');
251
+ console.log('to wire setup, generate handlers, and add invariants.');
252
+ }
253
+
254
+ main();