hex-audit 0.6.2 → 0.7.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/DEMO.md +13 -0
- package/README.md +60 -6
- package/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/app-build-manifest.json +100 -89
- package/dashboard/.next/app-path-routes-manifest.json +1 -1
- package/dashboard/.next/build-manifest.json +14 -14
- 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 +118 -118
- 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_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/access/page.js +1 -1
- package/dashboard/.next/server/app/access/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/access/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/calls/page.js +1 -1
- package/dashboard/.next/server/app/calls/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/changes/page.js +20 -0
- package/dashboard/.next/server/app/changes/page.js.nft.json +1 -0
- package/dashboard/.next/server/app/changes/page_client-reference-manifest.js +1 -0
- package/dashboard/.next/server/app/conformance/page.js +1 -1
- package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/diagram/page.js +1 -1
- package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/flows/page.js +1 -1
- package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/functions/page.js +1 -1
- package/dashboard/.next/server/app/functions/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/issues/page.js +6 -6
- package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/notes/page.js +3 -3
- package/dashboard/.next/server/app/notes/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/page.js +2 -2
- package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/progress/page.js +1 -1
- package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/report/page.js +1 -1
- package/dashboard/.next/server/app/report/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/stats/page.js +1 -1
- package/dashboard/.next/server/app/stats/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app-paths-manifest.json +9 -8
- package/dashboard/.next/server/chunks/42.js +1 -1
- package/dashboard/.next/server/chunks/530.js +1 -1
- package/dashboard/.next/server/chunks/649.js +1 -1
- package/dashboard/.next/server/chunks/939.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-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/chunks/{1.8868c4d131111be7.js → 1.a666047ea18866fb.js} +2 -2
- package/dashboard/.next/static/chunks/1015.39008440ab15e196.js +226 -0
- package/dashboard/.next/static/chunks/1151.497fa63c5b9eba52.js +1 -0
- package/dashboard/.next/static/chunks/1199.f30cbfa151e56076.js +148 -0
- package/dashboard/.next/static/chunks/1375.64c20f1064a38a10.js +43 -0
- package/dashboard/.next/static/chunks/1799.8dc56017eede704e.js +9 -0
- package/dashboard/.next/static/chunks/20154aaa.e87f69fe10483f8b.js +1 -0
- package/dashboard/.next/static/chunks/2077.5603adeb156c7d10.js +1 -0
- package/dashboard/.next/static/chunks/2166.9f6592b9399eadd8.js +215 -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/{2383.62c035a052272594.js → 2383.ca81f980ce6528a4.js} +1 -1
- package/dashboard/.next/static/chunks/2694.7dfa5fef28851903.js +1 -0
- package/dashboard/.next/static/chunks/275.38af87389c1d33d7.js +34 -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/{2879.51436986f93981d9.js → 2879.74d65e33e60505ee.js} +1 -1
- package/dashboard/.next/static/chunks/3017.4a5312e3c20a173f.js +1 -0
- package/dashboard/.next/static/chunks/3205-47d09be47325709f.js +2 -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/3626.c5dacee11c8fbc4d.js +64 -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-88d849290406ee6f.js +1 -0
- package/dashboard/.next/static/chunks/3948.74201b9f0672234d.js +287 -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/5060.47402abc10273699.js +1 -0
- package/dashboard/.next/static/chunks/5284.334c7c0587d5d47a.js +1 -0
- package/dashboard/.next/static/chunks/5715.e16b1230cc4b4652.js +115 -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/6177.a01cf0a03734cf09.js +1 -0
- package/dashboard/.next/static/chunks/618f8807-69fc7bb97c2b87c1.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/690f35d0.ab57e02a04c7e9e0.js +119 -0
- package/dashboard/.next/static/chunks/{7020.831e16e26d91abc1.js → 7020.b718b1b9cea36e60.js} +2 -2
- package/dashboard/.next/static/chunks/7397-37adf76cad543297.js +1 -0
- package/dashboard/.next/static/chunks/7498-d1814d68ba346d13.js +1 -0
- package/dashboard/.next/static/chunks/7802.f0134c792fccd382.js +80 -0
- package/dashboard/.next/static/chunks/7973.e34032723285a616.js +79 -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/{8452-e616b5f43bceb95f.js → 8452-6d77fa353402422c.js} +2 -2
- package/dashboard/.next/static/chunks/8645.98a43217d406500e.js +1 -0
- package/dashboard/.next/static/chunks/8928-fc049decdfbdaa6d.js +1 -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/9466.a914ce0de7d3bb84.js +1 -0
- package/dashboard/.next/static/chunks/9660.b1c8deae2c449d14.js +1 -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/9811.2993c4cbd28e8d1b.js +1 -0
- package/dashboard/.next/static/chunks/app/_not-found/page-c299b935209993df.js +1 -0
- package/dashboard/.next/static/chunks/app/access/page-f8403cbdfc1c176b.js +1 -0
- package/dashboard/.next/static/chunks/app/calls/page-41f20d01e12382ef.js +1 -0
- package/dashboard/.next/static/chunks/app/changes/page-82bf8b6f48cdc506.js +1 -0
- package/dashboard/.next/static/chunks/app/conformance/page-6bb8e3b372e38098.js +1 -0
- package/dashboard/.next/static/chunks/app/diagram/page-469cd7a6f183efba.js +1 -0
- package/dashboard/.next/static/chunks/app/flows/page-7872dd9141ba0b07.js +1 -0
- package/dashboard/.next/static/chunks/app/functions/page-5847bcb77a8e7edf.js +1 -0
- package/dashboard/.next/static/chunks/app/issues/page-1ffc64fe40439002.js +1 -0
- package/dashboard/.next/static/chunks/app/layout-6c6d2a0fd7c989d3.js +1 -0
- package/dashboard/.next/static/chunks/app/notes/page-8bcaa52304500098.js +1 -0
- package/dashboard/.next/static/chunks/app/page-d63800ddb072b77b.js +1 -0
- package/dashboard/.next/static/chunks/app/progress/page-e26554f655a62eef.js +1 -0
- package/dashboard/.next/static/chunks/app/report/page-18c04fb2f193b020.js +1 -0
- package/dashboard/.next/static/chunks/app/stats/page-67ff59fd69bed651.js +1 -0
- package/dashboard/.next/static/chunks/{b7167ec1.7afbab6f609e3326.js → b7167ec1.708a3d61698ca2e6.js} +1 -1
- 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-app-5662c64b50ba40d1.js +1 -0
- package/dashboard/.next/static/chunks/main-cc3a889b25e9aa68.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-4de0e79bdd6a0418.js +1 -0
- package/dashboard/.next/static/css/1112cea2260b3926.css +3 -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/a1f87af3f44fadbb-s.woff2 +0 -0
- package/dashboard/.next/static/media/f9e1dbe9676d9bb6-s.woff2 +0 -0
- package/dashboard/.next/static/z5XBev05xDAkDrxWxAjNu/_buildManifest.js +1 -0
- package/dashboard/app/changes/ChangesClient.tsx +464 -0
- package/dashboard/app/changes/page.tsx +36 -0
- package/dashboard/app/issues/IssuesBoardClient.tsx +11 -1
- package/dashboard/app/layout.tsx +13 -1
- package/dashboard/app/notes/NotesClient.tsx +5 -0
- package/dashboard/app/page.tsx +42 -0
- package/dashboard/components/DashboardLayout.tsx +43 -18
- 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 +529 -0
- package/dist/analysis/code-model.js.map +1 -0
- package/dist/analysis/diff.d.ts +64 -0
- package/dist/analysis/diff.d.ts.map +1 -0
- package/dist/analysis/diff.js +644 -0
- package/dist/analysis/diff.js.map +1 -0
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +18 -2
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/diff.d.ts +26 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +218 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +72 -9
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/issue.d.ts.map +1 -1
- package/dist/commands/issue.js +4 -4
- package/dist/commands/issue.js.map +1 -1
- package/dist/commands/note.d.ts.map +1 -1
- package/dist/commands/note.js +30 -2
- package/dist/commands/note.js.map +1 -1
- package/dist/core/config.d.ts +9 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +18 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +16 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/git.d.ts +24 -0
- package/dist/core/git.d.ts.map +1 -0
- package/dist/core/git.js +115 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/issues.d.ts +4 -2
- package/dist/core/issues.d.ts.map +1 -1
- package/dist/core/issues.js +67 -28
- package/dist/core/issues.js.map +1 -1
- package/dist/core/notes.d.ts +25 -1
- package/dist/core/notes.d.ts.map +1 -1
- package/dist/core/notes.js +34 -2
- package/dist/core/notes.js.map +1 -1
- package/dist/core/schema.d.ts +750 -53
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +153 -1
- package/dist/core/schema.js.map +1 -1
- 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/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/skills/ai-audit/LICENSE +21 -0
- package/dist/skills/ai-audit/SKILL.md +476 -0
- package/dist/skills/ai-audit/UPSTREAM.md +46 -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 +223 -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/generate-report.md +9 -3
- package/dist/skills/ingest-aa-report.md +11 -2
- package/dist/skills/init-audit.md +104 -2
- package/dist/skills/validate-all-findings.md +1 -1
- package/dist/skills/validate-finding.md +12 -7
- package/dist/skills/write-finding.md +8 -6
- package/dist/types/index.d.ts +7 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +2 -1
- 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/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.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/chunks/44.js +0 -1
- package/dashboard/.next/server/pages/404.html +0 -1
- package/dashboard/.next/static/ZYqkgvjnS38aMxfanyctA/_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/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/.next/static/{ZYqkgvjnS38aMxfanyctA → z5XBev05xDAkDrxWxAjNu}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# Report Formatting
|
|
2
|
+
|
|
3
|
+
## The one rule
|
|
4
|
+
|
|
5
|
+
**A report must not overstate its own coverage.** Every other rule in this file serves that
|
|
6
|
+
one. The report may print **less** than the scan found — a mistyped marker, a dead agent, a
|
|
7
|
+
pass that never ran — and when it does it says so in words. It may never claim to print
|
|
8
|
+
**more**. A report that shows 14 findings and reads as if it showed all of them is the defect
|
|
9
|
+
this whole design exists to kill.
|
|
10
|
+
|
|
11
|
+
## Who reads this file
|
|
12
|
+
|
|
13
|
+
Nothing composes a report from this template any more. There are two readers:
|
|
14
|
+
|
|
15
|
+
- **SKILL.md Turn 4 step 5a** — the pass writing its findings into `run-K.md`. It uses the
|
|
16
|
+
**finding block** shape below: title line, location line, `**Description**`, diff `**Fix**`
|
|
17
|
+
block. Those bytes are pasted straight through into the report, so they are written in the
|
|
18
|
+
report's own shape while the pass still has context to spare.
|
|
19
|
+
- **`references/assemble.sh`** — the assembler. Everything below the finding block — the
|
|
20
|
+
banner, the Scope table, the ordering, the Findings List, the Leads section, "Known from
|
|
21
|
+
earlier scans", the disclaimer — is what the assembler emits.
|
|
22
|
+
|
|
23
|
+
**This file settles the shape. `report-language.md` settles the words.** Every sentence a
|
|
24
|
+
human reads in the report — the finding title, the Description, the Lead description, the
|
|
25
|
+
Lead's code smells — is written in Simplified Technical English, and that file holds the rules.
|
|
26
|
+
It is read by the same Turn 4 step 5a that writes the block, and it is in all twelve agent
|
|
27
|
+
bundles. It never reaches the diff in a **Fix** block, the bug-class label inside a key, or an
|
|
28
|
+
identifier on a location line: those three are data, and it says so.
|
|
29
|
+
|
|
30
|
+
**The template is the contract the assembler emits, not a shape a model imitates.** A later
|
|
31
|
+
editor must not re-teach the orchestrator to write it. The orchestrator under context pressure
|
|
32
|
+
is the thing that failed; the step that must not lose a finding holds no model judgment.
|
|
33
|
+
|
|
34
|
+
## Report Path
|
|
35
|
+
|
|
36
|
+
**Every scan assembles `.hex/ai-audit/runs/{stamp}/full-report.md`** — the whole report,
|
|
37
|
+
banner line down to the disclaimer — at any pass count, with or without flags. That file is
|
|
38
|
+
the report. There is exactly one producer of it, and it is the assembler.
|
|
39
|
+
|
|
40
|
+
`--file-output` makes a **copy** of that file into the current working directory as
|
|
41
|
+
`{project-name}-hex-ai-audit-report-{stamp}.md`, where `{project-name}` is the repo root
|
|
42
|
+
basename and `{stamp}` is `YYYYMMDD-HHMMSS` at scan time. A copy, not a second build —
|
|
43
|
+
nothing regenerates, so the flag cannot collapse the report the way the terminal once did. The
|
|
44
|
+
flag never causes a report to be produced; it only decides whether a copy lands where the
|
|
45
|
+
runner can see it.
|
|
46
|
+
|
|
47
|
+
The `run-K.md` files stay in `.hex/ai-audit/runs/{stamp}/` under the same stamp, so a
|
|
48
|
+
report and the runs that produced it are tied together by eye. They are never copied into the
|
|
49
|
+
working directory — they are memory, not reports.
|
|
50
|
+
|
|
51
|
+
## Output Format
|
|
52
|
+
|
|
53
|
+
This is what the assembler emits.
|
|
54
|
+
|
|
55
|
+
````
|
|
56
|
+
# 🔐 Security Review — <ContractName or repo name>
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Scope
|
|
61
|
+
|
|
62
|
+
| | |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| **Mode** | ALL / default / filename |
|
|
65
|
+
| **Files reviewed** | `File1.sol` · `File2.sol`<br>`File3.sol` · `File4.sol` | <!-- every file, 3 per line -->
|
|
66
|
+
| **Confidence threshold (1-100)** | N |
|
|
67
|
+
| **Passes** | 3 | <!-- only when passes > 1 -->
|
|
68
|
+
| **Memory** | 12 records before this scan · 14 after · `a1b2c3d` | <!-- only when memory is on -->
|
|
69
|
+
| **Run files** | ⚠️ 2 findings marked, 1 readable. 1 could not be read. | <!-- only when the structure check disagrees -->
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Findings
|
|
74
|
+
|
|
75
|
+
[95] **1. <Title>**
|
|
76
|
+
|
|
77
|
+
`ContractName.functionName` · Confidence: 95 · seen in 2/3 runs · KNOWN (4 scans) <!-- runs segment only when passes > 1; memory segment only when memory is on -->
|
|
78
|
+
|
|
79
|
+
**Description**
|
|
80
|
+
<The vulnerable code pattern and why it is exploitable, in 1 short sentence>
|
|
81
|
+
|
|
82
|
+
**Fix**
|
|
83
|
+
|
|
84
|
+
```diff
|
|
85
|
+
- vulnerable line(s)
|
|
86
|
+
+ fixed line(s)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
[82] **2. <Title>**
|
|
92
|
+
|
|
93
|
+
`ContractName.functionName` · Confidence: 82
|
|
94
|
+
|
|
95
|
+
**Description**
|
|
96
|
+
<The vulnerable code pattern and why it is exploitable, in 1 short sentence>
|
|
97
|
+
|
|
98
|
+
**Fix**
|
|
99
|
+
|
|
100
|
+
```diff
|
|
101
|
+
- vulnerable line(s)
|
|
102
|
+
+ fixed line(s)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
< ... all above-threshold findings >
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
[60] **3. <Title>**
|
|
112
|
+
|
|
113
|
+
`ContractName.functionName` · Confidence: 60
|
|
114
|
+
|
|
115
|
+
**Description**
|
|
116
|
+
<The vulnerable code pattern and why it is exploitable, in 1 short sentence>
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
< ... all below-threshold findings (description only, no Fix block) >
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
Findings List
|
|
125
|
+
|
|
126
|
+
| # | Confidence | Title |
|
|
127
|
+
|---|---|---|
|
|
128
|
+
| 1 | [95] | <title> |
|
|
129
|
+
| 2 | [82] | <title> |
|
|
130
|
+
| 3 | [75] | <title> |
|
|
131
|
+
| | | **Below Confidence Threshold** |
|
|
132
|
+
| 4 | [60] | <title> |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Leads
|
|
137
|
+
|
|
138
|
+
_Vulnerability trails with concrete code smells where the full exploit path could not be completed in one analysis pass. These are not false positives — they are high-signal leads for manual review. Not scored._
|
|
139
|
+
|
|
140
|
+
- **<Title>** — `Contract.function` · NEW — Code smells: <missing guard, unsafe arithmetic, etc.> — <1-2 sentence description of the trail and what remains unverified> <!-- memory segment only when memory is on -->
|
|
141
|
+
- **<Title>** — `Contract.function` · seen in 2/3 runs · KNOWN (2 scans) — Code smells: <...> — <1-2 sentence description> <!-- runs segment only when passes > 1 -->
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Known from earlier scans
|
|
146
|
+
|
|
147
|
+
<!-- only when memory is on AND the ledger held at least one record — see Memory in the report -->
|
|
148
|
+
|
|
149
|
+
_Recorded by earlier scans of this repo, not raised again by this one. Not re-checked — a record here may be fixed, or may still be live and missed. `.hex/ai-audit/memory.tsv`._
|
|
150
|
+
|
|
151
|
+
| Scans | Kind | Location | Title |
|
|
152
|
+
|---|---|---|---|
|
|
153
|
+
| 4 | FINDING | `Router.swap` | Swap trusts a spot price as an oracle |
|
|
154
|
+
| 2 | LEAD | `Vault.sweep` | Sweep lets the owner take user deposits |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
> ⚠️ This review was performed by an AI assistant. AI analysis can never verify the complete absence of vulnerabilities and no guarantee of security is given. Team security reviews, bug bounty programs, and on-chain monitoring are strongly recommended.
|
|
159
|
+
|
|
160
|
+
````
|
|
161
|
+
|
|
162
|
+
**Rules describing the output**, all of them held by the assembler and none of them addressed
|
|
163
|
+
to a model:
|
|
164
|
+
|
|
165
|
+
- Findings are sorted by confidence, highest first.
|
|
166
|
+
- A finding at or above the threshold carries a **Description** and a diff **Fix** block. One
|
|
167
|
+
below carries the **Description** only. Nothing in the run file marks which side of the line
|
|
168
|
+
a finding sits on — it is re-derived from the confidence, so there is one source of truth.
|
|
169
|
+
- The **Below Confidence Threshold** separator row is printed whenever at least one finding
|
|
170
|
+
falls below the threshold, and left out when none does. Without it the table runs 1, 2, 3
|
|
171
|
+
with nothing to mark the boundary, so a reader of the table alone cannot tell which findings
|
|
172
|
+
carry no **Fix** block.
|
|
173
|
+
- **Empty cases say so in words, never with an empty table**: `_None — this scan raised no
|
|
174
|
+
findings._` in place of the Findings List, `_None._` under Leads, `**Body missing** — pass K
|
|
175
|
+
raised this finding and wrote no description.` in place of a body.
|
|
176
|
+
- **A `Run files` row appears only when the structure check disagrees.** The model types the
|
|
177
|
+
markers that bound each finding in a run file, so it can mistype one. The assembler counts
|
|
178
|
+
open markers against close markers against readable blocks, and prints the disagreement as a
|
|
179
|
+
Scope row naming how many findings could not be read. Everything readable is still printed
|
|
180
|
+
and the assembler never stops. That row is the one rule at the top made mechanical.
|
|
181
|
+
- **The Scope table's column padding is not part of the shape.** Markdown renders
|
|
182
|
+
`| **Mode** | default |` and a space-padded form identically, and the padding above is for
|
|
183
|
+
reading this file. Content and order are the contract; character widths are not.
|
|
184
|
+
|
|
185
|
+
**The threshold is 75**, set in `judging.md` and printed in the Scope row above. It is named
|
|
186
|
+
in `judging.md` and nowhere else; this file reads it from there. A finding at 75 or above gets
|
|
187
|
+
a description and a **Fix** block, one below 75 gets the description only. A promoted lead
|
|
188
|
+
lands at exactly 75, so it clears — that is why the number is 75.
|
|
189
|
+
|
|
190
|
+
## The size trigger
|
|
191
|
+
|
|
192
|
+
**More than 20 findings.** At 20 the terminal prints the assembled file word for word; at 21
|
|
193
|
+
it stops printing findings. Findings only — above and below the threshold together. **Leads
|
|
194
|
+
are excluded from the trigger count**, so a scan with 18 findings and 40 leads prints in full.
|
|
195
|
+
|
|
196
|
+
The trigger is on **size, not on flags**. A plain scan of a small contract is unchanged; a
|
|
197
|
+
plain scan of a big one gets the new shape.
|
|
198
|
+
|
|
199
|
+
**Above the trigger the terminal prints four things:** the banner, the Scope table unchanged,
|
|
200
|
+
a **Findings List holding the top 3 findings**, and the path to the full report — then the
|
|
201
|
+
disclaimer. About fifteen lines.
|
|
202
|
+
|
|
203
|
+
The full report is unaffected. Above the trigger, as below it, `full-report.md` holds every
|
|
204
|
+
finding in the shape above — only the terminal changes.
|
|
205
|
+
|
|
206
|
+
**The slice is honest because it is counted.** The table's header reads
|
|
207
|
+
`Findings List — top 3 of {F}`, and that `{F}` is the whole rule:
|
|
208
|
+
|
|
209
|
+
- **A report may print less than the scan found. It may never look like it printed more.**
|
|
210
|
+
A bare list of three findings breaks that — a reader cannot tell a truncated list from a
|
|
211
|
+
complete one. `top 3 of 52` cannot be misread.
|
|
212
|
+
- **The total goes in the header, not a footnote.** A reader who sees the table sees the
|
|
213
|
+
total in the same glance. This is not a style choice; a footnote can be scrolled past.
|
|
214
|
+
- **Three rows, and nothing else is enumerated.** No Leads, no "Known from earlier scans",
|
|
215
|
+
no findings past the third.
|
|
216
|
+
|
|
217
|
+
> **This replaces the older "nothing is enumerated above the trigger" rule**, which forbade
|
|
218
|
+
> every top-N slice. That rule was right that bare truncation lies and wrong to conclude no
|
|
219
|
+
> slice can be honest; a counted one is. A later editor must not restore the blanket ban by
|
|
220
|
+
> citing the half of the argument that survived.
|
|
221
|
+
|
|
222
|
+
**The rows are extracted by shell, never typed.** One `awk` over the assembled file — which is
|
|
223
|
+
already sorted highest-confidence first, so no sort happens in the terminal step. The
|
|
224
|
+
orchestrator has read dozens of findings by then and is the least reliable thing in the room;
|
|
225
|
+
the extractor cannot mis-rank, mis-quote a function name or invent a confidence. The command
|
|
226
|
+
is in `dedup-and-assembly.md` Turn 5 step 3b.
|
|
227
|
+
|
|
228
|
+
**The `Seen` column appears only when the `Passes` row does** — that is, when the pass count is
|
|
229
|
+
above 1. A plain scan's location line carries no `seen in k/N runs`, so the column is dropped
|
|
230
|
+
from the header, the separator and the rows together. A five-column header over four-column
|
|
231
|
+
rows draws as a broken table.
|
|
232
|
+
|
|
233
|
+
**There is no counts summary.** The `{F} findings, {L} leads` line and the
|
|
234
|
+
`100-90 / 89-75 / below 75` split are not printed. `top 3 of {F}` carries the only total the
|
|
235
|
+
moment needs, and the bucket split stood between the reader and the path. The buckets are still
|
|
236
|
+
**computed** as a self-check — `A + B + C` must equal `F`, in every mode, or the assembled file
|
|
237
|
+
is malformed and the scan says so instead of printing a slice of it.
|
|
238
|
+
|
|
239
|
+
The path line names `.hex/ai-audit/runs/{stamp}/full-report.md`, or — when `--file-output`
|
|
240
|
+
was passed — the **copy** and only the copy. Never both: two paths to identical bytes answer a
|
|
241
|
+
question the runner did not ask at the moment they want one filename. That line is the only
|
|
242
|
+
part of the block a flag changes.
|
|
243
|
+
|
|
244
|
+
The exact wording, spacing and order of the block are in `dedup-and-assembly.md` Turn 5 step
|
|
245
|
+
3b, which is where the terminal is printed.
|
|
246
|
+
|
|
247
|
+
## The freeze
|
|
248
|
+
|
|
249
|
+
**A small scan with no flags prints what it printed before any of this existed.** Below the
|
|
250
|
+
trigger the terminal prints `full-report.md` word for word — every byte, nothing added,
|
|
251
|
+
nothing cut, no preface — so the freeze is a property of the assembled file.
|
|
252
|
+
|
|
253
|
+
The freeze is a **diff against `golden/plain-full-report.md`**, the frozen plain-path report,
|
|
254
|
+
and it covers the report's **content and order, not its column padding** and not what lands on
|
|
255
|
+
disk. Byte-identity against "today" was tried and is unmeetable: no captured report exists
|
|
256
|
+
anywhere, and today's bytes were composed by a model from a template that contradicted itself.
|
|
257
|
+
The golden file is what replaced it.
|
|
258
|
+
|
|
259
|
+
What the freeze does **not** cover: writing files. Every scan now writes a runs directory and
|
|
260
|
+
assembles a report there, at any pass count. Writing a file is not printing, and the freeze is
|
|
261
|
+
on printed output.
|
|
262
|
+
|
|
263
|
+
## Memory in the report
|
|
264
|
+
|
|
265
|
+
Everything in this section is printed **only when memory is on** (`--memory`, or a pass count
|
|
266
|
+
above 1). With memory off the assembled file carries no extra rows, no extra segments, no
|
|
267
|
+
extra sections and no dangling `·`, and below the trigger it still diffs clean against the
|
|
268
|
+
golden file.
|
|
269
|
+
|
|
270
|
+
**Segment order on the meta line.** One dot-separated chain, in a fixed order:
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
`ContractName.functionName` · Confidence: 95 · seen in 2/3 runs · KNOWN (4 scans)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
location · confidence · runs · memory. **A segment appears only when it carries information** —
|
|
277
|
+
`seen in k/N runs` needs more than one run, `KNOWN (n scans)` / `NEW` needs memory on. So:
|
|
278
|
+
|
|
279
|
+
| Scan | Meta line |
|
|
280
|
+
|---|---|
|
|
281
|
+
| 1 pass, no flags | `` `Vault.withdraw` · Confidence: 95 `` |
|
|
282
|
+
| 1 pass, `--memory` | `` … · Confidence: 95 · KNOWN (4 scans) `` |
|
|
283
|
+
| 3 passes | `` … · Confidence: 95 · seen in 2/3 runs · KNOWN (4 scans) `` |
|
|
284
|
+
|
|
285
|
+
`KNOWN (4 scans)` and `NEW` are the ledger's own two words, so the report and the file say the
|
|
286
|
+
same thing. **`n` counts this scan.** The tag is derived by the assembler from
|
|
287
|
+
`memory-before.tsv` — the pre-scan photocopy — and `n` is that row's `scans` **plus one**: the
|
|
288
|
+
scan that is printing has just found it again, and the ledger already holds that same number.
|
|
289
|
+
Printing the stored count instead would show a report one behind its own ledger. `NEW` carries
|
|
290
|
+
no count. The tag is **not** carried in the run-file marker: one source, so the report and the
|
|
291
|
+
ledger cannot disagree.
|
|
292
|
+
|
|
293
|
+
The `Scans` column of "Known from earlier scans" is the opposite case and is printed **as
|
|
294
|
+
stored**: this scan did not raise those records, so nothing about them counts up. The
|
|
295
|
+
**Findings List** table is unchanged — it stays `# | Confidence | Title`.
|
|
296
|
+
|
|
297
|
+
Leads carry the same segments as findings, on their own line, because a Lead is a full ledger
|
|
298
|
+
record.
|
|
299
|
+
|
|
300
|
+
**The `Memory` row in Scope.** `<records in the ledger before this scan> records before this
|
|
301
|
+
scan · <records after the merge> after · `<sha>``. The SHA is the one every row of this scan
|
|
302
|
+
wrote; `none` when the repo has no commits. The row states the whole ledger state in one line,
|
|
303
|
+
so the two counts show at a glance what the scan added.
|
|
304
|
+
|
|
305
|
+
**The "before" count is the count after the prune** — the row count of `memory-before.tsv` as
|
|
306
|
+
the merge reads it, not the row count of the file the scan opened. On a scan where the prune
|
|
307
|
+
drops records the two differ, and using the pre-prune number makes the row's own arithmetic
|
|
308
|
+
wrong: a scan that opened 4 records, pruned 1 and added 12 would read `4 records before this
|
|
309
|
+
scan · 15 after`, and a reader counting 4 + 12 gets 16. The prune is already reported on its
|
|
310
|
+
own line (`Pruned N records …`), so the Scope row does not restate it and must not contradict
|
|
311
|
+
it.
|
|
312
|
+
|
|
313
|
+
**Building "Known from earlier scans".** These are the records the ledger already held that
|
|
314
|
+
this scan did **not** raise again. It is **not** a filter on the `status` column — `status`
|
|
315
|
+
stays `KNOWN` once set and never marks the not-found-again case.
|
|
316
|
+
|
|
317
|
+
**The `comm` block that used to sit here is now in `assemble.sh`**, under
|
|
318
|
+
`# Known from earlier scans`. It reads two inputs Turn 5 copies into the runs directory:
|
|
319
|
+
`memory-before.tsv`, the pruned photocopy, and `source-names.tsv`. The keys this scan raised
|
|
320
|
+
come from the assembler's own index of the run files, so no `run-keys.tsv` or `scan-rows.tsv`
|
|
321
|
+
is carried in — the run files are the record. It is computed once per scan, scoped to the
|
|
322
|
+
whole scan and not to the last run, so a bug found in run 1 but not in run 3 does not appear
|
|
323
|
+
here.
|
|
324
|
+
|
|
325
|
+
Each key `comm` returns is one row: `Scans`, `Kind` and `Title` come straight from its row in
|
|
326
|
+
`memory-before.tsv`. `Location` is rebuilt from the key's first two segments, which are stored
|
|
327
|
+
normalised (lower case, hyphenated) and cannot be printed as they are — each segment is looked
|
|
328
|
+
up in `source-names.tsv` and printed as the source spells it, or printed as stored when it is
|
|
329
|
+
not in the map, which happens on a named-file scan where the contract was never assembled into
|
|
330
|
+
`source.md`.
|
|
331
|
+
|
|
332
|
+
Three states, and no fourth:
|
|
333
|
+
|
|
334
|
+
- The ledger held records this scan did not raise → the table above.
|
|
335
|
+
- The ledger held records and this scan raised **every one** → `_None — every record in the
|
|
336
|
+
ledger was raised again by this scan._`
|
|
337
|
+
- Memory is off, or the ledger is empty (first-ever scan) → **no section at all.** A plain
|
|
338
|
+
scan grows no empty headings.
|
|
339
|
+
|
|
340
|
+
The italic line under the heading is load-bearing and is printed verbatim: these records are
|
|
341
|
+
**not re-checked**. A reader must not take the section as "still open", and must not take it
|
|
342
|
+
as "fixed".
|
|
343
|
+
|
|
344
|
+
## Loop mode in the report
|
|
345
|
+
|
|
346
|
+
Everything in this section is printed **only when the pass count is above 1**. One pass prints
|
|
347
|
+
none of it.
|
|
348
|
+
|
|
349
|
+
**One report per scan.** However many passes ran, the runner sees one combined list. The
|
|
350
|
+
per-pass output is one summary line each (SKILL.md Turn 4 step 5b) and one `run-K.md` in
|
|
351
|
+
`.hex/ai-audit/runs/{stamp}/` — neither is a report.
|
|
352
|
+
|
|
353
|
+
**`seen in k/N runs`.** `k` is how many of this scan's runs raised that group key; `N` is how
|
|
354
|
+
many passes produced a run file. A pass that collapsed produced none, so it is not in `N` — a
|
|
355
|
+
report must not claim a run that never happened. The segment sits between confidence and the
|
|
356
|
+
memory tag, and it is printed on Leads exactly as it is on findings, because a Lead is a full
|
|
357
|
+
ledger record.
|
|
358
|
+
|
|
359
|
+
**`seen in k/N runs` and `KNOWN (n scans)` count different things and must never be mixed.**
|
|
360
|
+
`k/N` counts runs inside **this** scan and is never written to the ledger. `n` counts scans and
|
|
361
|
+
comes from the ledger. A finding first raised by pass 1 of this scan is `NEW` in pass 3 — it is
|
|
362
|
+
this scan's work, however many of its runs saw it.
|
|
363
|
+
|
|
364
|
+
**Which write-up survives the merge.** One winner per key: strongest kind, then highest
|
|
365
|
+
confidence, then the later pass — a later pass read the ledger every earlier pass wrote, so it
|
|
366
|
+
is the better-informed write-up. **Confidence is untouched by the merge.** A finding three runs
|
|
367
|
+
saw keeps the number the runs gave it; repetition is reported on the line, never scored, and
|
|
368
|
+
`seen in 3/3 runs` is there for the reader to weigh.
|
|
369
|
+
|
|
370
|
+
**The `Passes` row in Scope** is composed by the assembler from recorded facts, never written
|
|
371
|
+
as prose. It carries degradation text whenever the scan did not run whole — a report claiming
|
|
372
|
+
3 passes when one of them ran three-quarters of its agents overstates its own coverage:
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
| **Passes** | 3 |
|
|
376
|
+
| **Passes** | 3 (pass 2 ran 11/12 agents) |
|
|
377
|
+
| **Passes** | 2 of 3 (pass 3 failed) |
|
|
378
|
+
| **Passes** | 2 of 3 (pass 1 ran 11/12 agents, pass 3 failed) |
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
The `R of P` prefix comes from counting run files. The dead agent's **name** never appears
|
|
382
|
+
here — it stays in the run file, in the sentence under the `<!--RUN-->` marker.
|
|
383
|
+
|
|
384
|
+
On a 1-pass scan this row is suppressed, so a pass 1 that produced nothing is reported by the
|
|
385
|
+
`Run files` row instead: `⚠️ No pass produced a run file. This scan reviewed nothing.`
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Report language — Simplified Technical English
|
|
2
|
+
|
|
3
|
+
Every sentence a human reads in the report obeys this file. The rules are ASD-STE100
|
|
4
|
+
(Simplified Technical English), reduced to the part an audit finding needs.
|
|
5
|
+
|
|
6
|
+
## Why
|
|
7
|
+
|
|
8
|
+
A report is read by the developer who must fix the code, often at speed, often not in their
|
|
9
|
+
first language. A sentence they must decode twice costs the fix, and the bug stays in the
|
|
10
|
+
code. The scan is only as good as the sentence that delivers it.
|
|
11
|
+
|
|
12
|
+
Short words do not make a finding less rigorous. The proof is the diff in the **Fix** block
|
|
13
|
+
and the location on the meta line. The sentence exists to say what breaks and who breaks it.
|
|
14
|
+
|
|
15
|
+
## What this covers
|
|
16
|
+
|
|
17
|
+
Four pieces of text, and no others:
|
|
18
|
+
|
|
19
|
+
- the finding **title**
|
|
20
|
+
- the **Description** sentence
|
|
21
|
+
- the **Lead** description
|
|
22
|
+
- the **code smells** list on a Lead
|
|
23
|
+
|
|
24
|
+
## What it must never touch
|
|
25
|
+
|
|
26
|
+
These are data, not prose. Rewriting one of them for readability breaks the scan:
|
|
27
|
+
|
|
28
|
+
- **Solidity identifiers** — contract, function, variable and event names. They are printed as
|
|
29
|
+
the source spells them. `withdrawToNativeChain` is never softened to `withdraw to chain`.
|
|
30
|
+
- **The diff inside a Fix block.** It is code. It is pasted verbatim from the agent that wrote
|
|
31
|
+
it, and `judging.md` and `dedup-and-assembly.md` both forbid paraphrase there.
|
|
32
|
+
- **The bug-class label** (`zero-abort-address`). It is the third segment of a memory key.
|
|
33
|
+
The same bug under a plainer word is a second ledger record, so memory remembers it twice
|
|
34
|
+
and recognises it never. Labels are chosen by the rules in `dedup-and-assembly.md` step 1,
|
|
35
|
+
never by this file.
|
|
36
|
+
- **Fixed strings the assembler prints** — the banner, the Scope table headers, the italic
|
|
37
|
+
lines under Leads and "Known from earlier scans", the disclaimer. They are in
|
|
38
|
+
`assemble.sh` and they are already written.
|
|
39
|
+
|
|
40
|
+
## The rules
|
|
41
|
+
|
|
42
|
+
1. **One sentence, one idea.** A Description is one sentence. A Lead description is one or
|
|
43
|
+
two. Never three.
|
|
44
|
+
2. **Twenty-five words is the ceiling.** Count them. Over the ceiling means two ideas in one
|
|
45
|
+
sentence — cut it or split it.
|
|
46
|
+
3. **Active voice, and name the actor.** Who does this? Write that word first.
|
|
47
|
+
- No: `Funds can be drained due to a missing check.`
|
|
48
|
+
- Yes: `Any caller can take all the tokens, because the function checks no caller.`
|
|
49
|
+
4. **Simple present tense.** The code does this today. Not `would be able to`, not
|
|
50
|
+
`could potentially`. If the path is uncertain it is a Lead, and the Lead says which step
|
|
51
|
+
is unproven.
|
|
52
|
+
5. **No `-ing` clauses.** They hide the actor and the order of events. Use `that`, `so`, or a
|
|
53
|
+
second sentence.
|
|
54
|
+
- No: `Missing access control allowing anyone to drain the vault.`
|
|
55
|
+
- Yes: `The function has no access control, so any caller can take all the tokens.`
|
|
56
|
+
6. **Keep the articles.** `the`, `a`, `an`. Telegraphic style — `Function reverts on zero
|
|
57
|
+
amount` — is not shorter to read, only shorter to type.
|
|
58
|
+
7. **Three nouns in a row is the limit.** Break a longer stack with `of`, `for` or `in`.
|
|
59
|
+
- No: `cross-chain message replay protection gap`
|
|
60
|
+
- Yes: `the contract does not stop a replay of a cross-chain message`
|
|
61
|
+
8. **One word for one thing, every time.** Pick `token`, or pick `asset`, and use that word
|
|
62
|
+
in the title, the Description and the fix. A synonym reads as a second thing.
|
|
63
|
+
9. **No metaphor, no idiom, no slang.** See the table below. A metaphor is a word the reader
|
|
64
|
+
must translate before they can act.
|
|
65
|
+
10. **Say what happens, not how bad it is.** `catastrophic`, `critical`, `severe` and
|
|
66
|
+
`trivially` carry no information — the confidence number and the Fix block carry it. Write
|
|
67
|
+
the effect: `the caller keeps the tokens and the pool keeps the debt`.
|
|
68
|
+
11. **Positive statements. No double negatives.** `The check is absent` beats `the check is
|
|
69
|
+
not present`.
|
|
70
|
+
12. **Event order is sentence order.** Cause, then effect. `The price comes from the pool
|
|
71
|
+
balance, so an attacker who moves the balance moves the price.`
|
|
72
|
+
13. **A title is one clause, twelve words or fewer,** present tense, active, and it names the
|
|
73
|
+
defect or its effect. `Swap trusts a spot price as an oracle.`
|
|
74
|
+
Not `Oracle manipulation vulnerability in swap functionality`.
|
|
75
|
+
|
|
76
|
+
## Words to replace
|
|
77
|
+
|
|
78
|
+
Left column: the wording to keep out of the report. Right column: what the report prints.
|
|
79
|
+
|
|
80
|
+
| Do not write | Write |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| burns the funds | sends the tokens to an address that cannot spend them |
|
|
83
|
+
| bricks the contract | makes the function fail for every caller, forever |
|
|
84
|
+
| rug / rugpull | the owner takes the user deposits |
|
|
85
|
+
| griefing | an attacker makes the function fail for other users |
|
|
86
|
+
| footgun | (delete the word and name the defect) |
|
|
87
|
+
| silently swallows the error | ignores the error |
|
|
88
|
+
| DoS / denial of service | blocks every caller |
|
|
89
|
+
| attack surface / attack vector | path |
|
|
90
|
+
| malicious actor / bad actor | an attacker |
|
|
91
|
+
| leverages / utilizes | uses |
|
|
92
|
+
| is able to | can |
|
|
93
|
+
| in order to | to |
|
|
94
|
+
| arbitrary value | any value the caller chooses |
|
|
95
|
+
| stale price | old price |
|
|
96
|
+
| sanity check | check |
|
|
97
|
+
| happy path | the normal path |
|
|
98
|
+
| atomically | in one transaction |
|
|
99
|
+
| trustlessly / permissionlessly | (delete, or name who may call) |
|
|
100
|
+
| non-zero | more than zero |
|
|
101
|
+
| cascading failures | (name each failure) |
|
|
102
|
+
| exponentially / trivially / catastrophically | (delete) |
|
|
103
|
+
| edge case | (name the input or the state) |
|
|
104
|
+
|
|
105
|
+
## Technical names stay
|
|
106
|
+
|
|
107
|
+
STE-100 keeps technical names, and a security report cannot work without them:
|
|
108
|
+
`reentrancy`, `slippage`, `oracle`, `revert`, `overflow`, `rounding`, `allowance`, `nonce`,
|
|
109
|
+
`slot`, `delegatecall`. Use them. They are precise and the reader who fixes Solidity knows
|
|
110
|
+
them.
|
|
111
|
+
|
|
112
|
+
The rule is what goes **around** them: name the mechanism once with its technical name, then
|
|
113
|
+
say in plain words what the attacker gets.
|
|
114
|
+
|
|
115
|
+
- No: `Classic CEI violation enabling reentrant drainage of the vault.`
|
|
116
|
+
- Yes: `The function sends ETH before it lowers the balance, so a reentrant call withdraws
|
|
117
|
+
the same deposit twice.`
|
|
118
|
+
|
|
119
|
+
## Worked examples
|
|
120
|
+
|
|
121
|
+
Before, and after. The code the sentence describes did not change.
|
|
122
|
+
|
|
123
|
+
**One**
|
|
124
|
+
|
|
125
|
+
- Before: `Improper validation of the abort address results in a catastrophic loss of user
|
|
126
|
+
funds via burning to the zero address.`
|
|
127
|
+
- After: `The function accepts a zero abort address, so a failed transfer sends the tokens to
|
|
128
|
+
an address that nobody controls.`
|
|
129
|
+
|
|
130
|
+
**Two**
|
|
131
|
+
|
|
132
|
+
- Before: `Lack of slippage protection in the swap path exposes users to sandwich attacks,
|
|
133
|
+
potentially leading to significant value extraction by MEV searchers.`
|
|
134
|
+
- After: `The swap sets the minimum output to zero, so an attacker who trades before and
|
|
135
|
+
after the victim keeps most of the output.`
|
|
136
|
+
|
|
137
|
+
**Three — a Lead**
|
|
138
|
+
|
|
139
|
+
- Before: `Potential accounting inconsistency stemming from asymmetric fee handling on
|
|
140
|
+
deposit/withdraw flows warranting further investigation.`
|
|
141
|
+
- After: `The deposit takes the fee from the amount, and the withdrawal takes it from the
|
|
142
|
+
balance. We did not find the input that makes the two disagree.`
|
|
143
|
+
|
|
144
|
+
## Self-check before you write the block
|
|
145
|
+
|
|
146
|
+
Four questions. Any `no` means rewrite the sentence, not the code:
|
|
147
|
+
|
|
148
|
+
- Does the sentence name **who** acts and **what** they get?
|
|
149
|
+
- Is it one sentence, twenty-five words or fewer, with no `-ing` clause?
|
|
150
|
+
- Is every word in it a word the reader does not have to translate?
|
|
151
|
+
- Are the identifiers, the label and the diff exactly as the source and the agent wrote them?
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Senior Auditor's Mindset
|
|
2
|
+
|
|
3
|
+
This is how a senior auditor thinks. Pattern-matching catches the obvious bugs — your specialty file teaches that. The high-value bugs, the ones everyone else misses, come from HOW you reason about code, not from WHAT bugs you know.
|
|
4
|
+
|
|
5
|
+
The senior auditor's edge is not "knowing more bug patterns" — it is having internalized mental tools they reach for instinctively when something feels off, when a path seems clean, or when a conclusion comes too quickly.
|
|
6
|
+
|
|
7
|
+
This file gives you three tools. They are not steps. You reach for the right one the moment the trigger fires. They are how you think, not text you write: do not put them in your reply, which holds only your FINDING and LEAD blocks. Use them. Trust your discomfort.
|
|
8
|
+
|
|
9
|
+
A finding is not real until you've traced the attack with concrete values. You are an attacker, not a defender — when you find a bug, deepen the attack; never argue yourself out of one.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. The Feynman test (FIRST — use it before anything else)
|
|
14
|
+
|
|
15
|
+
**This is the first tool. Apply it the moment you open any new function or contract — before you reason about anything else.** Code you have not Feynman'd is code you have not actually understood.
|
|
16
|
+
|
|
17
|
+
When you read code, STOP and ask: "Can I explain what this function does to someone who doesn't know Solidity?"
|
|
18
|
+
|
|
19
|
+
Try it. In plain words. The places where your explanation gets fuzzy — where you reach for Solidity jargon instead of plain meaning — are where you're papering over an assumption. That's where bugs hide.
|
|
20
|
+
|
|
21
|
+
Example: you read `_handleFeeTransfer(zrc20, fee)` and your explanation comes out as "it transfers the fee." That's not Feynman. Feynman is: "it picks up the protocol's commission off the user's payment and moves it to the treasury wallet." Now keep going: what if the payment is in ETH and the function uses an ERC20 method? Your plain-English explanation breaks. Bug.
|
|
22
|
+
|
|
23
|
+
A senior auditor doesn't trust their understanding until they can explain it without the safety net of technical vocabulary.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 2. Socratic questioning
|
|
28
|
+
|
|
29
|
+
For every line of code, ask: why is this here? What does it assume? What happens if the assumption breaks?
|
|
30
|
+
|
|
31
|
+
Don't accept "because that's how it's written" as an answer. Don't accept "the function name says so" as an answer. Drill until you reach the implicit belief the code rests on. The first answer is usually a restatement. The actual assumption is two or three "whys" deeper.
|
|
32
|
+
|
|
33
|
+
Example: `if (zrc20 != _ETH_ADDRESS_) IERC20(zrc20).transferFrom(msg.sender, address(this), amount);`
|
|
34
|
+
- Why is `zrc20 != _ETH_ADDRESS_` checked? → because ETH isn't transferable via transferFrom.
|
|
35
|
+
- Why is there no else branch? → because the developer assumed ETH arrives via `msg.value`.
|
|
36
|
+
- Where is `msg.value` enforced to equal `amount` for the ETH path? → **nowhere**. Bug.
|
|
37
|
+
|
|
38
|
+
A senior auditor accepts no "because" without examining it.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 3. Inversion
|
|
43
|
+
|
|
44
|
+
Every clean path gets a backward pass. After you understand what the code IS supposed to do, ask: how would I make it NOT do that?
|
|
45
|
+
|
|
46
|
+
Same code, attacker's eye instead of developer's eye. The developer asks "does this work?" The attacker asks "how do I break this?" Read every check and ask "what value slips past it?" Read every state update and ask "what state am I in just before this?"
|
|
47
|
+
|
|
48
|
+
A senior auditor never reads code only forward.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## When to reach for which tool
|
|
53
|
+
|
|
54
|
+
You don't apply these in order — except Feynman, which is always first. You reach for what the moment calls for:
|
|
55
|
+
|
|
56
|
+
- Opening any new function or contract → **Feynman** (always — before anything else)
|
|
57
|
+
- Trying to understand a line you don't yet → **Socratic**
|
|
58
|
+
- Something looks too clean → **Inversion**
|
|
59
|
+
- You reached a "bug" conclusion → amplify the attack (chain it, find more victims, lower the precondition cost — do NOT refute it)
|
|
60
|
+
|
|
61
|
+
The tools are how you keep yourself honest. Without them, you fall into the trap of every junior auditor: trusting your first read, accepting code that "looks right," moving on when something feels off.
|
|
62
|
+
|
|
63
|
+
Trust your discomfort. Reach for the tool. Don't stop until the discomfort has a name.
|
|
@@ -56,8 +56,8 @@ Each section has a defined **input signature** — the exact set of data it deri
|
|
|
56
56
|
|
|
57
57
|
| Section | Input signature (hash over) |
|
|
58
58
|
|---|---|
|
|
59
|
-
| `executive_summary` | severity + resolution histograms, `stats.totals.nsloc`, all `settings.report.*` fields, and the `overview.md` bytes (the synopsis derives from it) |
|
|
60
|
-
| `audited_files` | the per-file LoC results for every `project.scope` file, `repository_url`, `initial_commit` |
|
|
59
|
+
| `executive_summary` | severity + resolution histograms, `stats.totals.nsloc`, all `settings.report.*` fields, and the `overview.md` bytes (the synopsis derives from it); differential: also `diff.json` `base_commit` / `head_commit` / `summary` |
|
|
60
|
+
| `audited_files` | the per-file LoC results for every `project.scope` file (differential: every changed file, with its +/- counts), `repository_url`, `initial_commit` |
|
|
61
61
|
| `summary_of_findings` | the ordered synced-findings list: `(id, title, severity, resolution)` each |
|
|
62
62
|
| `system_overview` | `overview.md`, `access-control.json`, `deps.json` bytes |
|
|
63
63
|
| `findings` | the synced-findings full content: `(title, severity, description, code blocks, recommendation, resolution, update_from_client, root_cause.locations)` each |
|
|
@@ -85,7 +85,7 @@ Read `<output_dir>/config.json`. Look under `settings.report.*` for:
|
|
|
85
85
|
- `final_commit` — commit hash after fixes (defaults to `initial_commit` if no remediation cycle).
|
|
86
86
|
- `initial_report_date` — date the initial report was delivered (e.g. `May 22, 2026`).
|
|
87
87
|
- `final_report_date` — date the final report was delivered (defaults to `initial_report_date`).
|
|
88
|
-
- `audit_type` — defaults to `Security Review`.
|
|
88
|
+
- `audit_type` — defaults to `Security Review`. A differential audit (`project.mode: "diff"`) is initialized with `Differential Review`.
|
|
89
89
|
- `doc_assessment` — `High` / `Medium` / `Low`.
|
|
90
90
|
- `test_assessment` — `High` / `Medium` / `Low`.
|
|
91
91
|
- `kickoff_call` — optional focus note for the §7 kick-off sentence (e.g. "with a focus on the upgrade changes"). Empty means omit the kick-off sentence.
|
|
@@ -138,6 +138,8 @@ Style hints:
|
|
|
138
138
|
|
|
139
139
|
Write to `executive_summary.txt` **and** `01-executive-summary.tex`.
|
|
140
140
|
|
|
141
|
+
**Differential audit** (`config.json` → `project.mode` is `diff`): the review covers the changes between two commits, and the first paragraph must say so. Use `<SCOPE_DESCRIPTION>` = `changes to <scope description> between commit \href{<REPOSITORY_URL>/commit/<BASE_COMMIT>}{\texttt{<BASE_SHORT>}} and commit \href{<REPOSITORY_URL>/commit/<HEAD_COMMIT>}{\texttt{<HEAD_SHORT>}}` (commits from `.hex/diff.json`, short = first 7 characters). Replace the `<TOTAL_NSLOC>` sentence with the size of the change: `\textbf{The audit comprises} <ADDITIONS> added and <DELETIONS> removed lines of Solidity code across <FILES_CHANGED> files` (from `diff.json` `summary`). Everything else in the section is unchanged.
|
|
142
|
+
|
|
141
143
|
```latex
|
|
142
144
|
\pagebreak \vspace*{0cm}
|
|
143
145
|
\sectioncolor
|
|
@@ -222,6 +224,8 @@ Substitutions:
|
|
|
222
224
|
|
|
223
225
|
Write to `audited_files.txt` **and** `02-audited-files.tex`.
|
|
224
226
|
|
|
227
|
+
**Differential audit:** the rows are the files in `.hex/diff.json` `files` with status `added`, `modified` or `renamed` (not `deleted`), counted at the head commit, instead of every `project.scope` file. Keep the same columns; the table still describes the audited files at head. `<INITIAL_COMMIT>` in the links is the head commit.
|
|
228
|
+
|
|
225
229
|
Compute per-file line counts from each scope file. For each in-scope file in `config.json.project.scope`:
|
|
226
230
|
|
|
227
231
|
- Read the file. Count:
|
|
@@ -392,6 +396,8 @@ If the finding has multiple `root_cause.locations[]`, list them in the **File(s)
|
|
|
392
396
|
|
|
393
397
|
**A finding shows the relevant code as a fenced code block, not a line reference.** Authors embed a minimal ` ```solidity ` block in the description illustrating the issue; the report renders those (and any `root_cause.locations[].snippet` that a materialized finding happens to carry) as `minted` blocks.
|
|
394
398
|
|
|
399
|
+
Finding descriptions are authored already backticked and structured (identifiers in backticks, functions as `` `name(...)` `` which the markdown→LaTeX rule turns into `\texttt{name(...)}`, and short expected/flaw/impact paragraphs). Preserve that: render the paragraph breaks as-is (blank lines between paragraphs), do not collapse a multi-paragraph description into one block.
|
|
400
|
+
|
|
395
401
|
**Content the report must NOT contain** (enforced upstream at authoring time — the report renders synced GitHub content verbatim and does not rewrite it, so it must arrive clean):
|
|
396
402
|
- No specific source line numbers ("line 56", "on lines 43, 55") in `description` / `recommendation` — code is shown via `snippet` instead.
|
|
397
403
|
- No cross-references to other findings by hex id (`H-NNN`) or number/title — each finding stands alone; report readers have no hex ids.
|