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,133 @@
|
|
|
1
|
+
# Agent prompt templates — Turn 3a
|
|
2
|
+
|
|
3
|
+
The two prompts the orchestrator gives to the 12 agents. Agents 1–9 get the
|
|
4
|
+
single-specialty prompt; agents 10–12 get the gap-hunter prompt.
|
|
5
|
+
|
|
6
|
+
Both are verbatim text with values substituted in. Substitute `{bundle_dir}`,
|
|
7
|
+
the agent number `N`, and the bundle's real line count. Change nothing else.
|
|
8
|
+
|
|
9
|
+
The orchestrator reads this file in **Turn 2**, in the same parallel message
|
|
10
|
+
that reads `report-formatting.md` and `judging.md`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Single-specialty prompt
|
|
15
|
+
|
|
16
|
+
**Turn 3a-i — Single-specialty prompt template (agents 1–9, substitute real values):**
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
You are an attacker. Your specialty, mindset, source, and output rules
|
|
20
|
+
are in your bundle. Read it fully before producing findings.
|
|
21
|
+
|
|
22
|
+
Read first:
|
|
23
|
+
- {bundle_dir}/agent-N-bundle.md (XXXX lines) — source + SOP + specialty + shared rules.
|
|
24
|
+
|
|
25
|
+
The bundle contains all in-scope source. Do NOT re-read in-scope files
|
|
26
|
+
for the initial scan. Use Read/Grep only for cross-file searches or
|
|
27
|
+
out-of-scope context (interfaces/, mocks/, test/, and dependency
|
|
28
|
+
sources under node_modules/ or lib/ — read a base contract when the
|
|
29
|
+
behaviour it inherits matters).
|
|
30
|
+
|
|
31
|
+
You are READ-ONLY inside the audited repository. Never create, edit or
|
|
32
|
+
delete a file there — not a Foundry PoC, not a test, not a scratch note,
|
|
33
|
+
not even one you intend to delete afterwards. An audit that changes the
|
|
34
|
+
code it is measuring is not an audit. Write proof-of-concept code in your
|
|
35
|
+
own scratchpad, or quote it in your finding as text.
|
|
36
|
+
|
|
37
|
+
What a finding looks like:
|
|
38
|
+
- file, function
|
|
39
|
+
- root cause — the one-sentence code-level defect
|
|
40
|
+
- minimal fix — the smallest change that eliminates the defect
|
|
41
|
+
- proof — concrete numbers, a trace, or quoted code
|
|
42
|
+
|
|
43
|
+
Without concrete proof, it's a LEAD, not a finding. Leads are honest
|
|
44
|
+
about what you couldn't verify — they're not failures, they're
|
|
45
|
+
calibration. Emit them.
|
|
46
|
+
|
|
47
|
+
Don't skim. Don't trust your first read. Trust your discomfort.
|
|
48
|
+
|
|
49
|
+
Write every description in Simplified Technical English — the rules are
|
|
50
|
+
in your bundle, in "Report language". One sentence, 25 words or fewer,
|
|
51
|
+
active voice, no metaphor, and it names who acts and what they get.
|
|
52
|
+
Your bug_class label, the identifiers and any code you quote are data:
|
|
53
|
+
write those exactly as the source and the output rules require.
|
|
54
|
+
|
|
55
|
+
This is a differential audit. Your bundle carries "Differential audit —
|
|
56
|
+
focus": the source is the head version of the changed and impacted files
|
|
57
|
+
only. Spend your effort on the changed code and the flows that pass
|
|
58
|
+
through it. Report a bug in unchanged code only when the change makes it
|
|
59
|
+
reachable or worse, and say how. Other in-scope files were audited before;
|
|
60
|
+
Read them for context when a flow leaves your bundle.
|
|
61
|
+
|
|
62
|
+
Your bundle ends with "Known findings — ground already walked". Obey it:
|
|
63
|
+
spend your effort on new ground, report every bug you find in full —
|
|
64
|
+
the listed ones included — and reuse its bug-class labels for the same
|
|
65
|
+
class of bug in the same function.
|
|
66
|
+
|
|
67
|
+
Output format: see shared-rules.md inside your bundle.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The "differential audit" paragraph is included **only in a differential audit** (`{mode}` is `diff`, `diff-focus.md` appended). The "Known findings" paragraph is included **only when memory is on and `known-findings.md` was appended**. On a plain scan the prompt is byte-identical to the one it has always been — a paragraph about a section that is not there would send agents hunting for it.
|
|
71
|
+
|
|
72
|
+
The READ-ONLY paragraph is **unconditional** — every agent, every mode, every pass. It is here because a real scan proved it necessary: an agent built Foundry proof-of-concept files inside the audited repository and deleted them afterwards. It left the tree clean and the stored SHA honest, and it was still wrong. A later editor must not make it conditional, and must not soften it into a preference.
|
|
73
|
+
|
|
74
|
+
## Gap-hunter prompt
|
|
75
|
+
|
|
76
|
+
**Turn 3a-ii — Gap-hunter prompt template (agents 10–12, substitute real values):**
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
You are an attacker. Your gap-hunter specialty, mindset, source, and
|
|
80
|
+
output rules are in your bundle. Read it fully before producing findings.
|
|
81
|
+
|
|
82
|
+
Read first:
|
|
83
|
+
- {bundle_dir}/agent-N-bundle.md (XXXX lines) — source + SOP + gap-hunter specialty + shared rules.
|
|
84
|
+
|
|
85
|
+
The bundle contains all in-scope source. Do NOT re-read in-scope files
|
|
86
|
+
for the initial scan. Use Read/Grep only for cross-file searches or
|
|
87
|
+
out-of-scope context (interfaces/, mocks/, test/, and dependency
|
|
88
|
+
sources under node_modules/ or lib/ — read a base contract when the
|
|
89
|
+
behaviour it inherits matters).
|
|
90
|
+
|
|
91
|
+
You are READ-ONLY inside the audited repository. Never create, edit or
|
|
92
|
+
delete a file there — not a Foundry PoC, not a test, not a scratch note,
|
|
93
|
+
not even one you intend to delete afterwards. An audit that changes the
|
|
94
|
+
code it is measuring is not an audit. Write proof-of-concept code in your
|
|
95
|
+
own scratchpad, or quote it in your finding as text.
|
|
96
|
+
|
|
97
|
+
What a finding looks like:
|
|
98
|
+
- file, function
|
|
99
|
+
- seam — which two or three lenses combine
|
|
100
|
+
- root cause — the one-sentence code-level defect that lives at the seam
|
|
101
|
+
- minimal fix — the smallest change that eliminates the defect
|
|
102
|
+
- proof — concrete numbers, a trace, or quoted code showing the seam
|
|
103
|
+
|
|
104
|
+
Without concrete proof of the seam, it's a LEAD, not a finding.
|
|
105
|
+
Leads are honest about what you couldn't verify — they're not failures,
|
|
106
|
+
they're calibration. Emit them.
|
|
107
|
+
|
|
108
|
+
Don't skim. Don't trust your first read. Trust your discomfort.
|
|
109
|
+
|
|
110
|
+
Write every description in Simplified Technical English — the rules are
|
|
111
|
+
in your bundle, in "Report language". One sentence, 25 words or fewer,
|
|
112
|
+
active voice, no metaphor, and it names who acts and what they get.
|
|
113
|
+
Your bug_class label, the identifiers and any code you quote are data:
|
|
114
|
+
write those exactly as the source and the output rules require.
|
|
115
|
+
|
|
116
|
+
This is a differential audit. Your bundle carries "Differential audit —
|
|
117
|
+
focus": the source is the head version of the changed and impacted files
|
|
118
|
+
only. Spend your effort on the changed code and the flows that pass
|
|
119
|
+
through it. Report a bug in unchanged code only when the change makes it
|
|
120
|
+
reachable or worse, and say how. Other in-scope files were audited before;
|
|
121
|
+
Read them for context when a flow leaves your bundle.
|
|
122
|
+
|
|
123
|
+
Your bundle ends with "Known findings — ground already walked". Obey it:
|
|
124
|
+
spend your effort on new ground, report every bug you find in full —
|
|
125
|
+
the listed ones included — and reuse its bug-class labels for the same
|
|
126
|
+
class of bug in the same function.
|
|
127
|
+
|
|
128
|
+
Output format: see shared-rules.md inside your bundle (gap-hunter-specific
|
|
129
|
+
output fields are in your specialty file).
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The same two paragraphs, under the same conditions as Turn 3a-i: the differential paragraph only in a differential audit, the known-findings paragraph only with memory on and the file appended.
|
|
133
|
+
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# THE ASSEMBLER. It writes the whole ai-audit report. SKILL.md Turn 5 runs it.
|
|
3
|
+
#
|
|
4
|
+
# This is the only producer of a report in this skill. The orchestrator does not compose one,
|
|
5
|
+
# and must not be re-taught to: an orchestrator under context pressure is the thing that
|
|
6
|
+
# failed. Every finding this scan gated is in a run file; this script prints all of them or
|
|
7
|
+
# says out loud that it could not.
|
|
8
|
+
#
|
|
9
|
+
# assemble.sh --dir .hex/ai-audit/runs/{stamp}
|
|
10
|
+
#
|
|
11
|
+
# Reads ONE directory and writes {dir}/full-report.md — the complete report, banner line down
|
|
12
|
+
# to the disclaimer, ready to print word for word. No model judgment runs in here.
|
|
13
|
+
#
|
|
14
|
+
# reads dir/run-K.md the run files (ticket 01 shape), one per pass, model-written
|
|
15
|
+
# dir/scope.tsv key <TAB> value, append-only, LAST LINE PER KEY WINS
|
|
16
|
+
# dir/memory-before.tsv the pruned photocopy — its PRESENCE is not the memory flag,
|
|
17
|
+
# scope.tsv's `mem_before` key is
|
|
18
|
+
# dir/source-names.tsv normalised <TAB> as spelled in the source
|
|
19
|
+
# writes dir/full-report.md
|
|
20
|
+
# dir/winners.tsv (Hex) one row per key, the cross-run winner — Turn 6's input
|
|
21
|
+
#
|
|
22
|
+
# The model types the markers, so it can mistype one. The assembler CHECKS them and prints
|
|
23
|
+
# the disagreement into the Scope table. A broken run file becomes a visible line in the
|
|
24
|
+
# report, never a silent loss.
|
|
25
|
+
#
|
|
26
|
+
# Written to .part and moved into place on exit 0, so a half-report never exists.
|
|
27
|
+
set -euo pipefail
|
|
28
|
+
|
|
29
|
+
dir=
|
|
30
|
+
while [ $# -gt 0 ]; do
|
|
31
|
+
case "$1" in
|
|
32
|
+
--dir) dir=$2; shift 2 ;;
|
|
33
|
+
*) echo "assemble.sh: unknown argument $1" >&2; exit 2 ;;
|
|
34
|
+
esac
|
|
35
|
+
done
|
|
36
|
+
[ -d "$dir" ] || { echo "assemble.sh: no such directory $dir" >&2; exit 2; }
|
|
37
|
+
|
|
38
|
+
out="$dir/full-report.md"
|
|
39
|
+
work="$(mktemp -d)"
|
|
40
|
+
trap 'rm -rf "$work"' EXIT
|
|
41
|
+
|
|
42
|
+
THRESHOLD=75 # judging.md sets it. Named there and read here; never a second opinion.
|
|
43
|
+
|
|
44
|
+
# ---------------------------------------------------------------- scope.tsv, last wins
|
|
45
|
+
# An absent key gives an absent row. That is what keeps a plain scan's table at four rows.
|
|
46
|
+
# A missing scope.tsv is every key missing at once — the same path, no special case. It must
|
|
47
|
+
# not be a non-zero exit either: `set -e` would turn one absent label into no report at all.
|
|
48
|
+
scope() {
|
|
49
|
+
[ -f "$dir/scope.tsv" ] || return 0
|
|
50
|
+
awk -F'\t' -v k="$1" '$1==k { v=$2 } END { print v }' "$dir/scope.tsv"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
name=$(scope name); [ -n "$name" ] || name='**name missing**'
|
|
54
|
+
mode=$(scope mode); [ -n "$mode" ] || mode='**Mode missing**'
|
|
55
|
+
passes_planned=$(scope passes_planned)
|
|
56
|
+
mem_before=$(scope mem_before)
|
|
57
|
+
mem_after=$(scope mem_after)
|
|
58
|
+
mem_sha=$(scope mem_sha)
|
|
59
|
+
|
|
60
|
+
memory_on=0; [ -n "$mem_before" ] && memory_on=1
|
|
61
|
+
if [ "$memory_on" = 1 ] && [ ! -f "$dir/memory-before.tsv" ]; then
|
|
62
|
+
echo "assemble.sh: memory is on but $dir/memory-before.tsv is missing — Turn 5 did not copy it" >&2
|
|
63
|
+
memory_on=0
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# run files in PASS order. A plain glob puts run-10 before run-2, which is a real 10-pass bug.
|
|
67
|
+
runs=()
|
|
68
|
+
while IFS= read -r f; do runs+=("$f"); done < <(
|
|
69
|
+
ls "$dir"/run-*.md 2>/dev/null | sed 's/.*run-\([0-9]*\)\.md/\1 &/' | sort -n | cut -d' ' -f2)
|
|
70
|
+
N=${#runs[@]}
|
|
71
|
+
|
|
72
|
+
# ---------------------------------------------------------------- index every block
|
|
73
|
+
# key conf kind agents file pass start end bodystart bodyend title loc leadbody
|
|
74
|
+
#
|
|
75
|
+
# A FINDING and a LEAD are NOT the same shape on disk, and one geometry read over both is what
|
|
76
|
+
# produced `- **- **Title**` rows and a "Body missing" line under leads that had a body:
|
|
77
|
+
#
|
|
78
|
+
# FINDING LEAD
|
|
79
|
+
# +0 <!--F ...--> +0 <!--F ...-->
|
|
80
|
+
# +1 +1
|
|
81
|
+
# +2 [95] **1. T** +2 - **T** — `loc` · TAG — smells — why not verified
|
|
82
|
+
# +3 +3
|
|
83
|
+
# +4 `loc` · Conf +4 <!--/F-->
|
|
84
|
+
# +5
|
|
85
|
+
# +6 body …
|
|
86
|
+
#
|
|
87
|
+
# Read with the finding geometry, a lead put its WHOLE formatted line in `title` (which the
|
|
88
|
+
# emitter then wrapped in `- **…**` a second time), found no backticks at +4 so `loc` came out
|
|
89
|
+
# empty, and had no body region at all. Each kind now gets its own reader.
|
|
90
|
+
#
|
|
91
|
+
# **No field is ever emitted empty** — `-` stands in. `read` below splits on IFS=$'\t', and a
|
|
92
|
+
# tab is IFS *whitespace*, so bash collapses `\t\t` into one delimiter and every later field
|
|
93
|
+
# shifts left by one. That is how a lead's memory tag ended up printed as its location.
|
|
94
|
+
: > "$work/index.tsv"
|
|
95
|
+
for f in ${runs[@]+"${runs[@]}"}; do
|
|
96
|
+
awk -v F="$f" '
|
|
97
|
+
/^<!--RUN / { line=$0; sub(/[[:space:]]*-->[[:space:]]*$/, "", line)
|
|
98
|
+
n=split(line, a, /[[:space:]]+/)
|
|
99
|
+
for (i=2; i<=n; i++) { eq=index(a[i],"="); if (substr(a[i],1,eq-1)=="pass") pass=substr(a[i],eq+1) } }
|
|
100
|
+
/^<!--F / {
|
|
101
|
+
key=""; conf=""; kind=""; agents=""
|
|
102
|
+
line = $0
|
|
103
|
+
sub(/[[:space:]]*-->[[:space:]]*$/, "", line) # terminator off BEFORE splitting
|
|
104
|
+
n = split(line, a, /[[:space:]]+/)
|
|
105
|
+
for (i = 2; i <= n; i++) {
|
|
106
|
+
eq = index(a[i], "="); nm = substr(a[i], 1, eq-1); v = substr(a[i], eq+1)
|
|
107
|
+
if (nm == "key") key = v; else if (nm == "conf") conf = v
|
|
108
|
+
else if (nm == "kind") kind = v; else if (nm == "agents") agents = v
|
|
109
|
+
}
|
|
110
|
+
if (conf == "") conf = "-" # a LEAD is not scored
|
|
111
|
+
start = NR; title = ""; loc = ""; lbody = ""
|
|
112
|
+
next
|
|
113
|
+
}
|
|
114
|
+
kind != "LEAD" && start && NR == start + 2 { t = $0; sub(/^\[[0-9]+\] /, "", t); sub(/^\*\*/, "", t); sub(/\*\*$/, "", t); title = t }
|
|
115
|
+
kind != "LEAD" && start && NR == start + 4 { l = $0; if (match(l, /`[^`]*`/)) loc = substr(l, RSTART+1, RLENGTH-2) }
|
|
116
|
+
|
|
117
|
+
# A lead is one line. Split it here, once, so the emitter formats leads and findings with
|
|
118
|
+
# the same fields instead of re-printing a line that is already formatted.
|
|
119
|
+
# `match` + RSTART/RLENGTH, never index()+a literal width: the separator is an em dash,
|
|
120
|
+
# 3 bytes and 1 character, and the two disagree across awks and locales.
|
|
121
|
+
kind == "LEAD" && start && NR == start + 2 && /^- \*\*/ {
|
|
122
|
+
l = $0
|
|
123
|
+
sub(/^- \*\*/, "", l)
|
|
124
|
+
if (match(l, /\*\* — /)) { title = substr(l, 1, RSTART-1); l = substr(l, RSTART+RLENGTH) }
|
|
125
|
+
else { title = l; l = "" }
|
|
126
|
+
if (match(l, /^`[^`]*`/)) { loc = substr(l, RSTART+1, RLENGTH-2); l = substr(l, RSTART+RLENGTH) }
|
|
127
|
+
# What is left is " · NEW — body" or " — body". Either way the body starts after the
|
|
128
|
+
# first " — ". The inline tag is DROPPED: the assembler derives the memory tag itself
|
|
129
|
+
# from memory-before.tsv, and two sources for one fact is how they come to disagree.
|
|
130
|
+
if (match(l, / — /)) l = substr(l, RSTART+RLENGTH); else l = ""
|
|
131
|
+
lbody = l
|
|
132
|
+
}
|
|
133
|
+
/^<!--\/F-->/ && start {
|
|
134
|
+
if (title == "") title = "-"
|
|
135
|
+
if (loc == "") loc = "-"
|
|
136
|
+
if (lbody == "") lbody = "-"
|
|
137
|
+
print key "\t" conf "\t" kind "\t" agents "\t" F "\t" pass "\t" start "\t" NR "\t" (start+6) "\t" (NR-1) "\t" title "\t" loc "\t" lbody
|
|
138
|
+
start = 0; kind = ""
|
|
139
|
+
}
|
|
140
|
+
' "$f" >> "$work/index.tsv"
|
|
141
|
+
done
|
|
142
|
+
|
|
143
|
+
# ---------------------------------------------------------------- the structure check
|
|
144
|
+
# The model typed these markers. When the counts disagree, a finding was raised and cannot be
|
|
145
|
+
# read — say so IN the report. The report may print less than the scan found; it may never
|
|
146
|
+
# claim to print more.
|
|
147
|
+
#
|
|
148
|
+
# No run file at all is the same rule at its limit: pass 1 produced nothing, so the scan
|
|
149
|
+
# reviewed nothing. That is a REPORT, not an exit — SKILL.md Turn 3b routes a real scan down
|
|
150
|
+
# here, and a shell error in place of a report is the one outcome this skill must never have.
|
|
151
|
+
# The row is necessary because the Passes row is suppressed on a 1-pass scan, so without it
|
|
152
|
+
# nothing in the report would say the pass died.
|
|
153
|
+
broken=
|
|
154
|
+
if [ "$N" = 0 ]; then
|
|
155
|
+
broken="⚠️ No pass produced a run file. This scan reviewed nothing."
|
|
156
|
+
echo "assemble.sh: NO RUN FILES — $broken" >&2
|
|
157
|
+
else
|
|
158
|
+
opens=$(cat "${runs[@]}" | grep -c '^<!--F ' || :)
|
|
159
|
+
closes=$(cat "${runs[@]}" | grep -c '^<!--/F-->' || :)
|
|
160
|
+
indexed=$(wc -l < "$work/index.tsv" | tr -d ' ')
|
|
161
|
+
if [ "$opens" != "$closes" ] || [ "$opens" != "$indexed" ]; then
|
|
162
|
+
broken="⚠️ $opens findings marked, $indexed readable. $(( opens - indexed )) could not be read and are missing below. See the run files."
|
|
163
|
+
echo "assemble.sh: STRUCTURE BROKEN — $broken" >&2
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# ---------------------------------------------------------------- dedup across runs
|
|
168
|
+
# One winner per key: strongest kind, then highest confidence, then the LATER pass — a later
|
|
169
|
+
# pass read the ledger every earlier pass wrote, so it is the better-informed write-up.
|
|
170
|
+
# k counts every run that raised the key, in either section.
|
|
171
|
+
sort -t $'\t' -k1,1 "$work/index.tsv" | awk -F'\t' '
|
|
172
|
+
function rank(k) { return (k == "FINDING") ? 1 : 0 }
|
|
173
|
+
{
|
|
174
|
+
if (!(($5 SUBSEP $1) in seenrun)) { seenrun[$5 SUBSEP $1]=1; k[$1]++ }
|
|
175
|
+
c = ($2 == "-") ? -1 : $2 + 0
|
|
176
|
+
if (!($1 in best) || rank($3) > br[$1] || (rank($3) == br[$1] && c > bc[$1]) \
|
|
177
|
+
|| (rank($3) == br[$1] && c == bc[$1] && $6 + 0 >= bp[$1])) {
|
|
178
|
+
best[$1] = $0; br[$1] = rank($3); bc[$1] = c; bp[$1] = $6 + 0
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
END { for (key in best) print k[key] "\t" best[key] }
|
|
182
|
+
' > "$work/merged.tsv"
|
|
183
|
+
|
|
184
|
+
# ---------------------------------------------------------------- the memory tag
|
|
185
|
+
# Derived here from memory-before.tsv, not carried in the marker. One source: the report and
|
|
186
|
+
# the ledger cannot disagree because both read the same photocopy.
|
|
187
|
+
# KNOWN (n scans) — the STORED count plus one; this scan has just found it again.
|
|
188
|
+
if [ "$memory_on" = 1 ]; then
|
|
189
|
+
awk -F'\t' -v OFS='\t' '
|
|
190
|
+
FILENAME==ARGV[1] { if (FNR>1) sc[$1]=$3; next }
|
|
191
|
+
{ print $0, ($2 in sc) ? "KNOWN (" sc[$2]+1 " scans)" : "NEW" }
|
|
192
|
+
' "$dir/memory-before.tsv" "$work/merged.tsv" > "$work/merged.tagged.tsv"
|
|
193
|
+
else
|
|
194
|
+
awk -F'\t' -v OFS='\t' '{ print $0, "" }' "$work/merged.tsv" > "$work/merged.tagged.tsv"
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
# columns now: 1 k · 2 key · 3 conf · 4 kind · 5 agents · 6 file · 7 pass · 8 start · 9 end
|
|
198
|
+
# 10 bodystart · 11 bodyend · 12 title · 13 loc · 14 leadbody · 15 memtag
|
|
199
|
+
# 12, 13 and 14 are never empty — `-` stands in, because IFS=$'\t' collapses adjacent tabs.
|
|
200
|
+
sort -t $'\t' -k4,4 -k3,3nr -k2,2 "$work/merged.tagged.tsv" > "$work/sorted.tsv"
|
|
201
|
+
# Hex: persist the winners before the work dir is deleted. Same 15 columns as above, FINDINGs
|
|
202
|
+
# first, highest confidence first. hex-export.sh reads it; nothing in this script reads it back.
|
|
203
|
+
cp "$work/sorted.tsv" "$dir/winners.tsv"
|
|
204
|
+
awk -F'\t' '$4=="FINDING"' "$work/sorted.tsv" > "$work/findings.tsv"
|
|
205
|
+
awk -F'\t' '$4=="LEAD"' "$work/sorted.tsv" > "$work/leads.tsv"
|
|
206
|
+
|
|
207
|
+
nfind=$(wc -l < "$work/findings.tsv" | tr -d ' ')
|
|
208
|
+
nlead=$(wc -l < "$work/leads.tsv" | tr -d ' ')
|
|
209
|
+
|
|
210
|
+
# ---------------------------------------------------------------- emit
|
|
211
|
+
R="$work/report.md"
|
|
212
|
+
: > "$R"
|
|
213
|
+
say() { printf '%s\n' "$1" >> "$R"; }
|
|
214
|
+
rule() { say ""; say "---"; say ""; }
|
|
215
|
+
row() { printf '| %s | %s |\n' "$1" "$2" >> "$R"; }
|
|
216
|
+
|
|
217
|
+
say "# 🔐 Security Review — $name"
|
|
218
|
+
rule
|
|
219
|
+
say "## Scope"
|
|
220
|
+
say ""
|
|
221
|
+
row "" ""
|
|
222
|
+
row "---" "---"
|
|
223
|
+
row "**Mode**" "$mode"
|
|
224
|
+
|
|
225
|
+
# Files reviewed — 3 per line, in source.md order, joined with `<br>`. One `files` key holds
|
|
226
|
+
# them space separated; shell does the wrapping.
|
|
227
|
+
files=$(scope files | tr ' ' '\n' | awk 'NF { printf "`%s`", $0; if (++n % 3 == 0) printf "<br>"; else printf " · " }' \
|
|
228
|
+
| sed -e 's/ · $//' -e 's/<br>$//')
|
|
229
|
+
row "**Files reviewed**" "$files"
|
|
230
|
+
row "**Confidence threshold (1-100)**" "$THRESHOLD"
|
|
231
|
+
|
|
232
|
+
# The Passes cell is COMPOSED from facts, never written as prose by a model.
|
|
233
|
+
if [ -n "$passes_planned" ] && [ "$passes_planned" -gt 1 ] 2>/dev/null; then
|
|
234
|
+
short=""
|
|
235
|
+
for k in $(seq 1 "$passes_planned"); do
|
|
236
|
+
a=$(scope "pass_${k}_agents"); fail=$(scope "pass_${k}_failed")
|
|
237
|
+
if [ -n "$fail" ]; then short="${short:+$short, }pass $k failed"
|
|
238
|
+
elif [ -n "$a" ] && [ "$a" != "12/12" ]; then short="${short:+$short, }pass $k ran $a agents"; fi
|
|
239
|
+
done
|
|
240
|
+
if [ "$N" -lt "$passes_planned" ]; then cell="$N of $passes_planned"; else cell="$passes_planned"; fi
|
|
241
|
+
[ -n "$short" ] && cell="$cell ($short)"
|
|
242
|
+
row "**Passes**" "$cell"
|
|
243
|
+
fi
|
|
244
|
+
[ "$memory_on" = 1 ] && row "**Memory**" "$mem_before records before this scan · $mem_after after · \`$mem_sha\`"
|
|
245
|
+
[ -n "$broken" ] && row "**Run files**" "$broken"
|
|
246
|
+
rule
|
|
247
|
+
|
|
248
|
+
say "## Findings"
|
|
249
|
+
say ""
|
|
250
|
+
|
|
251
|
+
emit_body() { # file bodystart bodyend — copied through, never re-worded
|
|
252
|
+
awk -v s="$2" -v e="$3" 'NR>=s && NR<=e' "$1" \
|
|
253
|
+
| awk '{ lines[++n] = $0 } END {
|
|
254
|
+
b=1; while (b<=n && lines[b]=="") b++
|
|
255
|
+
while (n>=b && lines[n]=="") n--
|
|
256
|
+
for (i=b; i<=n; i++) print lines[i] }'
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
i=0
|
|
260
|
+
while IFS=$'\t' read -r k key conf kind agents file pass start end bstart bend title loc lbody memtag; do
|
|
261
|
+
i=$((i+1))
|
|
262
|
+
[ "$title" = "-" ] && title="**Title missing** — the block's title line could not be read"
|
|
263
|
+
if [ "$loc" = "-" ]; then meta="**location missing**"; else meta="\`$loc\`"; fi
|
|
264
|
+
say "[$conf] **$i. $title**"
|
|
265
|
+
say ""
|
|
266
|
+
meta="$meta · Confidence: $conf"
|
|
267
|
+
[ "$N" -gt 1 ] && meta="$meta · seen in $k/$N runs"
|
|
268
|
+
[ -n "$memtag" ] && meta="$meta · $memtag"
|
|
269
|
+
say "$meta"
|
|
270
|
+
say ""
|
|
271
|
+
body=$(emit_body "$file" "$bstart" "$bend")
|
|
272
|
+
if [ -z "$body" ]; then
|
|
273
|
+
say "**Body missing** — pass $pass raised this finding and wrote no description."
|
|
274
|
+
else
|
|
275
|
+
printf '%s\n' "$body" >> "$R"
|
|
276
|
+
fi
|
|
277
|
+
rule
|
|
278
|
+
done < "$work/findings.tsv"
|
|
279
|
+
|
|
280
|
+
if [ "$nfind" = 0 ]; then
|
|
281
|
+
# An empty table with a header row and no rows under it is not a report of nothing, it is a
|
|
282
|
+
# report that looks broken. Say it in words instead.
|
|
283
|
+
say "_None — this scan raised no findings._"
|
|
284
|
+
rule
|
|
285
|
+
else
|
|
286
|
+
say "Findings List"
|
|
287
|
+
say ""
|
|
288
|
+
say "| # | Confidence | Title |"
|
|
289
|
+
say "|---|---|---|"
|
|
290
|
+
i=0; sep=0
|
|
291
|
+
while IFS=$'\t' read -r k key conf kind agents file pass start end bstart bend title loc lbody memtag; do
|
|
292
|
+
i=$((i+1))
|
|
293
|
+
if [ "$sep" = 0 ] && [ "$conf" -lt "$THRESHOLD" ]; then
|
|
294
|
+
say "| | | **Below Confidence Threshold** |"; sep=1
|
|
295
|
+
fi
|
|
296
|
+
say "| $i | [$conf] | $title |"
|
|
297
|
+
done < "$work/findings.tsv"
|
|
298
|
+
rule
|
|
299
|
+
fi
|
|
300
|
+
|
|
301
|
+
say "## Leads"
|
|
302
|
+
say ""
|
|
303
|
+
say "_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._"
|
|
304
|
+
say ""
|
|
305
|
+
[ "$nlead" = 0 ] && say "_None._"
|
|
306
|
+
while IFS=$'\t' read -r k key conf kind agents file pass start end bstart bend title loc lbody memtag; do
|
|
307
|
+
seg=""
|
|
308
|
+
[ "$N" -gt 1 ] && seg="$seg · seen in $k/$N runs"
|
|
309
|
+
[ -n "$memtag" ] && seg="$seg · $memtag"
|
|
310
|
+
# The body was parsed out of the lead's own line by the indexer. Do NOT read it back out of
|
|
311
|
+
# the run file here: a lead has no body region, so emit_body returned nothing and every lead
|
|
312
|
+
# got the "Body missing" line whether or not it had one.
|
|
313
|
+
[ "$title" = "-" ] && title="**Title missing** — the lead's line could not be read"
|
|
314
|
+
if [ "$loc" = "-" ]; then locmd="**location missing**"; else locmd="\`$loc\`"; fi
|
|
315
|
+
[ "$lbody" = "-" ] && lbody="**Body missing** — pass $pass raised this lead and wrote no description."
|
|
316
|
+
say "- **$title** — $locmd$seg — $lbody"
|
|
317
|
+
done < "$work/leads.tsv"
|
|
318
|
+
|
|
319
|
+
# ---------------------------------------------------------------- Known from earlier scans
|
|
320
|
+
# The keys this scan raised come from the index — the run files are the record, so no separate
|
|
321
|
+
# run-keys.tsv or scan-rows.tsv has to be carried in.
|
|
322
|
+
if [ "$memory_on" = 1 ]; then
|
|
323
|
+
held=$(( $(wc -l < "$dir/memory-before.tsv") - 1 ))
|
|
324
|
+
if [ "$held" -gt 0 ]; then
|
|
325
|
+
tail -n +2 "$dir/memory-before.tsv" | cut -f1 | sort -u > "$work/keys-before.txt"
|
|
326
|
+
cut -f1 "$work/index.tsv" | sort -u > "$work/keys-scan.txt"
|
|
327
|
+
comm -23 "$work/keys-before.txt" "$work/keys-scan.txt" > "$work/keys-left.txt"
|
|
328
|
+
rule
|
|
329
|
+
say "## Known from earlier scans"
|
|
330
|
+
say ""
|
|
331
|
+
say "_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\`._"
|
|
332
|
+
say ""
|
|
333
|
+
if [ -s "$work/keys-left.txt" ]; then
|
|
334
|
+
say "| Scans | Kind | Location | Title |"
|
|
335
|
+
say "|---|---|---|---|"
|
|
336
|
+
awk -F'\t' '
|
|
337
|
+
FILENAME==ARGV[1] { nm[$1]=$2; next }
|
|
338
|
+
FILENAME==ARGV[2] { if (FNR>1) { sc[$1]=$3; ti[$1]=$5; ki[$1]=$6 } ; next }
|
|
339
|
+
{
|
|
340
|
+
split($1, p, "|")
|
|
341
|
+
c = (p[1] in nm) ? nm[p[1]] : p[1] # print-as-stored when the segment is not in the map
|
|
342
|
+
f = (p[2] in nm) ? nm[p[2]] : p[2]
|
|
343
|
+
print "| " sc[$1] " | " ki[$1] " | `" c "." f "` | " ti[$1] " |"
|
|
344
|
+
}
|
|
345
|
+
' "$dir/source-names.tsv" "$dir/memory-before.tsv" "$work/keys-left.txt" >> "$R"
|
|
346
|
+
else
|
|
347
|
+
say "_None — every record in the ledger was raised again by this scan._"
|
|
348
|
+
fi
|
|
349
|
+
fi
|
|
350
|
+
fi
|
|
351
|
+
|
|
352
|
+
rule
|
|
353
|
+
say "> ⚠️ 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."
|
|
354
|
+
|
|
355
|
+
cp "$R" "$out.part"
|
|
356
|
+
mv "$out.part" "$out"
|
|
357
|
+
echo "assembled $out — $nfind findings, $nlead leads, $N run files"
|