hex-audit 0.6.3 → 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.
- package/CLAUDE.md +137 -77
- package/DEMO.md +41 -105
- package/README.md +205 -353
- package/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/app-build-manifest.json +65 -99
- package/dashboard/.next/app-path-routes-manifest.json +1 -1
- package/dashboard/.next/build-manifest.json +14 -14
- package/dashboard/.next/next-minimal-server.js.nft.json +1 -1
- package/dashboard/.next/next-server.js.nft.json +1 -1
- package/dashboard/.next/prerender-manifest.js +1 -1
- package/dashboard/.next/prerender-manifest.json +1 -1
- package/dashboard/.next/react-loadable-manifest.json +540 -119
- package/dashboard/.next/routes-manifest.json +1 -1
- package/dashboard/.next/server/app/_not-found/page.js +1 -1
- package/dashboard/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/api/code/route.js +1 -1
- package/dashboard/.next/server/app/api/code/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/comments/route.js +1 -0
- package/dashboard/.next/server/app/api/comments/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/export/route.js +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/export/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/resolve/route.js +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/resolve/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/route.js +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/figures/[name]/route.js +1 -0
- package/dashboard/.next/server/app/api/figures/[name]/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/focus/route.js +1 -0
- package/dashboard/.next/server/app/api/focus/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/github-status/route.js +1 -1
- package/dashboard/.next/server/app/api/invariants/[id]/route.js +1 -0
- package/dashboard/.next/server/app/api/invariants/[id]/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/issues/[id]/revert-auto/route.js +1 -0
- package/dashboard/.next/server/app/api/issues/[id]/revert-auto/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/nav/route.js +1 -0
- package/dashboard/.next/server/app/api/nav/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/notes/done/route.js +1 -1
- package/dashboard/.next/server/app/api/notes/done/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/notes/lead/route.js +1 -1
- package/dashboard/.next/server/app/api/notes/lead/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/notes/question/route.js +1 -1
- package/dashboard/.next/server/app/api/notes/question/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/notes/record/route.js +3 -3
- package/dashboard/.next/server/app/api/notes/route.js +2 -2
- package/dashboard/.next/server/app/api/palette/route.js +1 -0
- package/dashboard/.next/server/app/api/palette/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/progress/route.js +1 -1
- package/dashboard/.next/server/app/api/progress/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/watch/route.js +2 -2
- package/dashboard/.next/server/app/api/watch/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/xref/route.js +1 -0
- package/dashboard/.next/server/app/changes/page.js +1 -0
- package/dashboard/.next/server/app/{access → changes}/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/changes/page_client-reference-manifest.js +1 -0
- package/dashboard/.next/server/app/excalidraw-assets/[...path]/route.js +1 -0
- package/dashboard/.next/server/app/issues/page.js +5 -28
- package/dashboard/.next/server/app/issues/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/model/page.js +1 -0
- package/dashboard/.next/server/app/{calls → model}/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/model/page_client-reference-manifest.js +1 -0
- package/dashboard/.next/server/app/page.js +1 -20
- package/dashboard/.next/server/app/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/report/page.js +1 -1
- package/dashboard/.next/server/app/report/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/report/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/review/page.js +1 -0
- package/dashboard/.next/server/app/{conformance → review}/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/review/page_client-reference-manifest.js +1 -0
- package/dashboard/.next/server/app-paths-manifest.json +20 -16
- package/dashboard/.next/server/chunks/310.js +4 -0
- package/dashboard/.next/server/chunks/370.js +1 -0
- package/dashboard/.next/server/chunks/42.js +1 -1
- package/dashboard/.next/server/chunks/624.js +14 -0
- package/dashboard/.next/server/chunks/645.js +1 -1
- package/dashboard/.next/server/chunks/649.js +1 -1
- package/dashboard/.next/server/chunks/653.js +1 -0
- package/dashboard/.next/server/functions-config-manifest.json +1 -1
- package/dashboard/.next/server/middleware-build-manifest.js +1 -1
- package/dashboard/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dashboard/.next/server/next-font-manifest.js +1 -1
- package/dashboard/.next/server/next-font-manifest.json +1 -1
- package/dashboard/.next/server/pages/500.html +1 -1
- package/dashboard/.next/server/pages/_error.js +1 -1
- package/dashboard/.next/server/pages-manifest.json +1 -1
- package/dashboard/.next/server/server-reference-manifest.js +1 -1
- package/dashboard/.next/server/server-reference-manifest.json +1 -1
- package/dashboard/.next/static/bGV1ry1vvIbM5b506eVBR/_buildManifest.js +1 -0
- package/dashboard/.next/static/chunks/0bbe10ee.8e7ffa06d2170dfe.js +84 -0
- package/dashboard/.next/static/chunks/{1.8868c4d131111be7.js → 1.a666047ea18866fb.js} +2 -2
- package/dashboard/.next/static/chunks/1015.39008440ab15e196.js +226 -0
- package/dashboard/.next/static/chunks/1026.0ef689a305302427.js +1 -0
- package/dashboard/.next/static/chunks/1151.497fa63c5b9eba52.js +1 -0
- package/dashboard/.next/static/chunks/1164.34eb76767ebea46f.js +8 -0
- package/dashboard/.next/static/chunks/119.a9a79633900a235f.js +5 -0
- package/dashboard/.next/static/chunks/1199.f30cbfa151e56076.js +148 -0
- package/dashboard/.next/static/chunks/1291.6c486c9b1d4b1b3a.js +1 -0
- package/dashboard/.next/static/chunks/1375.64c20f1064a38a10.js +43 -0
- package/dashboard/.next/static/chunks/139.4691848fc5a46253.js +10 -0
- package/dashboard/.next/static/chunks/145.1bf74fecdb4022e3.js +11 -0
- package/dashboard/.next/static/chunks/1517.8e7075f78e22b3a0.js +8 -0
- package/dashboard/.next/static/chunks/165.6f174060a0ce2db4.js +6 -0
- package/dashboard/.next/static/chunks/1741.5c370b7702d2eb40.js +8 -0
- package/dashboard/.next/static/chunks/1799.8dc56017eede704e.js +9 -0
- package/dashboard/.next/static/chunks/1e36816c.5748c83adc8a6bd6.js +108 -0
- package/dashboard/.next/static/chunks/20154aaa.e87f69fe10483f8b.js +1 -0
- package/dashboard/.next/static/chunks/2061.eab75b3c1dfa068a.js +1 -0
- package/dashboard/.next/static/chunks/2077.5603adeb156c7d10.js +1 -0
- package/dashboard/.next/static/chunks/2148.3ce718f62d1b2f7c.js +10 -0
- package/dashboard/.next/static/chunks/2166.9f6592b9399eadd8.js +215 -0
- package/dashboard/.next/static/chunks/217-1d5b680ffd10e3f9.js +1 -0
- package/dashboard/.next/static/chunks/2208.fb884379aa3ae968.js +1 -0
- package/dashboard/.next/static/chunks/2276.112c7855333fca5f.js +6 -0
- package/dashboard/.next/static/chunks/{2291.85a70cb0c228157b.js → 2291.584b42ccad079b99.js} +1 -1
- package/dashboard/.next/static/chunks/2325.7decd077edfb81d9.js +24 -0
- package/dashboard/.next/static/chunks/2374-8c6f137938f8518a.js +1 -0
- package/dashboard/.next/static/chunks/{2383.62c035a052272594.js → 2383.ca81f980ce6528a4.js} +1 -1
- package/dashboard/.next/static/chunks/2445.18a86507d2996b95.js +1 -0
- package/dashboard/.next/static/chunks/2694.7dfa5fef28851903.js +1 -0
- package/dashboard/.next/static/chunks/2712.15dd8577973baf22.js +10 -0
- package/dashboard/.next/static/chunks/275.38af87389c1d33d7.js +34 -0
- package/dashboard/.next/static/chunks/2759.533dec5317e0a1d1.js +1 -0
- package/dashboard/.next/static/chunks/2781.fba46046dbf2693b.js +93 -0
- package/dashboard/.next/static/chunks/2805.35b4cd8a94978aaf.js +1 -0
- package/dashboard/.next/static/chunks/2812.62b213bef580b69a.js +1 -0
- package/dashboard/.next/static/chunks/{2879.51436986f93981d9.js → 2879.74d65e33e60505ee.js} +1 -1
- package/dashboard/.next/static/chunks/2895.bb57cacb7aaf42a1.js +9 -0
- package/dashboard/.next/static/chunks/2972.e5a9251b538dcf19.js +9 -0
- package/dashboard/.next/static/chunks/3205-fd963acf2fdfd080.js +2 -0
- package/dashboard/.next/static/chunks/3206.8d9a10db2b04b93f.js +1 -0
- package/dashboard/.next/static/chunks/3236.eac9855778a54518.js +1 -0
- package/dashboard/.next/static/chunks/3480.853a445a3784642a.js +1 -0
- package/dashboard/.next/static/chunks/3485.36766504793b7237.js +9 -0
- package/dashboard/.next/static/chunks/3626.c5dacee11c8fbc4d.js +64 -0
- package/dashboard/.next/static/chunks/3725.de9376dc994735d4.js +9 -0
- package/dashboard/.next/static/chunks/3774.1df377928e8387f7.js +9 -0
- package/dashboard/.next/static/chunks/3865.5e6d2d501380e03b.js +90 -0
- package/dashboard/.next/static/chunks/3887.073cece834a4eae2.js +1 -0
- package/dashboard/.next/static/chunks/3924-f1f85ccc7d59d7ab.js +1 -0
- package/dashboard/.next/static/chunks/3948.74201b9f0672234d.js +287 -0
- package/dashboard/.next/static/chunks/3963.39d72b3875dfe2e9.js +13 -0
- package/dashboard/.next/static/chunks/4013.73884b23bfaebdde.js +11 -0
- package/dashboard/.next/static/chunks/4117.278aff1fa23fd36e.js +6 -0
- package/dashboard/.next/static/chunks/4210.cc8594110017c579.js +11 -0
- package/dashboard/.next/static/chunks/4282.28485875540886cc.js +7 -0
- package/dashboard/.next/static/chunks/4318.a2f469a88d88f6d0.js +8 -0
- package/dashboard/.next/static/chunks/4363.8999a6e727c48003.js +1 -0
- package/dashboard/.next/static/chunks/4641.e03d118fffebd580.js +5 -0
- package/dashboard/.next/static/chunks/4728.e69372b5e5b61b8d.js +24 -0
- package/dashboard/.next/static/chunks/4787.821a6ad2816cdc60.js +23 -0
- package/dashboard/.next/static/chunks/483.a910dab7734a1074.js +8 -0
- package/dashboard/.next/static/chunks/4926.76693f542e9cc062.js +6 -0
- package/dashboard/.next/static/chunks/4938.03f6d04dabf38745.js +10 -0
- package/dashboard/.next/static/chunks/5060.47402abc10273699.js +1 -0
- package/dashboard/.next/static/chunks/5112.0757c2b0c285e62e.js +1 -0
- package/dashboard/.next/static/chunks/5199.c83ea7efb0eec705.js +11 -0
- package/dashboard/.next/static/chunks/5284.334c7c0587d5d47a.js +1 -0
- package/dashboard/.next/static/chunks/530.849957a8907eb288.js +1 -0
- package/dashboard/.next/static/chunks/5424.4e8ca0711a32bccf.js +7 -0
- package/dashboard/.next/static/chunks/55.a593a78be9714679.js +1 -0
- package/dashboard/.next/static/chunks/5535.6cd0bd8d368d8902.js +4 -0
- package/dashboard/.next/static/chunks/5626.7d4e93d7acbeffc9.js +10 -0
- package/dashboard/.next/static/chunks/5715.e16b1230cc4b4652.js +115 -0
- package/dashboard/.next/static/chunks/5775.a0d7c1b1e89b9a93.js +9 -0
- package/dashboard/.next/static/chunks/6014.641a2c53ba506241.js +104 -0
- package/dashboard/.next/static/chunks/6024.f099c15f75aa6722.js +79 -0
- package/dashboard/.next/static/chunks/{6052.033a6f1013c666eb.js → 6052.3001318955e5b36c.js} +2 -2
- package/dashboard/.next/static/chunks/6118.266956b3333b1d7a.js +9 -0
- package/dashboard/.next/static/chunks/6121.a2e6d93720b1205e.js +77 -0
- package/dashboard/.next/static/chunks/6177.a01cf0a03734cf09.js +1 -0
- package/dashboard/.next/static/chunks/618f8807-fbb1466bc29c17c6.js +1 -0
- package/dashboard/.next/static/chunks/6434.f560693253fea8de.js +1 -0
- package/dashboard/.next/static/chunks/6468.976d89ba133185f1.js +77 -0
- package/dashboard/.next/static/chunks/6540.6f3c4f2c6877ed89.js +1 -0
- package/dashboard/.next/static/chunks/6549.e3c4c1766cff1449.js +1 -0
- package/dashboard/.next/static/chunks/6853.d3ad43614e8ca0ab.js +1 -0
- package/dashboard/.next/static/chunks/690f35d0.ab57e02a04c7e9e0.js +119 -0
- package/dashboard/.next/static/chunks/6951.02a3a158d02158c9.js +5 -0
- package/dashboard/.next/static/chunks/6970.013f24568c87d918.js +11 -0
- package/dashboard/.next/static/chunks/7013.39d41e82b37be63b.js +9 -0
- package/dashboard/.next/static/chunks/{7020.831e16e26d91abc1.js → 7020.b718b1b9cea36e60.js} +2 -2
- package/dashboard/.next/static/chunks/7107.1c5412197912b8ed.js +8 -0
- package/dashboard/.next/static/chunks/7498-7cf464d8af69cd0a.js +1 -0
- package/dashboard/.next/static/chunks/7508.dd60e2d06d149f5f.js +9 -0
- package/dashboard/.next/static/chunks/7524.0fde4c61553d1491.js +3 -0
- package/dashboard/.next/static/chunks/7802.f0134c792fccd382.js +80 -0
- package/dashboard/.next/static/chunks/7834-47f318a04a05688f.js +1 -0
- package/dashboard/.next/static/chunks/{7a04ac15.1c6cea694301806c.js → 7a04ac15.e49de94ece135900.js} +1 -1
- package/dashboard/.next/static/chunks/8216.1138ec313908a708.js +5 -0
- package/dashboard/.next/static/chunks/{8233babc.780b8e272eda298f.js → 8233babc.09872dcb3ff44064.js} +1 -1
- package/dashboard/.next/static/chunks/8317.d0b3eddef4cae0d5.js +1 -0
- package/dashboard/.next/static/chunks/838.2b2aa006519ba44c.js +10 -0
- package/dashboard/.next/static/chunks/8398.924fd8f4c83417c0.js +7 -0
- package/dashboard/.next/static/chunks/8428b36f.8ac4e67061c01307.js +34 -0
- package/dashboard/.next/static/chunks/8514.85ccbbea8ab21d04.js +5 -0
- package/dashboard/.next/static/chunks/8538.5f7ebe76c4b63162.js +1 -0
- package/dashboard/.next/static/chunks/8645.98a43217d406500e.js +1 -0
- package/dashboard/.next/static/chunks/8687.9406baa8b5601fd0.js +1 -0
- package/dashboard/.next/static/chunks/8721.47346e2cb6412376.js +10 -0
- package/dashboard/.next/static/chunks/8770.4f544bd1a6f03a62.js +8 -0
- package/dashboard/.next/static/chunks/8812.3d96fd54dba566f8.js +9 -0
- package/dashboard/.next/static/chunks/8962.d22aa67a97970dd8.js +1 -0
- package/dashboard/.next/static/chunks/8986.b327224b83f4399a.js +5 -0
- package/dashboard/.next/static/chunks/9173.a7160f7d0b685fa7.js +1 -0
- package/dashboard/.next/static/chunks/9178.998a8c49996de8e4.js +1 -0
- package/dashboard/.next/static/chunks/9271.5f66c19a8ee1ff36.js +10 -0
- package/dashboard/.next/static/chunks/9282.f8d01442bab4c0da.js +2 -0
- package/dashboard/.next/static/chunks/9366.0ec24a0791b9b00f.js +1 -0
- package/dashboard/.next/static/chunks/9466.a914ce0de7d3bb84.js +1 -0
- package/dashboard/.next/static/chunks/9660.b1c8deae2c449d14.js +1 -0
- package/dashboard/.next/static/chunks/9707.5cd7d2ee933a4af5.js +6 -0
- package/dashboard/.next/static/chunks/9716.15fffc0b0038601d.js +4 -0
- package/dashboard/.next/static/chunks/{9717.6cf5c8c89403b651.js → 9717.bba51b78ebd8fd29.js} +1 -1
- package/dashboard/.next/static/chunks/9720.d63a0696776bcc60.js +1 -0
- package/dashboard/.next/static/chunks/9791.e3b3f5a367f63c8a.js +1 -0
- package/dashboard/.next/static/chunks/9811.2993c4cbd28e8d1b.js +1 -0
- package/dashboard/.next/static/chunks/9820.8c1efad5260e8137.js +1 -0
- package/dashboard/.next/static/chunks/985.50150e9eaa4bde33.js +39 -0
- package/dashboard/.next/static/chunks/997.56901b86e1b8a87b.js +8 -0
- package/dashboard/.next/static/chunks/app/_not-found/page-5ff5d54b6fd6f17e.js +1 -0
- package/dashboard/.next/static/chunks/app/changes/page-f8a860034221cad4.js +1 -0
- package/dashboard/.next/static/chunks/app/issues/page-da4da93188c414a6.js +1 -0
- package/dashboard/.next/static/chunks/app/layout-27a9da4610423c1e.js +1 -0
- package/dashboard/.next/static/chunks/app/model/page-9680e22fdd6ddb81.js +1 -0
- package/dashboard/.next/static/chunks/app/page-0e67750d99fb2836.js +1 -0
- package/dashboard/.next/static/chunks/app/report/page-b56b1db9b9dcf2b6.js +1 -0
- package/dashboard/.next/static/chunks/app/review/page-3ef69f0e0badd333.js +1 -0
- package/dashboard/.next/static/chunks/{b7167ec1.7afbab6f609e3326.js → b7167ec1.708a3d61698ca2e6.js} +1 -1
- package/dashboard/.next/static/chunks/c75e29e3.d91220f782934d80.js +1 -0
- package/dashboard/.next/static/chunks/c7ea4e13.3073a2f551aa5ac8.js +1 -0
- package/dashboard/.next/static/chunks/framework-a117d81bf1b91f9a.js +33 -0
- package/dashboard/.next/static/chunks/main-9c95a7ffedc7afb4.js +1 -0
- package/dashboard/.next/static/chunks/main-app-5662c64b50ba40d1.js +1 -0
- package/dashboard/.next/static/chunks/pages/_app-308fef0bf9b328f2.js +1 -0
- package/dashboard/.next/static/chunks/pages/_error-c91b5eabd7ac9382.js +1 -0
- package/dashboard/.next/static/chunks/webpack-6da70e4f9fcf1799.js +1 -0
- package/dashboard/.next/static/css/ceafd91ca8dd753d.css +3 -0
- package/dashboard/.next/static/css/e4aad1f9c715b79a.css +1 -0
- package/dashboard/.next/static/media/39f449c8730c2295-s.woff2 +0 -0
- package/dashboard/.next/static/media/86f65e8637cc94e3-s.woff2 +0 -0
- package/dashboard/.next/static/media/8760c4774489e4ba-s.p.woff2 +0 -0
- package/dashboard/.next/static/media/9fabb9c65b63d798-s.woff2 +0 -0
- package/dashboard/.next/static/media/Assistant-Bold.c8f39f24.woff2 +0 -0
- package/dashboard/.next/static/media/Assistant-Medium.1e75d8e6.woff2 +0 -0
- package/dashboard/.next/static/media/Assistant-Regular.7acbabb8.woff2 +0 -0
- package/dashboard/.next/static/media/Assistant-SemiBold.167acbf8.woff2 +0 -0
- package/dashboard/.next/static/media/a1f87af3f44fadbb-s.woff2 +0 -0
- package/dashboard/.next/static/media/f9e1dbe9676d9bb6-s.woff2 +0 -0
- package/dashboard/app/api/code/route.ts +26 -20
- package/dashboard/app/api/comments/route.ts +158 -0
- package/dashboard/app/api/diagrams/[name]/export/route.ts +26 -0
- package/dashboard/app/api/diagrams/[name]/resolve/route.ts +25 -0
- package/dashboard/app/api/diagrams/[name]/route.ts +37 -0
- package/dashboard/app/api/figures/[name]/route.ts +15 -0
- package/dashboard/app/api/focus/route.ts +35 -0
- package/dashboard/app/api/invariants/[id]/route.ts +35 -0
- package/dashboard/app/api/issues/[id]/revert-auto/route.ts +18 -0
- package/dashboard/app/api/nav/route.ts +120 -0
- package/dashboard/app/api/palette/route.ts +68 -0
- package/dashboard/app/api/progress/route.ts +54 -23
- package/dashboard/app/api/xref/route.ts +30 -0
- package/dashboard/app/changes/ChangesClient.tsx +838 -0
- package/dashboard/app/changes/page.tsx +44 -0
- package/dashboard/app/excalidraw-assets/[...path]/route.ts +56 -0
- package/dashboard/app/globals.css +231 -77
- package/dashboard/app/issues/BoardClient.tsx +817 -0
- package/dashboard/app/issues/page.tsx +27 -272
- package/dashboard/app/layout.tsx +37 -10
- package/dashboard/app/model/ModelClient.tsx +1303 -0
- package/dashboard/app/model/page.tsx +98 -0
- package/dashboard/app/page.tsx +195 -239
- package/dashboard/app/report/ReportClient.tsx +147 -74
- package/dashboard/app/report/page.tsx +25 -14
- package/dashboard/app/review/ReviewClient.tsx +1180 -0
- package/dashboard/app/review/page.tsx +93 -0
- package/dashboard/components/AutoRefresh.tsx +22 -19
- package/dashboard/components/CodeComments.tsx +303 -0
- package/dashboard/components/CodeNav.tsx +523 -0
- package/dashboard/components/CodeReference.tsx +92 -99
- package/dashboard/components/CodeViewer.tsx +526 -0
- package/dashboard/components/CommandPalette.tsx +141 -66
- package/dashboard/components/DiagramCanvas.tsx +275 -0
- package/dashboard/components/DianeNote.tsx +244 -0
- package/dashboard/components/LiveStatus.tsx +30 -68
- package/dashboard/components/MarkdownRenderer.tsx +34 -32
- package/dashboard/components/RecordButton.tsx +132 -0
- package/dashboard/components/ui/Button.tsx +39 -0
- package/dashboard/components/ui/Chip.tsx +37 -0
- package/dashboard/components/ui/EmptyState.tsx +31 -0
- package/dashboard/components/ui/Icons.tsx +126 -0
- package/dashboard/components/ui/Inspector.tsx +122 -0
- package/dashboard/components/ui/Kbd.tsx +15 -0
- package/dashboard/components/ui/ListRow.tsx +92 -0
- package/dashboard/components/ui/LocalTime.tsx +14 -0
- package/dashboard/components/ui/ProgressRing.tsx +54 -0
- package/dashboard/components/ui/ResizeHandle.tsx +93 -0
- package/dashboard/components/ui/RiskMeter.tsx +27 -0
- package/dashboard/components/ui/SearchField.tsx +55 -0
- package/dashboard/components/ui/SegmentedControl.tsx +71 -0
- package/dashboard/components/ui/SeverityDot.tsx +57 -0
- package/dashboard/components/ui/Sidebar.tsx +236 -0
- package/dashboard/components/ui/SplitView.tsx +122 -0
- package/dashboard/components/ui/StateGlyph.tsx +66 -0
- package/dashboard/components/ui/Toast.tsx +91 -0
- package/dashboard/lib/api.ts +17 -0
- package/dashboard/lib/cn.ts +4 -0
- package/dashboard/lib/data.ts +2 -21
- package/dashboard/lib/finding-markdown.ts +1 -1
- package/dashboard/lib/focus.ts +42 -0
- package/dashboard/lib/hotkeys.ts +41 -0
- package/dashboard/lib/inline-markdown.test.ts +11 -0
- package/dashboard/lib/live.ts +32 -0
- package/dashboard/lib/pane-width.ts +36 -0
- package/dashboard/lib/server/board.ts +229 -0
- package/dashboard/lib/server/diagrams.ts +191 -0
- package/dashboard/lib/server/safe-path.ts +28 -0
- package/dashboard/lib/server/workspace.ts +113 -0
- package/dashboard/lib/server/xref.ts +42 -0
- package/dashboard/lib/solidity.test.ts +37 -0
- package/dashboard/lib/solidity.ts +191 -0
- package/dashboard/lib/source.ts +28 -0
- package/dashboard/lib/types.ts +164 -0
- package/dashboard/lib/url.ts +18 -0
- package/dashboard/lib/watcher.ts +31 -22
- package/dashboard/tailwind.config.ts +6 -3
- package/dist/analysis/code-model.d.ts +113 -0
- package/dist/analysis/code-model.d.ts.map +1 -0
- package/dist/analysis/code-model.js +532 -0
- package/dist/analysis/code-model.js.map +1 -0
- package/dist/analysis/diff.d.ts +75 -0
- package/dist/analysis/diff.d.ts.map +1 -0
- package/dist/analysis/diff.js +787 -0
- package/dist/analysis/diff.js.map +1 -0
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +25 -40
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/claude.d.ts.map +1 -1
- package/dist/commands/claude.js +5 -0
- package/dist/commands/claude.js.map +1 -1
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +10 -2
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/diagram.d.ts +3 -0
- package/dist/commands/diagram.d.ts.map +1 -0
- package/dist/commands/diagram.js +71 -0
- package/dist/commands/diagram.js.map +1 -0
- package/dist/commands/diff.d.ts +25 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +257 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +5 -18
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/facts.d.ts +23 -0
- package/dist/commands/facts.d.ts.map +1 -0
- package/dist/commands/facts.js +121 -0
- package/dist/commands/facts.js.map +1 -0
- package/dist/commands/fix-review.d.ts +9 -0
- package/dist/commands/fix-review.d.ts.map +1 -0
- package/dist/commands/fix-review.js +367 -0
- package/dist/commands/fix-review.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +106 -42
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/issue.d.ts.map +1 -1
- package/dist/commands/issue.js +154 -5
- package/dist/commands/issue.js.map +1 -1
- package/dist/commands/mcp.d.ts +3 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +11 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/model.d.ts +4 -0
- package/dist/commands/model.d.ts.map +1 -0
- package/dist/commands/model.js +275 -0
- package/dist/commands/model.js.map +1 -0
- package/dist/commands/note.d.ts.map +1 -1
- package/dist/commands/note.js +61 -3
- package/dist/commands/note.js.map +1 -1
- package/dist/commands/review.d.ts +4 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +164 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/core/comments.d.ts +59 -0
- package/dist/core/comments.d.ts.map +1 -0
- package/dist/core/comments.js +263 -0
- package/dist/core/comments.js.map +1 -0
- package/dist/core/config.d.ts +9 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +18 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/dedup.d.ts +56 -0
- package/dist/core/dedup.d.ts.map +1 -0
- package/dist/core/dedup.js +208 -0
- package/dist/core/dedup.js.map +1 -0
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +16 -15
- package/dist/core/errors.js.map +1 -1
- package/dist/core/external-tools.d.ts +0 -14
- package/dist/core/external-tools.d.ts.map +1 -1
- package/dist/core/external-tools.js +2 -52
- package/dist/core/external-tools.js.map +1 -1
- package/dist/core/fix-review.d.ts +54 -0
- package/dist/core/fix-review.d.ts.map +1 -0
- package/dist/core/fix-review.js +98 -0
- package/dist/core/fix-review.js.map +1 -0
- package/dist/core/fuzz-sync.d.ts +93 -0
- package/dist/core/fuzz-sync.d.ts.map +1 -0
- package/dist/core/fuzz-sync.js +516 -0
- package/dist/core/fuzz-sync.js.map +1 -0
- package/dist/core/git.d.ts +31 -0
- package/dist/core/git.d.ts.map +1 -0
- package/dist/core/git.js +157 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/issues.d.ts +35 -2
- package/dist/core/issues.d.ts.map +1 -1
- package/dist/core/issues.js +201 -30
- package/dist/core/issues.js.map +1 -1
- package/dist/core/mcp-config.d.ts +12 -0
- package/dist/core/mcp-config.d.ts.map +1 -0
- package/dist/core/mcp-config.js +29 -0
- package/dist/core/mcp-config.js.map +1 -0
- package/dist/core/model.d.ts +38 -0
- package/dist/core/model.d.ts.map +1 -0
- package/dist/core/model.js +160 -0
- package/dist/core/model.js.map +1 -0
- package/dist/core/notes.d.ts +27 -1
- package/dist/core/notes.d.ts.map +1 -1
- package/dist/core/notes.js +47 -5
- package/dist/core/notes.js.map +1 -1
- package/dist/core/review.d.ts +47 -0
- package/dist/core/review.d.ts.map +1 -1
- package/dist/core/review.js +177 -1
- package/dist/core/review.js.map +1 -1
- package/dist/core/rules.d.ts +12 -0
- package/dist/core/rules.d.ts.map +1 -0
- package/dist/core/rules.js +66 -0
- package/dist/core/rules.js.map +1 -0
- package/dist/core/schema.d.ts +5458 -2189
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +605 -114
- package/dist/core/schema.js.map +1 -1
- package/dist/core/scope.d.ts +8 -0
- package/dist/core/scope.d.ts.map +1 -0
- package/dist/core/scope.js +18 -0
- package/dist/core/scope.js.map +1 -0
- package/dist/core/skills.d.ts +10 -4
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +100 -37
- package/dist/core/skills.js.map +1 -1
- package/dist/diagrams/build.d.ts +18 -0
- package/dist/diagrams/build.d.ts.map +1 -0
- package/dist/diagrams/build.js +135 -0
- package/dist/diagrams/build.js.map +1 -0
- package/dist/diagrams/excalidraw.d.ts +27 -0
- package/dist/diagrams/excalidraw.d.ts.map +1 -0
- package/dist/diagrams/excalidraw.js +219 -0
- package/dist/diagrams/excalidraw.js.map +1 -0
- package/dist/diagrams/layout.d.ts +48 -0
- package/dist/diagrams/layout.d.ts.map +1 -0
- package/dist/diagrams/layout.js +686 -0
- package/dist/diagrams/layout.js.map +1 -0
- package/dist/facts/build.d.ts +23 -0
- package/dist/facts/build.d.ts.map +1 -0
- package/dist/facts/build.js +112 -0
- package/dist/facts/build.js.map +1 -0
- package/dist/facts/extract.d.ts +53 -0
- package/dist/facts/extract.d.ts.map +1 -0
- package/dist/facts/extract.js +635 -0
- package/dist/facts/extract.js.map +1 -0
- package/dist/facts/fallback.d.ts +7 -0
- package/dist/facts/fallback.d.ts.map +1 -0
- package/dist/facts/fallback.js +156 -0
- package/dist/facts/fallback.js.map +1 -0
- package/dist/facts/implementations.d.ts +29 -0
- package/dist/facts/implementations.d.ts.map +1 -0
- package/dist/facts/implementations.js +43 -0
- package/dist/facts/implementations.js.map +1 -0
- package/dist/facts/query.d.ts +35 -0
- package/dist/facts/query.d.ts.map +1 -0
- package/dist/facts/query.js +157 -0
- package/dist/facts/query.js.map +1 -0
- package/dist/facts/xref.d.ts +53 -0
- package/dist/facts/xref.d.ts.map +1 -0
- package/dist/facts/xref.js +282 -0
- package/dist/facts/xref.js.map +1 -0
- package/dist/index.js +16 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +400 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/skills/ai-audit/LICENSE +21 -0
- package/dist/skills/ai-audit/SKILL.md +486 -0
- package/dist/skills/ai-audit/UPSTREAM.md +51 -0
- package/dist/skills/ai-audit/references/agent-prompts.md +133 -0
- package/dist/skills/ai-audit/references/assemble.sh +357 -0
- package/dist/skills/ai-audit/references/dedup-and-assembly.md +420 -0
- package/dist/skills/ai-audit/references/hacking-agents/access-control-agent.md +27 -0
- package/dist/skills/ai-audit/references/hacking-agents/asymmetry-agent.md +77 -0
- package/dist/skills/ai-audit/references/hacking-agents/boundary-agent.md +79 -0
- package/dist/skills/ai-audit/references/hacking-agents/economic-security-agent.md +35 -0
- package/dist/skills/ai-audit/references/hacking-agents/execution-trace-agent.md +33 -0
- package/dist/skills/ai-audit/references/hacking-agents/first-principles-agent.md +36 -0
- package/dist/skills/ai-audit/references/hacking-agents/flow-gap-agent.md +49 -0
- package/dist/skills/ai-audit/references/hacking-agents/invariant-agent.md +44 -0
- package/dist/skills/ai-audit/references/hacking-agents/math-precision-agent.md +48 -0
- package/dist/skills/ai-audit/references/hacking-agents/numerical-gap-agent.md +46 -0
- package/dist/skills/ai-audit/references/hacking-agents/periphery-agent.md +27 -0
- package/dist/skills/ai-audit/references/hacking-agents/shared-rules.md +61 -0
- package/dist/skills/ai-audit/references/hacking-agents/trust-gap-agent.md +40 -0
- package/dist/skills/ai-audit/references/hex-board.md +211 -0
- package/dist/skills/ai-audit/references/hex-export.sh +71 -0
- package/dist/skills/ai-audit/references/judging.md +75 -0
- package/dist/skills/ai-audit/references/report-formatting.md +385 -0
- package/dist/skills/ai-audit/references/report-language.md +151 -0
- package/dist/skills/ai-audit/references/senior-auditor-sop.md +63 -0
- package/dist/skills/diane.md +26 -12
- package/dist/skills/fix-review.md +58 -0
- package/dist/skills/fuzz/LICENSE +21 -0
- package/dist/skills/fuzz/SKILL.md +655 -0
- package/dist/skills/fuzz/UPSTREAM.md +119 -0
- package/dist/skills/fuzz/agents/implementers/global-property-implementer.md +81 -0
- package/dist/skills/fuzz/agents/implementers/specific-property-implementer.md +121 -0
- package/dist/skills/fuzz/agents/invariant-discovery/adversarial-profit-maximizer.md +123 -0
- package/dist/skills/fuzz/agents/invariant-discovery/conservation-auditor.md +92 -0
- package/dist/skills/fuzz/agents/invariant-discovery/protocol-type-specialist.md +173 -0
- package/dist/skills/fuzz/agents/invariant-discovery/roundtrip-rounding-analyst.md +164 -0
- package/dist/skills/fuzz/agents/invariant-discovery/state-transition-mapper.md +92 -0
- package/dist/skills/fuzz/agents/invariant-discovery/synthesizer.md +261 -0
- package/dist/skills/fuzz/agents/protocol-analyzer.md +80 -0
- package/dist/skills/fuzz/agents/report-writer.md +135 -0
- package/dist/skills/fuzz/references/handler-patterns.md +222 -0
- package/dist/skills/fuzz/references/hex-invariants.md +102 -0
- package/dist/skills/fuzz/references/property-generation.md +149 -0
- package/dist/skills/fuzz/references/selection-policy.md +49 -0
- package/dist/skills/fuzz/references/setup-playbook.md +92 -0
- package/dist/skills/fuzz/references/template-map.md +121 -0
- package/dist/skills/fuzz/scripts/ensure_foundry.sh +125 -0
- package/dist/skills/fuzz/scripts/estimate_cost.js +157 -0
- package/dist/skills/fuzz/scripts/extract_abis.js +303 -0
- package/dist/skills/fuzz/scripts/fizz_sync.js +692 -0
- package/dist/skills/fuzz/scripts/generate_handlers.js +370 -0
- package/dist/skills/fuzz/scripts/generate_suite.js +254 -0
- package/dist/skills/fuzz/scripts/lib/log-viewer.js +332 -0
- package/dist/skills/fuzz/scripts/run_echidna.js +192 -0
- package/dist/skills/fuzz/scripts/run_medusa.js +329 -0
- package/dist/skills/fuzz/scripts/select_functions.js +637 -0
- package/dist/skills/fuzz/scripts/setup_fuzz_profile.sh +142 -0
- package/dist/skills/fuzz/templates/Actor.sol +63 -0
- package/dist/skills/fuzz/templates/Base.sol +121 -0
- package/dist/skills/fuzz/templates/FoundryTester.sol +29 -0
- package/dist/skills/fuzz/templates/FuzzTester.sol +11 -0
- package/dist/skills/fuzz/templates/Properties.sol +17 -0
- package/dist/skills/fuzz/templates/README.md +56 -0
- package/dist/skills/fuzz/templates/Snapshots.sol +26 -0
- package/dist/skills/fuzz/templates/echidna.yaml +18 -0
- package/dist/skills/fuzz/templates/handlers/Handlers.sol +13 -0
- package/dist/skills/fuzz/templates/medusa.json +93 -0
- package/dist/skills/fuzz/templates/utils/Clamp.sol +223 -0
- package/dist/skills/fuzz/templates/utils/DecimalPrinter.sol +63 -0
- package/dist/skills/fuzz/templates/utils/Deployer.sol +17 -0
- package/dist/skills/fuzz/templates/utils/EnumerableSet.sol +206 -0
- package/dist/skills/fuzz/templates/utils/Hevm.sol +62 -0
- package/dist/skills/fuzz/templates/utils/Logger.sol +619 -0
- package/dist/skills/fuzz/templates/utils/Math.sol +52 -0
- package/dist/skills/fuzz/templates/utils/MockERC20.sol +279 -0
- package/dist/skills/fuzz/templates/utils/PropertiesAsserts.sol +238 -0
- package/dist/skills/fuzz/templates/utils/StringUtils.sol +85 -0
- package/dist/skills/fuzz-convert/SKILL.md +249 -0
- package/dist/skills/fuzz-sync/SKILL.md +342 -0
- package/dist/skills/generate-poc.md +8 -26
- package/dist/skills/generate-report.md +24 -8
- package/dist/skills/ingest-aa-report.md +11 -30
- package/dist/skills/init-audit/SKILL.md +155 -0
- package/dist/skills/init-audit/references/agents/conformance-checker.md +36 -0
- package/dist/skills/init-audit/references/agents/contract-reader.md +59 -0
- package/dist/skills/init-audit/references/agents/diagram-composer.md +48 -0
- package/dist/skills/init-audit/references/agents/docs-extractor.md +26 -0
- package/dist/skills/init-audit/references/agents/prior-audit.md +32 -0
- package/dist/skills/init-audit/references/agents/regression-checker.md +28 -0
- package/dist/skills/init-audit/references/agents/skeptic.md +31 -0
- package/dist/skills/init-audit/references/agents/standards-checker.md +39 -0
- package/dist/skills/init-audit/references/agents/synthesizer.md +50 -0
- package/dist/skills/prevalidate.md +62 -0
- package/dist/skills/sync-issues.md +11 -25
- package/dist/skills/validate-all-findings.md +3 -3
- package/dist/skills/validate-finding.md +33 -28
- package/dist/skills/write-finding.md +6 -5
- package/dist/types/index.d.ts +22 -12
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +6 -4
- package/dashboard/.next/server/app/_not-found.html +0 -1
- package/dashboard/.next/server/app/_not-found.meta +0 -6
- package/dashboard/.next/server/app/_not-found.rsc +0 -12
- package/dashboard/.next/server/app/access/page.js +0 -1
- package/dashboard/.next/server/app/access/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/api/flows/route.js +0 -1
- package/dashboard/.next/server/app/api/mermaid/route.js +0 -1
- package/dashboard/.next/server/app/calls/page.js +0 -1
- package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/conformance/page.js +0 -1
- package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/diagram/page.js +0 -1
- package/dashboard/.next/server/app/diagram/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/diagram.html +0 -1
- package/dashboard/.next/server/app/diagram.meta +0 -5
- package/dashboard/.next/server/app/diagram.rsc +0 -10
- package/dashboard/.next/server/app/flows/page.js +0 -1
- package/dashboard/.next/server/app/flows/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/flows.html +0 -1
- package/dashboard/.next/server/app/flows.meta +0 -5
- package/dashboard/.next/server/app/flows.rsc +0 -10
- package/dashboard/.next/server/app/functions/page.js +0 -1
- package/dashboard/.next/server/app/functions/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/notes/page.js +0 -22
- package/dashboard/.next/server/app/notes/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/notes/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/progress/page.js +0 -1
- package/dashboard/.next/server/app/progress/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/stats/page.js +0 -1
- package/dashboard/.next/server/app/stats/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/chunks/44.js +0 -1
- package/dashboard/.next/server/chunks/530.js +0 -1
- package/dashboard/.next/server/chunks/622.js +0 -3
- package/dashboard/.next/server/chunks/665.js +0 -13
- package/dashboard/.next/server/pages/404.html +0 -1
- package/dashboard/.next/static/AyrRAwu4mazjp8iX4Yjbb/_buildManifest.js +0 -1
- package/dashboard/.next/static/chunks/1015.3ab89142e5f44120.js +0 -226
- package/dashboard/.next/static/chunks/1151.b6ef5c786e587ed7.js +0 -1
- package/dashboard/.next/static/chunks/1199.a072929dbec89965.js +0 -148
- package/dashboard/.next/static/chunks/1375.d4d2f7fc9c9c2ff1.js +0 -43
- package/dashboard/.next/static/chunks/1799.83206776abbbf1fc.js +0 -9
- package/dashboard/.next/static/chunks/20154aaa.ccc347c04ab5ad4a.js +0 -1
- package/dashboard/.next/static/chunks/2077.7011a570c87aa7b1.js +0 -1
- package/dashboard/.next/static/chunks/2166.cc0fabeb2e89b840.js +0 -215
- package/dashboard/.next/static/chunks/2325.2c55cb9a6282ae3f.js +0 -24
- package/dashboard/.next/static/chunks/2694.92bbe252063e4786.js +0 -1
- package/dashboard/.next/static/chunks/275.0d761aa0e5b030b8.js +0 -34
- package/dashboard/.next/static/chunks/2781.8536b644a480aede.js +0 -93
- package/dashboard/.next/static/chunks/2805.a8d71d2f92bb6ba9.js +0 -1
- package/dashboard/.next/static/chunks/3017.e55781da9dd32d37.js +0 -1
- package/dashboard/.next/static/chunks/3205-728c260fbb4f89c6.js +0 -2
- package/dashboard/.next/static/chunks/3236.dff44fa7961d9d5e.js +0 -1
- package/dashboard/.next/static/chunks/3480.9451396ad7ee7613.js +0 -1
- package/dashboard/.next/static/chunks/3626.ba1cf848a9f2e93d.js +0 -64
- package/dashboard/.next/static/chunks/3865.a432a7910a2f5281.js +0 -90
- package/dashboard/.next/static/chunks/3887.c22cbfa3f095826c.js +0 -1
- package/dashboard/.next/static/chunks/3924-4a05057b5450abe1.js +0 -1
- package/dashboard/.next/static/chunks/3948.fe3c7d758568d98b.js +0 -287
- package/dashboard/.next/static/chunks/4728.07d87640a3e7dd0d.js +0 -24
- package/dashboard/.next/static/chunks/4787.4e5f6a0e0e40a583.js +0 -23
- package/dashboard/.next/static/chunks/5060.baca226af35ed016.js +0 -1
- package/dashboard/.next/static/chunks/5284.f949ac90c95ff143.js +0 -1
- package/dashboard/.next/static/chunks/5715.1524bcc9591e180b.js +0 -115
- package/dashboard/.next/static/chunks/6014.700ae4969b64d728.js +0 -104
- package/dashboard/.next/static/chunks/6024.4d23707c65514679.js +0 -79
- package/dashboard/.next/static/chunks/6177.e5c84cfc4c0dea51.js +0 -1
- package/dashboard/.next/static/chunks/618f8807-547c5614e1318888.js +0 -1
- package/dashboard/.next/static/chunks/6434.9481771c33195d29.js +0 -1
- package/dashboard/.next/static/chunks/6468.f4a3e8fa6accc6da.js +0 -77
- package/dashboard/.next/static/chunks/6540.86f367d7390738d4.js +0 -1
- package/dashboard/.next/static/chunks/6549.4d0d472df96429a5.js +0 -1
- package/dashboard/.next/static/chunks/690f35d0.3e40ca0930e4bbdb.js +0 -119
- package/dashboard/.next/static/chunks/7397-f6f4dddc7a20bfc1.js +0 -1
- package/dashboard/.next/static/chunks/7498-ea83cb9e30ec5491.js +0 -1
- package/dashboard/.next/static/chunks/7802.89aec9ee11680850.js +0 -80
- package/dashboard/.next/static/chunks/7973.8b526f589aca5d84.js +0 -79
- package/dashboard/.next/static/chunks/8216.1bead812eb126c35.js +0 -5
- package/dashboard/.next/static/chunks/8452-e616b5f43bceb95f.js +0 -13
- package/dashboard/.next/static/chunks/8645.a5ca76f11edc9633.js +0 -1
- package/dashboard/.next/static/chunks/8928-60c623ee89d2e6ad.js +0 -1
- package/dashboard/.next/static/chunks/9173.2486ffca31131ec5.js +0 -1
- package/dashboard/.next/static/chunks/9178.469341860bf8caec.js +0 -1
- package/dashboard/.next/static/chunks/9466.e904660d38c03eea.js +0 -1
- package/dashboard/.next/static/chunks/9660.84a85811380c5f33.js +0 -1
- package/dashboard/.next/static/chunks/9720.67d4d0d15a96d691.js +0 -1
- package/dashboard/.next/static/chunks/9811.65e1d080c2d256af.js +0 -1
- package/dashboard/.next/static/chunks/app/_not-found/page-548ab392d0e890d1.js +0 -1
- package/dashboard/.next/static/chunks/app/access/page-3668562e7464eb5d.js +0 -1
- package/dashboard/.next/static/chunks/app/calls/page-d07f5b8664cc8303.js +0 -1
- package/dashboard/.next/static/chunks/app/conformance/page-2fede1d7b5f9265d.js +0 -1
- package/dashboard/.next/static/chunks/app/diagram/page-b228444265546495.js +0 -1
- package/dashboard/.next/static/chunks/app/flows/page-fa67783d8cd79cab.js +0 -1
- package/dashboard/.next/static/chunks/app/functions/page-686f0296639133a3.js +0 -1
- package/dashboard/.next/static/chunks/app/issues/page-98a298e1c1045c91.js +0 -1
- package/dashboard/.next/static/chunks/app/layout-49f2496c7637d931.js +0 -1
- package/dashboard/.next/static/chunks/app/notes/page-17af94c67ba79c00.js +0 -1
- package/dashboard/.next/static/chunks/app/page-24bac51dfe007c66.js +0 -1
- package/dashboard/.next/static/chunks/app/progress/page-427fb18da3afb061.js +0 -1
- package/dashboard/.next/static/chunks/app/report/page-796f2f4a8a5ac8f7.js +0 -1
- package/dashboard/.next/static/chunks/app/stats/page-db81f600a086f252.js +0 -1
- package/dashboard/.next/static/chunks/c7ea4e13.5effeeba6618bdb7.js +0 -1
- package/dashboard/.next/static/chunks/framework-cf6f5bdca6ba0184.js +0 -33
- package/dashboard/.next/static/chunks/main-63ff429eab01f5bf.js +0 -1
- package/dashboard/.next/static/chunks/main-app-9d2f6b8a47133e9b.js +0 -1
- package/dashboard/.next/static/chunks/pages/_app-6ad2b50514c24ab4.js +0 -1
- package/dashboard/.next/static/chunks/pages/_error-d5eb11c5c4626811.js +0 -1
- package/dashboard/.next/static/chunks/webpack-08869f2b18792e51.js +0 -1
- package/dashboard/.next/static/css/4a38d8f6f6b7a68f.css +0 -3
- package/dashboard/.next/static/media/438aa629764e75f3-s.woff2 +0 -0
- package/dashboard/.next/static/media/4c9affa5bc8f420e-s.p.woff2 +0 -0
- package/dashboard/.next/static/media/51251f8b9793cdb3-s.woff2 +0 -0
- package/dashboard/.next/static/media/875ae681bfde4580-s.woff2 +0 -0
- package/dashboard/.next/static/media/cc978ac5ee68c2b6-s.woff2 +0 -0
- package/dashboard/.next/static/media/e857b654a2caa584-s.woff2 +0 -0
- package/dashboard/app/access/AccessClient.tsx +0 -402
- package/dashboard/app/access/ReadOnlyFunctions.tsx +0 -114
- package/dashboard/app/access/page.tsx +0 -125
- package/dashboard/app/api/flows/route.ts +0 -32
- package/dashboard/app/api/mermaid/route.ts +0 -25
- package/dashboard/app/calls/CallsClient.tsx +0 -170
- package/dashboard/app/calls/page.tsx +0 -57
- package/dashboard/app/conformance/ConformanceTable.tsx +0 -214
- package/dashboard/app/conformance/page.tsx +0 -186
- package/dashboard/app/diagram/page.tsx +0 -65
- package/dashboard/app/flows/page.tsx +0 -102
- package/dashboard/app/functions/FunctionsClient.tsx +0 -167
- package/dashboard/app/functions/page.tsx +0 -178
- package/dashboard/app/issues/IssuesBoardClient.tsx +0 -803
- package/dashboard/app/notes/NotesClient.tsx +0 -701
- package/dashboard/app/notes/page.tsx +0 -47
- package/dashboard/app/progress/ProgressClient.tsx +0 -354
- package/dashboard/app/progress/page.tsx +0 -127
- package/dashboard/app/stats/StatsClient.tsx +0 -452
- package/dashboard/app/stats/page.tsx +0 -50
- package/dashboard/components/ConfidenceBadge.tsx +0 -53
- package/dashboard/components/DashboardLayout.tsx +0 -485
- package/dashboard/components/FilterableTable.tsx +0 -293
- package/dashboard/components/MermaidViewer.tsx +0 -267
- package/dashboard/components/NotYetGenerated.tsx +0 -32
- package/dashboard/components/SeverityBadge.tsx +0 -28
- package/dashboard/components/SignalBars.tsx +0 -27
- package/dashboard/components/SortableTable.tsx +0 -122
- package/dashboard/lib/conformance-tokens.ts +0 -49
- package/dist/skills/init-audit.md +0 -284
- /package/dashboard/.next/server/app/api/{flows → xref}/route.js.nft.json +0 -0
- /package/dashboard/.next/server/app/{api/mermaid → excalidraw-assets/[...path]}/route.js.nft.json +0 -0
- /package/dashboard/.next/static/{AyrRAwu4mazjp8iX4Yjbb → bGV1ry1vvIbM5b506eVBR}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,655 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fuzz
|
|
3
|
+
description: Stateful Echidna/Medusa fuzz suite for the auditor's accepted Hex invariants (fork of pashov's fizz). Each accepted invariant in .hex/model/invariants.json becomes one fuzz property; campaign results flow back into the invariants and reproduced violations become cards on the Hex board. Trigger on "fuzz", "fuzz the invariants", "generate fuzz suite", "build fuzz harness", "stateful fuzzing", "fuzzing harness", "property testing", and "invariant suite".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fizz
|
|
7
|
+
|
|
8
|
+
> **Hex fork.** This skill is pashov's `fizz` (MIT; see `UPSTREAM.md` and `LICENSE` next to this file) adapted for Hex. Four things differ from upstream. First, the property list is the auditor's **accepted Hex invariants** (Step 3), not an x-ray report. fizz's discovery agents still run, but anything new they find is written back as a *proposed* invariant for the auditor and is not fuzzed. Second, every property carries the `INV-NNN` it checks. Third, `PROPERTIES.md` and the metadata live under `.hex/fuzz/`. Fourth, **Step 12** folds every campaign back into the invariants (`hex invariant sync-fuzz`) and opens a board card for each reproduced violation. The rest is upstream, kept as close to its wording as possible so future upstream releases merge cleanly. The Hex rules are in `{SKILL_PATH}/references/hex-invariants.md`.
|
|
9
|
+
|
|
10
|
+
Generate a stateful Solidity fuzz suite under `{SUITE_DIR}` (default: `test/fizz/`), with the English property spec at `.hex/fuzz/PROPERTIES.md` and metadata and fuzzer runtime files under `{META_DIR}` (default: `.hex/fuzz/fizz_data/`).
|
|
11
|
+
|
|
12
|
+
Use `Echidna` and `Medusa` for invariant campaigns. Use `Foundry` for compilation, smoke testing, and quick debugging.
|
|
13
|
+
|
|
14
|
+
## Workflow Rules
|
|
15
|
+
|
|
16
|
+
- Follow the steps in order. Do not skip forward if a required artifact for the current step does not exist yet.
|
|
17
|
+
- If a step fails, stop there and report the blocker.
|
|
18
|
+
- If tooling is missing, say exactly what was attempted and what is missing.
|
|
19
|
+
- Keep the generated Solidity suite isolated under `test/fizz/` and the property spec and metadata/runtime files under `.hex/fuzz/` unless the user explicitly asks for different paths.
|
|
20
|
+
- Call the Hex CLI as `npx --no-install hex …`, never `npx hex …`: an unrelated npm package named `hex` exists.
|
|
21
|
+
- Reuse existing project setup and test logic whenever possible; do not invent a deployment flow if the repo already has one.
|
|
22
|
+
|
|
23
|
+
## Parameters
|
|
24
|
+
|
|
25
|
+
- `PROJECT_ROOT`: user-provided path, otherwise the current working directory. In a Hex project it is the directory that holds `.hex/` (normally next to `foundry.toml`).
|
|
26
|
+
- `SKILL_PATH`: this skill's base directory. Claude Code prints it as `Base directory for this skill: …` when the skill loads; use that path. Only if it is missing, Glob exactly `.claude/skills/fuzz/SKILL.md` and take its directory. Never resolve it with a broad Glob (`**/fizz/**`, `**/scripts/run_medusa.js`): pashov's upstream `fizz` may be installed too, and its scripts write to upstream's paths.
|
|
27
|
+
- `SUITE_DIR`: `test/fizz` relative to `PROJECT_ROOT`. Pass `--suite-dir` to suite-generation steps.
|
|
28
|
+
- `META_DIR`: `.hex/fuzz/fizz_data` relative to `PROJECT_ROOT`. Pass `--meta-dir` to metadata steps.
|
|
29
|
+
- Optional contract arguments narrow handler generation to specific contracts.
|
|
30
|
+
- `--no-invariants` skips Step 9 only.
|
|
31
|
+
- `--max` (or `--opus`, or "max quality") upgrades every subagent in this run from Sonnet to Opus. See "Subagent Model" below.
|
|
32
|
+
- `--guided` / `--automatic` selects the run mode. See "Run Mode" below.
|
|
33
|
+
|
|
34
|
+
## Run Mode
|
|
35
|
+
|
|
36
|
+
The skill runs in one of two modes, resolved once at the start of the run and reused for every checkpoint below:
|
|
37
|
+
|
|
38
|
+
- `{MODE} = "guided"` — the parent agent pauses for user input at key checkpoints: Step 3 (additional docs), Step 4 (interactive function picker UI), Step 4.5 (cost confirmation), Step 6 (setup review), Step 8 (per-cycle coverage decision), Step 9c (property review), Step 10 (fuzzer choice).
|
|
39
|
+
- `{MODE} = "automatic"` — the parent agent never pauses. Step 4 runs with `--auto`, Step 8 loops up to 3 coverage cycles then proceeds, Step 10 defaults to Medusa, and the cost estimate from Step 4.5 is printed but not gated on user confirmation.
|
|
40
|
+
|
|
41
|
+
### Resolving `{MODE}`
|
|
42
|
+
|
|
43
|
+
- If the user invoked with `--guided` / "guided mode" / "walk me through" / "let me review" → `{MODE} = "guided"`.
|
|
44
|
+
- If the user invoked with `--automatic` / `--auto` / "unguided" / "run the whole thing" / "no prompts" → `{MODE} = "automatic"`.
|
|
45
|
+
- Otherwise, leave `{MODE}` unresolved; Step 0 asks for it via the selection prompt **after** printing the banner.
|
|
46
|
+
|
|
47
|
+
Every subsequent instruction referencing `{MODE}` must substitute the resolved value. Do NOT switch modes mid-run.
|
|
48
|
+
|
|
49
|
+
## Subagent Model
|
|
50
|
+
|
|
51
|
+
All subagents spawned by this skill (Step 3 fallback Protocol Analyzer, the 5 Step 9b discovery agents, the Step 9c Synthesizer, the 2 Step 9d Implementers, and the Step 11 Report Writer) default to **Sonnet** for cost and latency.
|
|
52
|
+
|
|
53
|
+
The parent agent orchestrating the pipeline is whatever model the user's Claude Code session is running (this skill does not control it). Only the delegated subagents are covered by `{AGENT_MODEL}`.
|
|
54
|
+
|
|
55
|
+
### Resolving `{AGENT_MODEL}`
|
|
56
|
+
|
|
57
|
+
Resolve once at the start of the run and reuse it for every spawn below:
|
|
58
|
+
|
|
59
|
+
- If the user invoked with `--max` / `--opus` / "max quality" / "run on opus" / similar → `{AGENT_MODEL} = "opus"`.
|
|
60
|
+
- If the user invoked with `--sonnet` / "use sonnet" / "default model" → `{AGENT_MODEL} = "sonnet"`.
|
|
61
|
+
- Otherwise, leave `{AGENT_MODEL}` unresolved; Step 0 asks for it via the selection prompt **after** printing the banner.
|
|
62
|
+
|
|
63
|
+
Every subsequent spawn instruction below references `{AGENT_MODEL}` — substitute the resolved value when making the actual tool call. Do NOT mix tiers within a single run.
|
|
64
|
+
|
|
65
|
+
## Step 0: Print Banner
|
|
66
|
+
|
|
67
|
+
At the start of every skill run, **first** print this banner once before any other output — including any selection prompt:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
Hex /fuzz: accepted invariants → Echidna/Medusa (fork of pashov's fizz)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
After the banner, resolve `{MODE}` per the "Run Mode" section and `{AGENT_MODEL}` per the "Subagent Model" section. For any value still unresolved from invocation flags, ask the user via a single `AskUserQuestion` tool call containing only the unresolved questions (skip the call entirely if both were resolved from flags).
|
|
74
|
+
|
|
75
|
+
**Output discipline (mandatory)**: Between the banner block and the `AskUserQuestion` invocation, emit **no user-facing text whatsoever** — no "I'll ask about…", no "loading the tool…", no acknowledgement that flags were missing. If `AskUserQuestion`'s schema needs to be fetched via `ToolSearch` first, do that silently as well. The user should see banner → selection UI → resolved-values lines, with nothing in between. This overrides the default behavior of narrating intent before tool calls.
|
|
76
|
+
|
|
77
|
+
- **Question for `{MODE}`** — `header: "Run mode"`, `question: "How should I run?"`, options:
|
|
78
|
+
- `label: "Automatic (Recommended)"`, `description: "Run end-to-end with no prompts."`
|
|
79
|
+
- `label: "Guided"`, `description: "Pause at 7 checkpoints: extra docs, entry-point picker (browser UI), cost confirm, setup review, per-cycle coverage decision, property review, fuzzer choice."`
|
|
80
|
+
- **Question for `{AGENT_MODEL}`** — `header: "Subagent model"`, `question: "Which model should drive the subagents?"`, options:
|
|
81
|
+
- `label: "Sonnet (Recommended)"`, `description: "Default. Faster and cheaper for the 5 discovery agents, synthesizer, and 2 implementers."`
|
|
82
|
+
- `label: "Opus"`, `description: "Higher quality but ~10× the cost. Equivalent to passing --max / --opus."`
|
|
83
|
+
|
|
84
|
+
Map the user's selections back to `{MODE}` (`automatic` / `guided`) and `{AGENT_MODEL}` (`sonnet` / `opus`), then print these two lines so the resolved values are visible in transcript:
|
|
85
|
+
|
|
86
|
+
- `Mode: guided` or `Mode: automatic` — the resolved `{MODE}`.
|
|
87
|
+
- `Subagent model: sonnet` (default) or `Subagent model: opus (--max)` (if `--max` / `--opus` / "max quality" / "use opus" / Opus selection was requested).
|
|
88
|
+
|
|
89
|
+
## Step 1: Verify Tooling And Environment
|
|
90
|
+
|
|
91
|
+
Run sequentially:
|
|
92
|
+
|
|
93
|
+
0. (Hex) Run `cd {PROJECT_ROOT} && npx --no-install hex invariant list --status accepted --json`. If it fails (no Hex project here) or prints `[]`, stop now and tell the auditor what Step 3 says. There is no point compiling first.
|
|
94
|
+
1. Read [template-map.md](./references/template-map.md).
|
|
95
|
+
2. Run `forge --version`.
|
|
96
|
+
3. If `forge --version` fails, tell the user that Foundry is missing and give the exact commands to run themselves (do not install anything): `curl -L https://foundry.paradigm.xyz | bash`, then `foundryup` in a new shell, then re-run `/fuzz`. Official documentation:
|
|
97
|
+
Foundry install guide: `https://www.getfoundry.sh/introduction/installation`
|
|
98
|
+
4. If `forge --version` fails, stop here. Foundry is required before proceeding with the rest of the workflow.
|
|
99
|
+
5. Run `bash {SKILL_PATH}/scripts/ensure_foundry.sh {PROJECT_ROOT}`.
|
|
100
|
+
6. If `foundry.toml` is missing, allow `ensure_foundry.sh` to create one. If it fails, stop and report the error.
|
|
101
|
+
7. Run `medusa --version`.
|
|
102
|
+
8. Run `echidna --version`.
|
|
103
|
+
9. If either command fails, tell the user which tool is missing, how to install it, and to re-run `/fuzz` afterwards. Do not install anything yourself.
|
|
104
|
+
- Medusa: `brew install medusa`, or put a prebuilt binary from `https://github.com/crytic/medusa/releases` on `PATH`.
|
|
105
|
+
- Echidna: `brew install echidna`, or put a prebuilt binary from `https://github.com/crytic/echidna/releases` on `PATH`.
|
|
106
|
+
- Both compile the project through `crytic-compile` (`pipx install crytic-compile`, or `pip3 install crytic-compile`). Slither is optional (`pipx install slither-analyzer`); without it, set `disableSlither: true` in `echidna.yaml` if Echidna complains. Give these commands too when a later `medusa`/`echidna` run fails on a crytic-compile or slither error.
|
|
107
|
+
Medusa install guide: `https://secure-contracts.com/program-analysis/medusa/docs/src/getting_started/installation.html`
|
|
108
|
+
Echidna install guide: `https://secure-contracts.com/program-analysis/echidna/introduction/installation.html`
|
|
109
|
+
10. If `medusa --version` fails, stop here. Medusa is required before proceeding with the rest of the workflow.
|
|
110
|
+
11. If `echidna --version` fails but Foundry and Medusa are installed, you may continue, but keep the installation recommendation in the user-facing summary because Echidna is still expected for the full workflow.
|
|
111
|
+
|
|
112
|
+
## Step 2: Compile And Extract
|
|
113
|
+
|
|
114
|
+
Run sequentially:
|
|
115
|
+
|
|
116
|
+
1. Read `{PROJECT_ROOT}/foundry.toml`.
|
|
117
|
+
2. Run `cd {PROJECT_ROOT} && forge build`.
|
|
118
|
+
3. Run `node {SKILL_PATH}/scripts/extract_abis.js {PROJECT_ROOT} --meta-dir {META_DIR}`.
|
|
119
|
+
|
|
120
|
+
## Step 3: Understand The Protocol
|
|
121
|
+
|
|
122
|
+
This step exists to drive setup, handler selection, and invariant generation quality.
|
|
123
|
+
|
|
124
|
+
If `{MODE} = "guided"`, before touching any analysis source first ask the user: *"Any additional docs, links, whitepapers, spec files, or prior-audit notes I should consider? (paste paths or URLs, or reply 'none')"*. If the user provides anything, write the raw list to `{PROJECT_ROOT}/{META_DIR}/additional-context.md` (one entry per line, include URLs verbatim). Later sub-steps of this step — and Step 9a — must read that file if it exists and fold it into the protocol-understanding context.
|
|
125
|
+
|
|
126
|
+
### Hex inputs (replaces upstream's x-ray)
|
|
127
|
+
|
|
128
|
+
This fork reads the protocol from Hex. It never invokes, installs or clones the `x-ray` skill (or any other), and it does not check upstream for new versions. Read `{SKILL_PATH}/references/hex-invariants.md` first.
|
|
129
|
+
|
|
130
|
+
1. **Accepted invariants: the property list.** Run:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
mkdir -p {PROJECT_ROOT}/{META_DIR}
|
|
134
|
+
cd {PROJECT_ROOT} && npx --no-install hex invariant list --status accepted --json > {META_DIR}/hex-invariants.json
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Each entry is `{id: "INV-NNN", statement, kind, scope: {contracts, functions}, evidence: [{file, line_start, line_end}], on_chain_enforced, status, test?}`. If the command fails, report its error and stop. **If the array is empty, stop here.** Tell the auditor that `/fuzz` fuzzes accepted invariants only and none is accepted yet. To see the proposals, run `npx --no-install hex invariant list`. Accept the ones that hold with `npx --no-install hex invariant accept INV-001 INV-004 …` or on the dashboard's Model page, then re-run `/fuzz`. Do not substitute a property list of your own.
|
|
138
|
+
|
|
139
|
+
2. **The protocol model.** If `{PROJECT_ROOT}/.hex/model/protocol.json` exists, read it first as the primary project-understanding source (`npx --no-install hex model show` prints it, `npx --no-install hex model show <section>` one section):
|
|
140
|
+
- `actors` and `privileges`: actor roles, permissioned actions, the admin handlers.
|
|
141
|
+
- `assets`: seeded balances and approvals.
|
|
142
|
+
- `accounting` (equations, with the functions that update each term) and `state_machines`: ghosts, snapshots and invariant wiring.
|
|
143
|
+
- `risky_flows`: handler shaping.
|
|
144
|
+
- `external_dependencies`: mocks.
|
|
145
|
+
- `trust_assumptions`: what the harness may treat as trusted.
|
|
146
|
+
|
|
147
|
+
Claims a skeptic marked `contested` are doubtful: check them in the code before relying on them.
|
|
148
|
+
|
|
149
|
+
3. **Exact facts.** For structural questions, use the facts instead of grep: `npx --no-install hex facts query <callers|callees|readers|writers|layout|linearization|entry-points|reach|function> [ref]`.
|
|
150
|
+
- `entry-points`: Step 4.
|
|
151
|
+
- `layout <Contract>` and `writers <Contract.var>`: aggregate variables and ghosts in Step 9a.
|
|
152
|
+
- `linearization <Contract>`: harness contracts.
|
|
153
|
+
- `function <name>`: exact function ids.
|
|
154
|
+
|
|
155
|
+
If it reports that `.hex/facts.json` is missing, run `npx --no-install hex facts` once.
|
|
156
|
+
|
|
157
|
+
If `{PROJECT_ROOT}/.hex/model/protocol.json` does NOT exist (the auditor skipped `/init-audit`), run the Protocol Analyzer fallback directly. There is no acquisition protocol to run first.
|
|
158
|
+
|
|
159
|
+
Fallback: Read `{SKILL_PATH}/agents/protocol-analyzer.md`, replace `{SKILL_PATH}` with the actual `{SKILL_PATH}`, `{PROJECT_ROOT}` with the actual `{PROJECT_ROOT}`, and `{META_DIR}` with the actual `{META_DIR}`, then spawn as a `general-purpose` agent with `model: "{AGENT_MODEL}"`. The agent reads the source files, then writes the analysis to `{PROJECT_ROOT}/{META_DIR}/protocol-understanding.md` so that later steps can read it back instead of relying on conversation context.
|
|
160
|
+
|
|
161
|
+
From the Hex model (or `protocol-understanding.md`) and the accepted invariants infer and summarize:
|
|
162
|
+
|
|
163
|
+
- deployment order
|
|
164
|
+
- constructor parameter meaning
|
|
165
|
+
- required post-deploy initialization
|
|
166
|
+
- actor roles and permissioned actions
|
|
167
|
+
- approvals, liquidity, or other state needed before handlers will be useful
|
|
168
|
+
- which external functions are real fuzzing entry points versus protocol-internal plumbing
|
|
169
|
+
- how each accepted invariant can be observed from the harness (the contracts, state and functions it touches), plus any further candidates for Step 9 to propose
|
|
170
|
+
|
|
171
|
+
If something is still ambiguous after those reads, keep going with a conservative assumption and leave a targeted TODO later instead of guessing broadly.
|
|
172
|
+
|
|
173
|
+
Do not plan full ghost-variable layouts, snapshot structs, or final implementation details here. Do record the likely invariants clearly so Step 9 can reuse them from `{PROJECT_ROOT}/{META_DIR}/hex-invariants.json`, `{PROJECT_ROOT}/.hex/model/protocol.json` or `{PROJECT_ROOT}/{META_DIR}/protocol-understanding.md` as its starting point.
|
|
174
|
+
|
|
175
|
+
## Step 4: Select Entry Points
|
|
176
|
+
|
|
177
|
+
Read [selection-policy.md](./references/selection-policy.md).
|
|
178
|
+
|
|
179
|
+
Create `{PROJECT_ROOT}/{META_DIR}/entry-point-selection.json` as a filtered copy of `{PROJECT_ROOT}/{META_DIR}/contracts.json` that keeps the functions most likely to produce useful state transitions.
|
|
180
|
+
|
|
181
|
+
Build the preselection from the protocol understanding gathered in Step 3 — primarily the exact entry points (`npx --no-install hex facts query entry-points`) with the model's `actors` and `privileges` (if available), and source-level access control observations. If Step 3 produced an entry-point map with caller or access annotations (`npx --no-install hex facts query callers <Contract.fn>` shows contract-to-contract callers), use that as the primary filter: exclude functions marked as internal-caller-only or contract-to-contract plumbing. Use `{PROJECT_ROOT}/{META_DIR}/contracts.json` only as the structural template for the output JSON format, not to decide which functions to include.
|
|
182
|
+
|
|
183
|
+
Then run:
|
|
184
|
+
|
|
185
|
+
- If `{MODE} = "automatic"`:
|
|
186
|
+
`node {SKILL_PATH}/scripts/select_functions.js {PROJECT_ROOT} --contracts {PROJECT_ROOT}/{META_DIR}/contracts.json --selection {PROJECT_ROOT}/{META_DIR}/entry-point-selection.json --meta-dir {META_DIR} --auto`
|
|
187
|
+
- If `{MODE} = "guided"`:
|
|
188
|
+
`node {SKILL_PATH}/scripts/select_functions.js {PROJECT_ROOT} --contracts {PROJECT_ROOT}/{META_DIR}/contracts.json --selection {PROJECT_ROOT}/{META_DIR}/entry-point-selection.json --meta-dir {META_DIR}`
|
|
189
|
+
|
|
190
|
+
The `--auto` flag accepts the inferred selection and exits immediately. Without it, the script opens a browser UI with the inferred selection pre-checked so the user can adjust and confirm. Both paths write `entry-point-selection.json`.
|
|
191
|
+
|
|
192
|
+
After the script completes, read `{PROJECT_ROOT}/{META_DIR}/entry-point-selection.json`.
|
|
193
|
+
|
|
194
|
+
If the script exits before writing `entry-point-selection.json`, stop and report that failure.
|
|
195
|
+
|
|
196
|
+
Print a short summary:
|
|
197
|
+
|
|
198
|
+
- selected contracts
|
|
199
|
+
- selected functions by contract
|
|
200
|
+
- notable excluded functions
|
|
201
|
+
|
|
202
|
+
### Dispatcher for Low-Frequency Functions
|
|
203
|
+
|
|
204
|
+
After reading the selection, classify the selected functions into two tiers:
|
|
205
|
+
|
|
206
|
+
- **Primary**: core user flows that should be called frequently by the fuzzer (deposit, withdraw, mint, redeem, borrow, repay, swap, stake, unstake, claim, liquidate, etc.)
|
|
207
|
+
- **Secondary**: less common functions that are still useful but should be called less often (admin setters, configuration changes, pause/unpause, role grants, parameter tuning, etc.)
|
|
208
|
+
|
|
209
|
+
Write this classification to `{PROJECT_ROOT}/{META_DIR}/entry-point-selection.json` by adding a `"tier": "primary"` or `"tier": "secondary"` field to each function entry.
|
|
210
|
+
|
|
211
|
+
In Step 7, secondary-tier functions will be wrapped in a dispatcher handler that groups them behind a single entry point with an enum selector. This reduces call frequency naturally without excluding them entirely — the fuzzer picks a random selector value, so secondary functions get exercised occasionally but don't dominate the call sequence.
|
|
212
|
+
|
|
213
|
+
If the user already excluded a function during selection, it stays excluded. The dispatcher is only for functions the user chose to keep but that should be deprioritized.
|
|
214
|
+
|
|
215
|
+
`{PROJECT_ROOT}/{META_DIR}/entry-point-selection.json` limits handler generation only. It does not limit the setup dependency graph.
|
|
216
|
+
|
|
217
|
+
## Step 4.5: Cost Estimate
|
|
218
|
+
|
|
219
|
+
Run:
|
|
220
|
+
|
|
221
|
+
`node {SKILL_PATH}/scripts/estimate_cost.js {PROJECT_ROOT} --meta-dir {META_DIR} --model {AGENT_MODEL} --mode {MODE}`
|
|
222
|
+
|
|
223
|
+
The script reads `entry-point-selection.json`, applies a size bucket based on selected-function count, and writes `{PROJECT_ROOT}/{META_DIR}/cost-estimate.md` with a per-stage breakdown plus a total and an expected range. The numbers are Anthropic list-price ballparks; actual cost varies with coverage cycles, re-runs, and prompt-cache hit rate.
|
|
224
|
+
|
|
225
|
+
Print the cost estimate table to the user. Then:
|
|
226
|
+
|
|
227
|
+
- If `{MODE} = "automatic"`: continue to Step 5 without pausing.
|
|
228
|
+
- If `{MODE} = "guided"`: ask the user *"Proceed with this estimate, or abort?"* and wait for confirmation before continuing. If the user aborts, stop the run and report where the artifacts so far were written.
|
|
229
|
+
|
|
230
|
+
## Step 5: Generate Scaffold
|
|
231
|
+
|
|
232
|
+
Run:
|
|
233
|
+
|
|
234
|
+
`node {SKILL_PATH}/scripts/generate_suite.js {PROJECT_ROOT} --suite-dir {SUITE_DIR} --meta-dir {META_DIR}`
|
|
235
|
+
|
|
236
|
+
This copies the full template scaffold into `{PROJECT_ROOT}/{SUITE_DIR}/`, including core harness files and utility files such as `utils/MockERC20.sol`. It also writes the fuzzer config files (`echidna.yaml`, `medusa.json`) into `{PROJECT_ROOT}/`.
|
|
237
|
+
|
|
238
|
+
It also reads `{PROJECT_ROOT}/{META_DIR}/entry-point-selection.json` and generates one stub handler file per selected contract under `{PROJECT_ROOT}/{SUITE_DIR}/handlers/`. Those stubs include the clamped and unclamped section headers but no sample handler functions. `Handlers.sol` is scaffolded to import and inherit from all generated handler stubs.
|
|
239
|
+
|
|
240
|
+
Treat the copied files as the starting point only. The next steps must modify them to fit the target protocol.
|
|
241
|
+
|
|
242
|
+
## Step 6: Modify Core Files And Wire Setup
|
|
243
|
+
|
|
244
|
+
Read [setup-playbook.md](./references/setup-playbook.md) and [template-map.md](./references/template-map.md).
|
|
245
|
+
|
|
246
|
+
Modify the scaffolded core files under `{PROJECT_ROOT}/{SUITE_DIR}/`. Use [template-map.md](./references/template-map.md) as the source of truth for the inheritance chain, file roles, and which scaffolded files are expected to be refined in this step versus later steps.
|
|
247
|
+
|
|
248
|
+
Use [setup-playbook.md](./references/setup-playbook.md) as the source of truth for:
|
|
249
|
+
|
|
250
|
+
- proxy and upgradeability detection
|
|
251
|
+
- setup requirements and good defaults
|
|
252
|
+
- mock-versus-real dependency choices
|
|
253
|
+
- signature-dependent setup guidance
|
|
254
|
+
- `Base.sol` integration points and TODO/FIXME policy
|
|
255
|
+
|
|
256
|
+
When the target protocol depends on simple external ERC20s that are not part of the in-scope deployment graph, prefer the scaffolded `utils/MockERC20.sol` helper unless the project already includes a more faithful token mock.
|
|
257
|
+
|
|
258
|
+
The key output of this step is a **compiling** scaffold with a realistic `Base.sol::setup()` function and the rest of the core scaffold adjusted to match it.
|
|
259
|
+
|
|
260
|
+
If `{MODE} = "guided"`, after the edits to `Base.sol` are complete and before running `forge build`, print a **Setup Review** block summarising what was wired:
|
|
261
|
+
|
|
262
|
+
- Contracts deployed in `setup()` (name + address variable + constructor args source)
|
|
263
|
+
- Proxies detected and which implementation each wraps
|
|
264
|
+
- Mocks vs real dependencies used, with the reason for each mock
|
|
265
|
+
- Actors configured (addresses + role), and which ones the fuzzer will impersonate via handler caller selection
|
|
266
|
+
- Seeded balances (token, recipient, amount)
|
|
267
|
+
- Roles / access-control grants (role, grantee)
|
|
268
|
+
- Approvals (token, owner, spender, amount)
|
|
269
|
+
|
|
270
|
+
Then ask the user: *"Setup looks right? Reply 'proceed' to build, or tell me what to adjust."* If the user requests adjustments, apply them and re-print the review block; loop until they approve. In `{MODE} = "automatic"`, skip the review block and continue directly.
|
|
271
|
+
|
|
272
|
+
Run `cd {PROJECT_ROOT} && forge build` before moving on.
|
|
273
|
+
|
|
274
|
+
## Step 7: Generate Handlers
|
|
275
|
+
|
|
276
|
+
Read [handler-patterns.md](./references/handler-patterns.md).
|
|
277
|
+
|
|
278
|
+
First, run the handler generation script to produce pre-populated stubs with correct function signatures and type mappings:
|
|
279
|
+
|
|
280
|
+
`node {SKILL_PATH}/scripts/generate_handlers.js {PROJECT_ROOT} --suite-dir {SUITE_DIR} --meta-dir {META_DIR}`
|
|
281
|
+
|
|
282
|
+
Then read these in parallel:
|
|
283
|
+
|
|
284
|
+
- `{PROJECT_ROOT}/{SUITE_DIR}/handlers/Handlers.sol`
|
|
285
|
+
- each generated `{PROJECT_ROOT}/{SUITE_DIR}/handlers/<Contract>Handler.sol`
|
|
286
|
+
- each selected contract source file
|
|
287
|
+
|
|
288
|
+
Then refine the generated `{PROJECT_ROOT}/{SUITE_DIR}/handlers/<Contract>Handler.sol` for the selected contracts. The stubs already contain correct signatures and clamping hints — focus on wiring the actual protocol calls, adding semantic clamping, and implementing boundary-value stress variants.
|
|
289
|
+
|
|
290
|
+
Use [handler-patterns.md](./references/handler-patterns.md) as the source of truth for:
|
|
291
|
+
|
|
292
|
+
- clamped versus unclamped handler structure
|
|
293
|
+
- handler shaping and semantic action selection
|
|
294
|
+
- caller context
|
|
295
|
+
- clamping strategy
|
|
296
|
+
- edge-case and signature-dependent handler guidance
|
|
297
|
+
|
|
298
|
+
Update `Handlers.sol` to import and inherit from all generated handlers.
|
|
299
|
+
|
|
300
|
+
Run `cd {PROJECT_ROOT} && forge build` and fix compile issues before moving on.
|
|
301
|
+
|
|
302
|
+
## Step 8: Reach Coverage With Medusa
|
|
303
|
+
|
|
304
|
+
Before generating invariants, ensure the generated harness can drive enough protocol coverage under Medusa.
|
|
305
|
+
|
|
306
|
+
### Via-IR Coverage Deflation Handling
|
|
307
|
+
|
|
308
|
+
When `via_ir = true` is set in `foundry.toml`, the Yul IR optimizer aggressively merges and eliminates branches. This deflates Medusa's coverage numbers — you may be at 85% source coverage but Medusa reports 65%. This must be handled before the first Medusa run.
|
|
309
|
+
|
|
310
|
+
**Step 8.0: Detect and configure fuzz profile.**
|
|
311
|
+
|
|
312
|
+
1. Read `{PROJECT_ROOT}/foundry.toml` and check whether `via_ir = true` is set under `[profile.default]` or at the top level.
|
|
313
|
+
2. If `via_ir` is not enabled, skip this subsection — no fuzz profile is needed.
|
|
314
|
+
3. If `via_ir` is enabled, run:
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
bash {SKILL_PATH}/scripts/setup_fuzz_profile.sh {PROJECT_ROOT}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
This script:
|
|
321
|
+
- Appends a `[profile.fuzz]` section to `foundry.toml` with `via_ir = false`
|
|
322
|
+
- Runs `FOUNDRY_PROFILE=fuzz forge build`
|
|
323
|
+
- If compilation succeeds: exits 0, prints `FUZZ_PROFILE=no-ir`
|
|
324
|
+
- If "stack too deep" error: retries with `via_ir = true` and `optimizer_runs = 0`, exits 0, prints `FUZZ_PROFILE=ir-no-opt`
|
|
325
|
+
- If both fail: exits 1 (use default profile, accept deflated coverage)
|
|
326
|
+
|
|
327
|
+
4. Read the script output to determine the fuzz profile mode:
|
|
328
|
+
- `FUZZ_PROFILE=no-ir` → accurate coverage, use standard targets
|
|
329
|
+
- `FUZZ_PROFILE=ir-no-opt` → reduced deflation but still some; lower coverage targets by ~10%
|
|
330
|
+
- Script failed → fall back to default profile; lower coverage targets by ~15-20%
|
|
331
|
+
|
|
332
|
+
5. Record the profile mode in `{PROJECT_ROOT}/{META_DIR}/coverage-targets.md` at the top:
|
|
333
|
+
- `no-ir`: "Fuzz profile: via_ir disabled — coverage numbers are accurate"
|
|
334
|
+
- `ir-no-opt`: "Fuzz profile: via_ir required (stack too deep), optimizer_runs=0 — coverage deflated ~10%, targets adjusted"
|
|
335
|
+
- default fallback: "Fuzz profile: via_ir required with optimizer — coverage deflated ~15-20%, targets adjusted"
|
|
336
|
+
|
|
337
|
+
6. For all subsequent `forge build` commands in Steps 8–11, use:
|
|
338
|
+
- `cd {PROJECT_ROOT} && FOUNDRY_PROFILE=fuzz forge build` (if fuzz profile was created)
|
|
339
|
+
- `cd {PROJECT_ROOT} && forge build` (if no fuzz profile needed)
|
|
340
|
+
|
|
341
|
+
Store the build command in a variable `{FUZZ_BUILD_CMD}` for reuse in later steps.
|
|
342
|
+
|
|
343
|
+
### Medusa Runs
|
|
344
|
+
|
|
345
|
+
Every Medusa run in this step must use `run_medusa.js`, including reruns after harness changes. Do not switch to raw `medusa fuzz` for later cycles in this step.
|
|
346
|
+
|
|
347
|
+
Before launching Medusa, rebuild with the fuzz profile if one was configured:
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
{FUZZ_BUILD_CMD}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Run the Medusa script asynchronously using the agent's command-execution tool. This is critical — do NOT use shell backgrounding (`&`), do NOT use `sleep` + `tail` to poll, and do NOT wait synchronously in a single blocking command. Start the process in a way the agent runtime can track and notify on completion.
|
|
354
|
+
|
|
355
|
+
```
|
|
356
|
+
node {SKILL_PATH}/scripts/run_medusa.js {PROJECT_ROOT} --meta-dir {META_DIR} --coverage-mode
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
The wrapper starts a temporary local browser log viewer and prints its URL, but does not open the browser by default. Read the viewer URL from the wrapper output and provide it to the user. Add `--logs` to the command only if the user asks for the viewer to open in their browser automatically.
|
|
360
|
+
|
|
361
|
+
When the background command completes and you are notified, inspect the resulting coverage with focus on the core protocol contracts, not peripheral mocks or helper libraries.
|
|
362
|
+
|
|
363
|
+
### Dynamic Coverage Targets
|
|
364
|
+
|
|
365
|
+
Not all contracts require the same coverage. Assign per-contract targets based on the contract's role:
|
|
366
|
+
|
|
367
|
+
| Contract Role | Target (no-ir) | Target (ir-no-opt) | Target (ir fallback) |
|
|
368
|
+
|---|---|---|---|
|
|
369
|
+
| Core protocol logic (vault, pool, lending core, staking engine) | 80%+ | 70%+ | 65%+ |
|
|
370
|
+
| Access control / role management | 60%+ | 50%+ | 45%+ |
|
|
371
|
+
| Peripheral helpers (routers, views, adapters) | 50%+ | 40%+ | 35%+ |
|
|
372
|
+
| Libraries and math utilities | Coverage inherited from callers | Same | Same |
|
|
373
|
+
|
|
374
|
+
Use the column matching the fuzz profile mode determined in Step 8.0.
|
|
375
|
+
|
|
376
|
+
After the first Medusa run, review the per-contract coverage report and classify each contract. If a contract has legitimately unreachable paths in the harness context (e.g., fork-only branches, multi-block MEV paths, oracle-failure paths), note them and adjust that contract's target downward rather than wasting cycles on unreachable code.
|
|
377
|
+
|
|
378
|
+
Write the per-contract targets and any skip justifications to `{PROJECT_ROOT}/{META_DIR}/coverage-targets.md` so the user can review them.
|
|
379
|
+
|
|
380
|
+
### Coverage Iteration Loop
|
|
381
|
+
|
|
382
|
+
- with `--coverage-mode`, the wrapper runs `medusa fuzz --timeout 300`, allows at least 60 seconds of fuzzing, then stops earlier if 5 consecutive progress lines show no increase in `branches hit`, and prints the coverage report path when finished (add `--logs` to also open it in the browser)
|
|
383
|
+
- if coverage is below target, improve handler shapes, clamping, setup, approvals, seed balances, caller roles, and any missing lifecycle actions
|
|
384
|
+
- when debugging why a specific handler or call sequence is not reaching the expected code paths, or when validating a hypothesis, use `FoundryTester.sol` to quickly PoC it
|
|
385
|
+
- rerun `{FUZZ_BUILD_CMD}` before each new Medusa run
|
|
386
|
+
- treat one cycle as: run `node {SKILL_PATH}/scripts/run_medusa.js {PROJECT_ROOT} --meta-dir {META_DIR} --coverage-mode`, inspect coverage, adjust the harness, then rebuild
|
|
387
|
+
|
|
388
|
+
After each cycle, build and print a per-contract coverage summary table from the Medusa coverage report:
|
|
389
|
+
|
|
390
|
+
| Contract | Role | Target | Hit | Status |
|
|
391
|
+
|---|---|---|---|---|
|
|
392
|
+
|
|
393
|
+
`Status` is `✅` if Hit ≥ Target, else `❌`. Append the same table to `{PROJECT_ROOT}/{META_DIR}/coverage-targets.md` under a timestamped `## Cycle N` heading so the history is preserved.
|
|
394
|
+
|
|
395
|
+
Then branch on `{MODE}`:
|
|
396
|
+
|
|
397
|
+
- `{MODE} = "automatic"`: if all contracts meet target, give a brief summary and proceed. Otherwise loop; cap at 3 cycles total, then log remaining gaps in `coverage-targets.md` and proceed to the next step with the current harness.
|
|
398
|
+
- `{MODE} = "guided"`: after every cycle (including cycle 1), ask the user *"iterate / adjust targets / proceed"*. `iterate` = run another cycle with the current harness adjustments. `adjust targets` = let the user edit per-contract targets in `coverage-targets.md` before the next cycle. `proceed` = exit the loop regardless of gaps. Honour the user's choice; there is no hard cap in guided mode.
|
|
399
|
+
|
|
400
|
+
After exiting the loop, provide the coverage report path for optional review: `{PROJECT_ROOT}/{META_DIR}/corpus_medusa/coverage/coverage_report.html`.
|
|
401
|
+
|
|
402
|
+
### Acceptable Skip Reasons
|
|
403
|
+
|
|
404
|
+
It is acceptable to skip coverage for specific functions or paths when:
|
|
405
|
+
|
|
406
|
+
- the function requires external state that cannot be simulated (e.g., specific oracle prices from a live feed)
|
|
407
|
+
- the path is a revert-only guard that is intentionally unreachable in the harness (e.g., `require(msg.sender == bridgeContract)`)
|
|
408
|
+
- the function is behind a time-lock or multi-sig that the harness doesn't simulate
|
|
409
|
+
- the function interacts with an external protocol that is not mocked
|
|
410
|
+
|
|
411
|
+
Document each skip in `{PROJECT_ROOT}/{META_DIR}/coverage-targets.md` with the reason.
|
|
412
|
+
|
|
413
|
+
Do not move to invariant generation while Medusa coverage is still clearly too low for the selected flows, unless the user explicitly tells you to proceed anyway.
|
|
414
|
+
|
|
415
|
+
## Step 9: Generate Invariants (5 Parallel Discovery Agents + Synthesizer + 2 Implementers)
|
|
416
|
+
|
|
417
|
+
Skip this step only when the user passed `--no-invariants`.
|
|
418
|
+
|
|
419
|
+
This is the make-or-break step. It uses **5 specialized discovery agents in parallel**, each applying a different invariant discovery approach drawn from 50+ real DeFi bugs caught by fuzzers.
|
|
420
|
+
|
|
421
|
+
### Step 9a: Build Invariant Context
|
|
422
|
+
|
|
423
|
+
Read [property-generation.md](./references/property-generation.md), then build `INVARIANT_CONTEXT` by reading:
|
|
424
|
+
|
|
425
|
+
- the accepted Hex invariants from `{PROJECT_ROOT}/{META_DIR}/hex-invariants.json`, first, under the block below
|
|
426
|
+
- the invariant notes captured in Step 3 from `{PROJECT_ROOT}/.hex/model/protocol.json` (its `accounting`, `state_machines` and `risky_flows` sections) when available, otherwise `{PROJECT_ROOT}/{META_DIR}/protocol-understanding.md`
|
|
427
|
+
- `{PROJECT_ROOT}/{META_DIR}/additional-context.md` if it exists (guided-mode supplementary docs/links from Step 3)
|
|
428
|
+
- all in-scope source files
|
|
429
|
+
- `Base.sol`, `Snapshots.sol`, `Properties.sol`
|
|
430
|
+
- all generated handler files
|
|
431
|
+
|
|
432
|
+
Extract from the codebase:
|
|
433
|
+
- **AGGREGATE_VARIABLES**: grep for variables named `total*`, `sum*`, `accumulated*`, or any variable that multiple functions write to (`npx --no-install hex facts query layout <Contract>` lists the state variables; `npx --no-install hex facts query writers <Contract.var>` lists every function that writes one)
|
|
434
|
+
- **PAIRED_OPERATIONS**: match function pairs (deposit/withdraw, mint/burn, add/remove, lock/unlock, open/close, stake/unstake, borrow/repay, create/destroy, join/exit)
|
|
435
|
+
- **CONVERSION_FUNCTIONS**: grep for `convertTo*`, `preview*`, `toAssets`, `toShares`, or any function mapping between two unit systems
|
|
436
|
+
- **ACCESS_CONTROL**: grep for `onlyOwner`, `onlyAdmin`, `onlyRole`, `require(msg.sender`, custom role modifiers (and read the model's `privileges`)
|
|
437
|
+
|
|
438
|
+
Open `INVARIANT_CONTEXT` with this block (Hex), so every discovery agent knows the property list is fixed:
|
|
439
|
+
|
|
440
|
+
> **Accepted invariants (the property list).** The auditor accepted the invariants below. Each becomes exactly one property, tagged with its `INV-NNN`. For each one, give the most precise check you can (Solidity sketch, ghosts, snapshot fields, the handler it follows) and tag it with the `INV-NNN` it implements. Anything else you find is a *candidate*: report it as usual, with its evidence. It will be proposed to the auditor as a new invariant, not fuzzed in this run.
|
|
441
|
+
>
|
|
442
|
+
> One line per invariant: `INV-NNN (kind; enforced on-chain | not enforced on-chain; scope): statement (evidence file:line)`
|
|
443
|
+
|
|
444
|
+
### Step 9b: Spawn 5 Discovery Agents in Parallel
|
|
445
|
+
|
|
446
|
+
**CRITICAL**: All 5 agents MUST be spawned in a SINGLE message (one tool call per agent, all in the same response).
|
|
447
|
+
|
|
448
|
+
| Agent | File | Discovery Approach |
|
|
449
|
+
|-------|------|-------------------|
|
|
450
|
+
| 1. Conservation Auditor | `{SKILL_PATH}/agents/invariant-discovery/conservation-auditor.md` | Sum-of-parts = tracked-whole for every aggregate variable |
|
|
451
|
+
| 2. Round-Trip & Rounding Analyst | `{SKILL_PATH}/agents/invariant-discovery/roundtrip-rounding-analyst.md` | Forward+inverse operations, directional rounding |
|
|
452
|
+
| 3. State Transition Mapper | `{SKILL_PATH}/agents/invariant-discovery/state-transition-mapper.md` | Postconditions, monotonicity, entity counts, state machine |
|
|
453
|
+
| 4. Adversarial Profit Maximizer | `{SKILL_PATH}/agents/invariant-discovery/adversarial-profit-maximizer.md` | Attacker thinking — DoS, value extraction, edge states |
|
|
454
|
+
| 5. Protocol-Type Specialist | `{SKILL_PATH}/agents/invariant-discovery/protocol-type-specialist.md` | Auto-detect type, apply domain templates (vault/lending/AMM/etc.) |
|
|
455
|
+
|
|
456
|
+
Read each agent file, replace `{INVARIANT_CONTEXT}` and `{FILE_PATHS}` with actual values, spawn as `general-purpose` agent with `model: "{AGENT_MODEL}"`.
|
|
457
|
+
|
|
458
|
+
### Step 9c: Synthesize Property Plan
|
|
459
|
+
|
|
460
|
+
After all 5 agents return, read the Synthesizer agent file:
|
|
461
|
+
|
|
462
|
+
| Agent | File |
|
|
463
|
+
|-------|------|
|
|
464
|
+
| 6. Synthesizer | `{SKILL_PATH}/agents/invariant-discovery/synthesizer.md` |
|
|
465
|
+
|
|
466
|
+
Replace `{AGENT_OUTPUTS}` with the outputs from agents 1-5, `{META_DIR}` with the actual `{META_DIR}` path, `{PROJECT_ROOT}` with the actual `{PROJECT_ROOT}` path, `{SUITE_DIR}` with the actual `{SUITE_DIR}` path, and `{SKILL_PATH}` with the actual `{SKILL_PATH}` path, then spawn as `general-purpose` agent with `model: "{AGENT_MODEL}"`.
|
|
467
|
+
The Synthesizer merges, deduplicates, prioritizes, and writes BOTH:
|
|
468
|
+
- `{PROJECT_ROOT}/{META_DIR}/property-plan.md` — implementation tables with stable Spec IDs (`GL-NN`, `SP-NN`)
|
|
469
|
+
- `{PROJECT_ROOT}/.hex/fuzz/PROPERTIES.md` — English-language spec with `[ ]` checkboxes, one entry per property, identified by the same Spec IDs. This is the artifact that the `/fuzz-convert` command and the implementers in Step 9d operate on. (Hex) One entry per accepted invariant, each tagged `(INV-NNN)` after its Spec ID.
|
|
470
|
+
- (Hex) `.hex/model/invariants.json` — discovery-agent properties that no accepted invariant covers, appended as `status: "proposed"` invariants for the auditor. They are not fuzzed in this run.
|
|
471
|
+
|
|
472
|
+
Each property carries a **Guarantee** tag set at generation time — `SHOULD-HOLD` (explicitly guaranteed by docs/spec/standard or an exact identity, with evidence cited) or `EXPLORATORY` (inferred). This tag is what lets Step 10 triage a violation without post-campaign severity guessing: a violated SHOULD-HOLD property is a confirmed bug, a violated EXPLORATORY property is a lead for human review.
|
|
473
|
+
|
|
474
|
+
**Hex mapping.** When the Synthesizer returns:
|
|
475
|
+
|
|
476
|
+
1. Read `{PROJECT_ROOT}/.hex/fuzz/PROPERTIES.md`. Check that every invariant in `hex-invariants.json` has exactly one entry carrying its `(INV-NNN)` tag and that no entry lacks a tag. Send any gap back to the Synthesizer (SendMessage to the same agent).
|
|
477
|
+
2. Record each mapping, one call per entry:
|
|
478
|
+
|
|
479
|
+
```bash
|
|
480
|
+
npx --no-install hex invariant set-test INV-NNN --tool fizz --property GL-NN --file {SUITE_DIR}/Properties.sol --status not_written
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
3. If the Synthesizer proposed new invariants, run `npx --no-install hex model validate`. Send any error back to the Synthesizer until it passes.
|
|
484
|
+
|
|
485
|
+
Print a summary: "Generated X properties for X accepted invariants (N HIGH, N MEDIUM, N LOW; P SHOULD-HOLD, Q EXPLORATORY); proposed K new invariants for the auditor" with a brief list of the top properties by priority and the ids of the proposed invariants.
|
|
486
|
+
|
|
487
|
+
If `{MODE} = "guided"`, pause here: tell the user the file path (`{PROJECT_ROOT}/.hex/fuzz/PROPERTIES.md`), summarise what the Synthesizer produced, and ask *"Review `PROPERTIES.md` and edit freely — rename, add, remove, or reword properties. Keep the Spec IDs (`GL-NN` / `SP-NN`) and their `(INV-NNN)` tags on entries you want implemented, and leave `[ ]` checkboxes unchanged. An entry without an `(INV-NNN)` tag is fuzzed but not tracked in Hex. Reply 'proceed' when done, or 'regenerate' to re-run the Synthesizer with additional guidance."* If they reply `regenerate`, ask what to change, then re-spawn the Synthesizer (Step 9c) with the extra guidance appended to its input. If they reply `proceed`, continue to Step 9d. In `{MODE} = "automatic"`, skip the pause and proceed directly.
|
|
488
|
+
|
|
489
|
+
### Step 9d: Implement Properties (2 Parallel Agents)
|
|
490
|
+
|
|
491
|
+
Read each agent file:
|
|
492
|
+
|
|
493
|
+
| Agent | File | Scope |
|
|
494
|
+
|-------|------|-------|
|
|
495
|
+
| 7A. Global Property Implementer | `{SKILL_PATH}/agents/implementers/global-property-implementer.md` | Ghosts in Base.sol, State in Snapshots.sol, global properties in Properties.sol, harness contracts if needed |
|
|
496
|
+
| 7B. Specific Property Implementer | `{SKILL_PATH}/agents/implementers/specific-property-implementer.md` | Specific properties in Properties.sol, handler wiring (ghost updates + snapshot calls + property assertions) |
|
|
497
|
+
|
|
498
|
+
Replace `{META_DIR}` with the actual `{META_DIR}` path, `{SKILL_PATH}` with the actual `{SKILL_PATH}` path, `{PROJECT_ROOT}` with the actual `{PROJECT_ROOT}` path, and `{SUITE_DIR}` with the actual `{SUITE_DIR}` path, then spawn both as `general-purpose` agents with `model: "{AGENT_MODEL}"` in parallel.
|
|
499
|
+
|
|
500
|
+
Both implementers MUST flip `[ ]` → `[x]` in `{PROJECT_ROOT}/.hex/fuzz/PROPERTIES.md` for each property they actually implement (matching by Spec ID `GL-NN` / `SP-NN`). Properties left as TODO stubs stay `[ ]` so `/fuzz-convert` can pick them up later.
|
|
501
|
+
|
|
502
|
+
### Step 9e: Validate
|
|
503
|
+
|
|
504
|
+
Run `{FUZZ_BUILD_CMD}` after the edits. Fix any compilation errors.
|
|
505
|
+
|
|
506
|
+
If a property is low-confidence after implementation, prefer a commented TODO over a brittle assertion.
|
|
507
|
+
|
|
508
|
+
## Step 10: Run Campaigns
|
|
509
|
+
|
|
510
|
+
After invariant generation and validation, run a full fuzzing campaign to find property violations.
|
|
511
|
+
|
|
512
|
+
### Fuzzer Selection
|
|
513
|
+
|
|
514
|
+
- `{MODE} = "automatic"`: default to **Medusa** — faster with multi-worker parallelism and better suited for initial runs.
|
|
515
|
+
- `{MODE} = "guided"`: ask the user *"Which fuzzer for this campaign — Medusa (default, parallel workers) or Echidna?"* and use their answer. If they express no preference, default to Medusa.
|
|
516
|
+
|
|
517
|
+
Do not run both fuzzers simultaneously — this consumes excessive resources and can cause system instability or crashes. Campaign Iteration (below) is where a complementary run on the other fuzzer is offered.
|
|
518
|
+
|
|
519
|
+
### Running the Campaign
|
|
520
|
+
|
|
521
|
+
Run the wrapper for the chosen fuzzer, either **Medusa** or **Echidna** (ONLY ONE), asynchronously using the agent's command-execution tool, then wait for that tracked background job to finish — the wrapper exits when the fuzzer's own stop condition triggers or the `--timeout` is reached. Both wrappers start a temporary local browser log viewer and print its URL, but do not open the browser by default; read the viewer URL from the wrapper output and provide it to the user. Add `--logs` to the command only if the user asks for the viewer to open in their browser automatically.
|
|
522
|
+
|
|
523
|
+
For **Medusa**, run this command:
|
|
524
|
+
|
|
525
|
+
```
|
|
526
|
+
node {SKILL_PATH}/scripts/run_medusa.js {PROJECT_ROOT} --meta-dir {META_DIR} --timeout 600
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
For **Echidna**, run this command:
|
|
530
|
+
|
|
531
|
+
```
|
|
532
|
+
node {SKILL_PATH}/scripts/run_echidna.js {PROJECT_ROOT} --meta-dir {META_DIR} --timeout 600
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
If Echidna fails with `unlinked libraries detected in bytecode`, link the libraries in `echidna.yaml`:
|
|
536
|
+
|
|
537
|
+
```yaml
|
|
538
|
+
deployContracts: [["0xf1", "Lib1"], ["0xf2", "Lib2"]]
|
|
539
|
+
cryticArgs: ["--compile-libraries=(Lib1,0xf1), (Lib2,0xf2)"]
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
Replace `Lib1`, `Lib2` with the actual library names and `0xf1`, `0xf2` with the desired deployment addresses.
|
|
543
|
+
|
|
544
|
+
### Interpreting Results
|
|
545
|
+
|
|
546
|
+
After the campaign completes:
|
|
547
|
+
|
|
548
|
+
- check for property violations (failed assertions)
|
|
549
|
+
- for each violation, extract the call sequence that triggered it
|
|
550
|
+
- verify the violation is a real bug, not a harness issue — if the property or handler has a bug, fix it and rerun
|
|
551
|
+
- **triage by the violated property's Guarantee tag** (from `PROPERTIES.md`): a violated **SHOULD-HOLD** property is a confirmed bug — the protocol broke a documented/mathematical guarantee, so report it as such; a violated **EXPLORATORY** property is flagged for human review — it may be a real bug or an over-strong inferred assumption, so present the call sequence and let a human judge rather than asserting a bug. Always rule out a harness/property bug first regardless of tag.
|
|
552
|
+
- if no violations were found, report that the campaign completed cleanly with the coverage achieved
|
|
553
|
+
- if violations were found, document each one with the failing property name, its Spec ID and `INV-NNN`, its Guarantee tag, the call sequence, and the contract state at failure
|
|
554
|
+
- (Hex) run Step 12's `npx --no-install hex invariant sync-fuzz` now, so the invariants show this campaign's result even if the run stops before Step 11; Step 12 runs again at the end
|
|
555
|
+
|
|
556
|
+
### Campaign Iteration
|
|
557
|
+
|
|
558
|
+
If the user wants to explore further after the first campaign:
|
|
559
|
+
|
|
560
|
+
- offer to run the other fuzzer (Echidna if Medusa was used, or vice versa) for a complementary pass
|
|
561
|
+
- offer to increase the timeout or test limit
|
|
562
|
+
- offer to adjust handler shapes based on coverage gaps observed during the campaign
|
|
563
|
+
- (Hex) after every extra campaign, write repros for new violations (Step 11, "Generate Violation Repros") and run Step 12 again
|
|
564
|
+
|
|
565
|
+
## Step 11: Validate And Report
|
|
566
|
+
|
|
567
|
+
Run:
|
|
568
|
+
|
|
569
|
+
1. `{FUZZ_BUILD_CMD}`
|
|
570
|
+
2. If `FoundryTester.sol` exists, `cd {PROJECT_ROOT} && FOUNDRY_PROFILE=fuzz forge test --match-contract FoundryTester` (or without `FOUNDRY_PROFILE` if no fuzz profile was created)
|
|
571
|
+
|
|
572
|
+
If validation fails:
|
|
573
|
+
|
|
574
|
+
- fix the specific broken files
|
|
575
|
+
- do not regenerate the whole suite unless the user asks
|
|
576
|
+
- limit repair retries to 3 cycles, then report the remaining issues cleanly
|
|
577
|
+
|
|
578
|
+
### Generate Violation Repros
|
|
579
|
+
|
|
580
|
+
If the campaign in Step 10 found property violations, generate a Foundry reproduction test for each distinct violation in `FoundryTester.sol`. This turns fuzzer output into deterministic, one-command proof that the violation is real.
|
|
581
|
+
|
|
582
|
+
**When to run**: only when `{PROJECT_ROOT}/{META_DIR}/corpus_medusa/test_results/` contains violation JSON files (Medusa) or the Echidna log contains `failed!` lines with call sequences. If the campaign found no violations, skip this sub-step entirely.
|
|
583
|
+
|
|
584
|
+
**How to generate repros**:
|
|
585
|
+
|
|
586
|
+
1. Read each violation file (Medusa: one JSON per violation in `test_results/`; Echidna: parse call sequences from the log after each `failed!` line).
|
|
587
|
+
2. For each distinct violated property (group multiple reproductions of the same property — use only the shortest call sequence):
|
|
588
|
+
- Create a `test_repro_<propertyName>()` function in `FoundryTester.sol`.
|
|
589
|
+
- Replay the shrunk call sequence by calling the handler functions from the JSON `methodSignature` and `inputValues` fields directly.
|
|
590
|
+
- Between calls, use `vm.roll()` and `vm.warp()` to advance block number and timestamp by the `blockNumberDelay` and `blockTimestampDelay` from each call entry.
|
|
591
|
+
- The fuzzer's `from` addresses map to actors by index: `0x10000` → `actors[0]`, `0x20000` → `actors[1]`, `0x30000` → `actors[2]`. The clamped handlers accept an actor seed parameter that runs through `toActor()`, so pass the raw fuzzer input values — the seed modulus selects the right actor.
|
|
592
|
+
- **Two violation patterns require different test structures**:
|
|
593
|
+
- **Global property violations** (`property_*` functions that return `bool`): replay the full call sequence, then assert the property returns `false`: `assertFalse(property_xxx(), "property should be violated");`. The test **passes** when the property is violated.
|
|
594
|
+
- **Inline assertion violations** (`_prop_*` / `_check*` assertions inside handlers that revert via `assert()` / `t()`): the violating handler call will revert with `panic(0x01)` before any post-call assertion can run. Wrap the violating call in `try this._repro_helperN() { revert("assertion should have fired"); } catch {}`, where `_repro_helperN()` is an `external` helper function that calls the handler. The `try/catch` proves the assertion fired. The test **passes** when the catch triggers.
|
|
595
|
+
3. Run `{FUZZ_BUILD_CMD}` and then `cd {PROJECT_ROOT} && FOUNDRY_PROFILE=fuzz forge test --match-contract FoundryTester -vvv` to confirm all repro tests pass.
|
|
596
|
+
4. If a repro test fails to compile or does not reproduce the violation, fix it (max 2 attempts per test). If it still fails, comment out the test body with a `// TODO: manual repro needed — fuzzer sequence did not reproduce under Foundry` note and move on.
|
|
597
|
+
|
|
598
|
+
**Repro naming convention**: `test_repro_<propertyName>` (e.g., `test_repro_property_solvency`, `test_repro_prop_depositIncreasesShares`). If the same property was violated by multiple distinct root causes (different call sequences hitting different code paths), suffix with `_1`, `_2`.
|
|
599
|
+
|
|
600
|
+
(Hex) `<propertyName>` must be the exact name of the property function (the one under its `/// @notice GL-NN:` / `SP-NN:` doctag). That is how `hex invariant sync-fuzz` attributes a violation to its invariant and opens a card for it. For an inline `SP-*` assertion that fired inside a handler, name the repro after the property function, not the handler. A repro that keeps the `TODO: manual repro needed` note is not counted as a repro.
|
|
601
|
+
|
|
602
|
+
### Final Report
|
|
603
|
+
|
|
604
|
+
After validation succeeds, spawn the Report Writer subagent to synthesize the final report. Read `{SKILL_PATH}/agents/report-writer.md`, replace `{SKILL_PATH}` with the actual `{SKILL_PATH}`, `{PROJECT_ROOT}` with the actual `{PROJECT_ROOT}`, `{META_DIR}` with the actual `{META_DIR}`, and `{SUITE_DIR}` with the actual `{SUITE_DIR}`, then spawn as a `general-purpose` agent with `model: "{AGENT_MODEL}"`.
|
|
605
|
+
|
|
606
|
+
The agent reads the campaign outputs (coverage, corpus, `medusa-run.log`, `PROPERTIES.md`, `Properties.sol`, handler files, open TODOs) and writes `{PROJECT_ROOT}/{META_DIR}/report.md`.
|
|
607
|
+
|
|
608
|
+
The report-writer agent will also print the report content to the conversation (so the user sees it inline) and remind the user of the commands to run campaigns manually:
|
|
609
|
+
|
|
610
|
+
- `medusa fuzz` (from project root)
|
|
611
|
+
- `echidna . --contract FuzzTester --config echidna.yaml`
|
|
612
|
+
|
|
613
|
+
### Snapshot For Future Re-Use
|
|
614
|
+
|
|
615
|
+
After the final report is written, capture a sync snapshot so the `/fuzz-sync` skill can detect drift on subsequent source changes without re-running the full pipeline:
|
|
616
|
+
|
|
617
|
+
```
|
|
618
|
+
node {SKILL_PATH}/scripts/fizz_sync.js {PROJECT_ROOT} --init --meta-dir {META_DIR} --suite-dir {SUITE_DIR}
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
If the snapshot already exists (because a prior run already initialised it), re-run with `--refresh-snapshot` instead so the new baseline reflects the current state:
|
|
622
|
+
|
|
623
|
+
```
|
|
624
|
+
node {SKILL_PATH}/scripts/fizz_sync.js {PROJECT_ROOT} --refresh-snapshot --meta-dir {META_DIR} --suite-dir {SUITE_DIR}
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
This writes `{PROJECT_ROOT}/{META_DIR}/last-run.json` — a hash+signature snapshot of the in-scope contracts, handlers, and `PROPERTIES.md` entries. Later, when the user modifies sources and invokes `/fuzz-sync`, that skill diffs against this file to detect added/removed/changed functions, quarantine stale properties, and regenerate only the drifted handler stubs.
|
|
628
|
+
|
|
629
|
+
## Step 12: Sync Results To Hex
|
|
630
|
+
|
|
631
|
+
Run this after every campaign (Step 10 and each Campaign Iteration rerun) and once more at the very end, after the repros, the report and the snapshot:
|
|
632
|
+
|
|
633
|
+
```bash
|
|
634
|
+
cd {PROJECT_ROOT} && npx --no-install hex invariant sync-fuzz
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
It reads:
|
|
638
|
+
|
|
639
|
+
- `.hex/fuzz/PROPERTIES.md`: the `(INV-NNN)` tags and checkboxes.
|
|
640
|
+
- The `/// @notice` doctags under `{SUITE_DIR}`.
|
|
641
|
+
- The latest Medusa/Echidna logs under `{META_DIR}`.
|
|
642
|
+
- The `test_repro_*` tests in `{SUITE_DIR}/FoundryTester.sol`.
|
|
643
|
+
|
|
644
|
+
For each mapped invariant it sets the test status (`passing` / `failing` / `broken` / `not_written`), runs, last run and repro file. For each failing invariant that has a repro and no card yet, it opens a High card on the Hex board (`Invariant broken: <statement>`, Potential column) and links it. It is idempotent. See `{SKILL_PATH}/references/hex-invariants.md` for the exact rules.
|
|
645
|
+
|
|
646
|
+
Summarize its output for the auditor:
|
|
647
|
+
|
|
648
|
+
- invariants passing
|
|
649
|
+
- invariants failing, with the card each one got and whether it is new
|
|
650
|
+
- invariants broken (quarantined, missing code, or not evaluable)
|
|
651
|
+
- invariants not yet run
|
|
652
|
+
- properties it could not map (no `(INV-NNN)` tag)
|
|
653
|
+
- violations it could not attribute: an `SP-*` assertion fired inside a handler but no `test_repro_<property>` exists. Write the repro, then run the sync again.
|
|
654
|
+
|
|
655
|
+
A card for a violated `EXPLORATORY` property still needs the auditor's triage; say so. If Step 9c proposed new invariants, remind the auditor to review them (`npx --no-install hex invariant list --status proposed`, or the dashboard's Model page). Accepted ones are added to this suite with `/fuzz-convert`.
|