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.
Files changed (333) hide show
  1. package/DEMO.md +13 -0
  2. package/README.md +60 -6
  3. package/dashboard/.next/BUILD_ID +1 -1
  4. package/dashboard/.next/app-build-manifest.json +100 -89
  5. package/dashboard/.next/app-path-routes-manifest.json +1 -1
  6. package/dashboard/.next/build-manifest.json +14 -14
  7. package/dashboard/.next/next-server.js.nft.json +1 -1
  8. package/dashboard/.next/prerender-manifest.js +1 -1
  9. package/dashboard/.next/prerender-manifest.json +1 -1
  10. package/dashboard/.next/react-loadable-manifest.json +118 -118
  11. package/dashboard/.next/routes-manifest.json +1 -1
  12. package/dashboard/.next/server/app/_not-found/page.js +1 -1
  13. package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/dashboard/.next/server/app/access/page.js +1 -1
  15. package/dashboard/.next/server/app/access/page.js.nft.json +1 -1
  16. package/dashboard/.next/server/app/access/page_client-reference-manifest.js +1 -1
  17. package/dashboard/.next/server/app/calls/page.js +1 -1
  18. package/dashboard/.next/server/app/calls/page.js.nft.json +1 -1
  19. package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +1 -1
  20. package/dashboard/.next/server/app/changes/page.js +20 -0
  21. package/dashboard/.next/server/app/changes/page.js.nft.json +1 -0
  22. package/dashboard/.next/server/app/changes/page_client-reference-manifest.js +1 -0
  23. package/dashboard/.next/server/app/conformance/page.js +1 -1
  24. package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +1 -1
  25. package/dashboard/.next/server/app/diagram/page.js +1 -1
  26. package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +1 -1
  27. package/dashboard/.next/server/app/flows/page.js +1 -1
  28. package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +1 -1
  29. package/dashboard/.next/server/app/functions/page.js +1 -1
  30. package/dashboard/.next/server/app/functions/page.js.nft.json +1 -1
  31. package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +1 -1
  32. package/dashboard/.next/server/app/issues/page.js +6 -6
  33. package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -1
  34. package/dashboard/.next/server/app/notes/page.js +3 -3
  35. package/dashboard/.next/server/app/notes/page_client-reference-manifest.js +1 -1
  36. package/dashboard/.next/server/app/page.js +2 -2
  37. package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
  38. package/dashboard/.next/server/app/progress/page.js +1 -1
  39. package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +1 -1
  40. package/dashboard/.next/server/app/report/page.js +1 -1
  41. package/dashboard/.next/server/app/report/page_client-reference-manifest.js +1 -1
  42. package/dashboard/.next/server/app/stats/page.js +1 -1
  43. package/dashboard/.next/server/app/stats/page.js.nft.json +1 -1
  44. package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +1 -1
  45. package/dashboard/.next/server/app-paths-manifest.json +9 -8
  46. package/dashboard/.next/server/chunks/42.js +1 -1
  47. package/dashboard/.next/server/chunks/530.js +1 -1
  48. package/dashboard/.next/server/chunks/649.js +1 -1
  49. package/dashboard/.next/server/chunks/939.js +1 -0
  50. package/dashboard/.next/server/functions-config-manifest.json +1 -1
  51. package/dashboard/.next/server/middleware-build-manifest.js +1 -1
  52. package/dashboard/.next/server/middleware-react-loadable-manifest.js +1 -1
  53. package/dashboard/.next/server/next-font-manifest.js +1 -1
  54. package/dashboard/.next/server/next-font-manifest.json +1 -1
  55. package/dashboard/.next/server/pages/500.html +1 -1
  56. package/dashboard/.next/server/pages-manifest.json +1 -1
  57. package/dashboard/.next/server/server-reference-manifest.js +1 -1
  58. package/dashboard/.next/server/server-reference-manifest.json +1 -1
  59. package/dashboard/.next/static/chunks/{1.8868c4d131111be7.js → 1.a666047ea18866fb.js} +2 -2
  60. package/dashboard/.next/static/chunks/1015.39008440ab15e196.js +226 -0
  61. package/dashboard/.next/static/chunks/1151.497fa63c5b9eba52.js +1 -0
  62. package/dashboard/.next/static/chunks/1199.f30cbfa151e56076.js +148 -0
  63. package/dashboard/.next/static/chunks/1375.64c20f1064a38a10.js +43 -0
  64. package/dashboard/.next/static/chunks/1799.8dc56017eede704e.js +9 -0
  65. package/dashboard/.next/static/chunks/20154aaa.e87f69fe10483f8b.js +1 -0
  66. package/dashboard/.next/static/chunks/2077.5603adeb156c7d10.js +1 -0
  67. package/dashboard/.next/static/chunks/2166.9f6592b9399eadd8.js +215 -0
  68. package/dashboard/.next/static/chunks/{2291.85a70cb0c228157b.js → 2291.584b42ccad079b99.js} +1 -1
  69. package/dashboard/.next/static/chunks/2325.7decd077edfb81d9.js +24 -0
  70. package/dashboard/.next/static/chunks/{2383.62c035a052272594.js → 2383.ca81f980ce6528a4.js} +1 -1
  71. package/dashboard/.next/static/chunks/2694.7dfa5fef28851903.js +1 -0
  72. package/dashboard/.next/static/chunks/275.38af87389c1d33d7.js +34 -0
  73. package/dashboard/.next/static/chunks/2781.fba46046dbf2693b.js +93 -0
  74. package/dashboard/.next/static/chunks/2805.35b4cd8a94978aaf.js +1 -0
  75. package/dashboard/.next/static/chunks/{2879.51436986f93981d9.js → 2879.74d65e33e60505ee.js} +1 -1
  76. package/dashboard/.next/static/chunks/3017.4a5312e3c20a173f.js +1 -0
  77. package/dashboard/.next/static/chunks/3205-47d09be47325709f.js +2 -0
  78. package/dashboard/.next/static/chunks/3236.eac9855778a54518.js +1 -0
  79. package/dashboard/.next/static/chunks/3480.853a445a3784642a.js +1 -0
  80. package/dashboard/.next/static/chunks/3626.c5dacee11c8fbc4d.js +64 -0
  81. package/dashboard/.next/static/chunks/3865.5e6d2d501380e03b.js +90 -0
  82. package/dashboard/.next/static/chunks/3887.073cece834a4eae2.js +1 -0
  83. package/dashboard/.next/static/chunks/3924-88d849290406ee6f.js +1 -0
  84. package/dashboard/.next/static/chunks/3948.74201b9f0672234d.js +287 -0
  85. package/dashboard/.next/static/chunks/4728.e69372b5e5b61b8d.js +24 -0
  86. package/dashboard/.next/static/chunks/4787.821a6ad2816cdc60.js +23 -0
  87. package/dashboard/.next/static/chunks/5060.47402abc10273699.js +1 -0
  88. package/dashboard/.next/static/chunks/5284.334c7c0587d5d47a.js +1 -0
  89. package/dashboard/.next/static/chunks/5715.e16b1230cc4b4652.js +115 -0
  90. package/dashboard/.next/static/chunks/6014.641a2c53ba506241.js +104 -0
  91. package/dashboard/.next/static/chunks/6024.f099c15f75aa6722.js +79 -0
  92. package/dashboard/.next/static/chunks/{6052.033a6f1013c666eb.js → 6052.3001318955e5b36c.js} +2 -2
  93. package/dashboard/.next/static/chunks/6177.a01cf0a03734cf09.js +1 -0
  94. package/dashboard/.next/static/chunks/618f8807-69fc7bb97c2b87c1.js +1 -0
  95. package/dashboard/.next/static/chunks/6434.f560693253fea8de.js +1 -0
  96. package/dashboard/.next/static/chunks/6468.976d89ba133185f1.js +77 -0
  97. package/dashboard/.next/static/chunks/6540.6f3c4f2c6877ed89.js +1 -0
  98. package/dashboard/.next/static/chunks/6549.e3c4c1766cff1449.js +1 -0
  99. package/dashboard/.next/static/chunks/690f35d0.ab57e02a04c7e9e0.js +119 -0
  100. package/dashboard/.next/static/chunks/{7020.831e16e26d91abc1.js → 7020.b718b1b9cea36e60.js} +2 -2
  101. package/dashboard/.next/static/chunks/7397-37adf76cad543297.js +1 -0
  102. package/dashboard/.next/static/chunks/7498-d1814d68ba346d13.js +1 -0
  103. package/dashboard/.next/static/chunks/7802.f0134c792fccd382.js +80 -0
  104. package/dashboard/.next/static/chunks/7973.e34032723285a616.js +79 -0
  105. package/dashboard/.next/static/chunks/{7a04ac15.1c6cea694301806c.js → 7a04ac15.e49de94ece135900.js} +1 -1
  106. package/dashboard/.next/static/chunks/8216.1138ec313908a708.js +5 -0
  107. package/dashboard/.next/static/chunks/{8233babc.780b8e272eda298f.js → 8233babc.09872dcb3ff44064.js} +1 -1
  108. package/dashboard/.next/static/chunks/{8452-e616b5f43bceb95f.js → 8452-6d77fa353402422c.js} +2 -2
  109. package/dashboard/.next/static/chunks/8645.98a43217d406500e.js +1 -0
  110. package/dashboard/.next/static/chunks/8928-fc049decdfbdaa6d.js +1 -0
  111. package/dashboard/.next/static/chunks/9173.a7160f7d0b685fa7.js +1 -0
  112. package/dashboard/.next/static/chunks/9178.998a8c49996de8e4.js +1 -0
  113. package/dashboard/.next/static/chunks/9466.a914ce0de7d3bb84.js +1 -0
  114. package/dashboard/.next/static/chunks/9660.b1c8deae2c449d14.js +1 -0
  115. package/dashboard/.next/static/chunks/{9717.6cf5c8c89403b651.js → 9717.bba51b78ebd8fd29.js} +1 -1
  116. package/dashboard/.next/static/chunks/9720.d63a0696776bcc60.js +1 -0
  117. package/dashboard/.next/static/chunks/9811.2993c4cbd28e8d1b.js +1 -0
  118. package/dashboard/.next/static/chunks/app/_not-found/page-c299b935209993df.js +1 -0
  119. package/dashboard/.next/static/chunks/app/access/page-f8403cbdfc1c176b.js +1 -0
  120. package/dashboard/.next/static/chunks/app/calls/page-41f20d01e12382ef.js +1 -0
  121. package/dashboard/.next/static/chunks/app/changes/page-82bf8b6f48cdc506.js +1 -0
  122. package/dashboard/.next/static/chunks/app/conformance/page-6bb8e3b372e38098.js +1 -0
  123. package/dashboard/.next/static/chunks/app/diagram/page-469cd7a6f183efba.js +1 -0
  124. package/dashboard/.next/static/chunks/app/flows/page-7872dd9141ba0b07.js +1 -0
  125. package/dashboard/.next/static/chunks/app/functions/page-5847bcb77a8e7edf.js +1 -0
  126. package/dashboard/.next/static/chunks/app/issues/page-1ffc64fe40439002.js +1 -0
  127. package/dashboard/.next/static/chunks/app/layout-6c6d2a0fd7c989d3.js +1 -0
  128. package/dashboard/.next/static/chunks/app/notes/page-8bcaa52304500098.js +1 -0
  129. package/dashboard/.next/static/chunks/app/page-d63800ddb072b77b.js +1 -0
  130. package/dashboard/.next/static/chunks/app/progress/page-e26554f655a62eef.js +1 -0
  131. package/dashboard/.next/static/chunks/app/report/page-18c04fb2f193b020.js +1 -0
  132. package/dashboard/.next/static/chunks/app/stats/page-67ff59fd69bed651.js +1 -0
  133. package/dashboard/.next/static/chunks/{b7167ec1.7afbab6f609e3326.js → b7167ec1.708a3d61698ca2e6.js} +1 -1
  134. package/dashboard/.next/static/chunks/c7ea4e13.3073a2f551aa5ac8.js +1 -0
  135. package/dashboard/.next/static/chunks/framework-a117d81bf1b91f9a.js +33 -0
  136. package/dashboard/.next/static/chunks/main-app-5662c64b50ba40d1.js +1 -0
  137. package/dashboard/.next/static/chunks/main-cc3a889b25e9aa68.js +1 -0
  138. package/dashboard/.next/static/chunks/pages/_app-308fef0bf9b328f2.js +1 -0
  139. package/dashboard/.next/static/chunks/pages/_error-c91b5eabd7ac9382.js +1 -0
  140. package/dashboard/.next/static/chunks/webpack-4de0e79bdd6a0418.js +1 -0
  141. package/dashboard/.next/static/css/1112cea2260b3926.css +3 -0
  142. package/dashboard/.next/static/media/39f449c8730c2295-s.woff2 +0 -0
  143. package/dashboard/.next/static/media/86f65e8637cc94e3-s.woff2 +0 -0
  144. package/dashboard/.next/static/media/8760c4774489e4ba-s.p.woff2 +0 -0
  145. package/dashboard/.next/static/media/9fabb9c65b63d798-s.woff2 +0 -0
  146. package/dashboard/.next/static/media/a1f87af3f44fadbb-s.woff2 +0 -0
  147. package/dashboard/.next/static/media/f9e1dbe9676d9bb6-s.woff2 +0 -0
  148. package/dashboard/.next/static/z5XBev05xDAkDrxWxAjNu/_buildManifest.js +1 -0
  149. package/dashboard/app/changes/ChangesClient.tsx +464 -0
  150. package/dashboard/app/changes/page.tsx +36 -0
  151. package/dashboard/app/issues/IssuesBoardClient.tsx +11 -1
  152. package/dashboard/app/layout.tsx +13 -1
  153. package/dashboard/app/notes/NotesClient.tsx +5 -0
  154. package/dashboard/app/page.tsx +42 -0
  155. package/dashboard/components/DashboardLayout.tsx +43 -18
  156. package/dist/analysis/code-model.d.ts +113 -0
  157. package/dist/analysis/code-model.d.ts.map +1 -0
  158. package/dist/analysis/code-model.js +529 -0
  159. package/dist/analysis/code-model.js.map +1 -0
  160. package/dist/analysis/diff.d.ts +64 -0
  161. package/dist/analysis/diff.d.ts.map +1 -0
  162. package/dist/analysis/diff.js +644 -0
  163. package/dist/analysis/diff.js.map +1 -0
  164. package/dist/commands/analyze.d.ts.map +1 -1
  165. package/dist/commands/analyze.js +18 -2
  166. package/dist/commands/analyze.js.map +1 -1
  167. package/dist/commands/diff.d.ts +26 -0
  168. package/dist/commands/diff.d.ts.map +1 -0
  169. package/dist/commands/diff.js +218 -0
  170. package/dist/commands/diff.js.map +1 -0
  171. package/dist/commands/init.d.ts.map +1 -1
  172. package/dist/commands/init.js +72 -9
  173. package/dist/commands/init.js.map +1 -1
  174. package/dist/commands/issue.d.ts.map +1 -1
  175. package/dist/commands/issue.js +4 -4
  176. package/dist/commands/issue.js.map +1 -1
  177. package/dist/commands/note.d.ts.map +1 -1
  178. package/dist/commands/note.js +30 -2
  179. package/dist/commands/note.js.map +1 -1
  180. package/dist/core/config.d.ts +9 -0
  181. package/dist/core/config.d.ts.map +1 -1
  182. package/dist/core/config.js +18 -0
  183. package/dist/core/config.js.map +1 -1
  184. package/dist/core/errors.d.ts +1 -1
  185. package/dist/core/errors.d.ts.map +1 -1
  186. package/dist/core/errors.js +16 -0
  187. package/dist/core/errors.js.map +1 -1
  188. package/dist/core/git.d.ts +24 -0
  189. package/dist/core/git.d.ts.map +1 -0
  190. package/dist/core/git.js +115 -0
  191. package/dist/core/git.js.map +1 -0
  192. package/dist/core/issues.d.ts +4 -2
  193. package/dist/core/issues.d.ts.map +1 -1
  194. package/dist/core/issues.js +67 -28
  195. package/dist/core/issues.js.map +1 -1
  196. package/dist/core/notes.d.ts +25 -1
  197. package/dist/core/notes.d.ts.map +1 -1
  198. package/dist/core/notes.js +34 -2
  199. package/dist/core/notes.js.map +1 -1
  200. package/dist/core/schema.d.ts +750 -53
  201. package/dist/core/schema.d.ts.map +1 -1
  202. package/dist/core/schema.js +153 -1
  203. package/dist/core/schema.js.map +1 -1
  204. package/dist/core/skills.d.ts +10 -4
  205. package/dist/core/skills.d.ts.map +1 -1
  206. package/dist/core/skills.js +100 -37
  207. package/dist/core/skills.js.map +1 -1
  208. package/dist/index.js +2 -0
  209. package/dist/index.js.map +1 -1
  210. package/dist/skills/ai-audit/LICENSE +21 -0
  211. package/dist/skills/ai-audit/SKILL.md +476 -0
  212. package/dist/skills/ai-audit/UPSTREAM.md +46 -0
  213. package/dist/skills/ai-audit/references/agent-prompts.md +133 -0
  214. package/dist/skills/ai-audit/references/assemble.sh +357 -0
  215. package/dist/skills/ai-audit/references/dedup-and-assembly.md +420 -0
  216. package/dist/skills/ai-audit/references/hacking-agents/access-control-agent.md +27 -0
  217. package/dist/skills/ai-audit/references/hacking-agents/asymmetry-agent.md +77 -0
  218. package/dist/skills/ai-audit/references/hacking-agents/boundary-agent.md +79 -0
  219. package/dist/skills/ai-audit/references/hacking-agents/economic-security-agent.md +35 -0
  220. package/dist/skills/ai-audit/references/hacking-agents/execution-trace-agent.md +33 -0
  221. package/dist/skills/ai-audit/references/hacking-agents/first-principles-agent.md +36 -0
  222. package/dist/skills/ai-audit/references/hacking-agents/flow-gap-agent.md +49 -0
  223. package/dist/skills/ai-audit/references/hacking-agents/invariant-agent.md +44 -0
  224. package/dist/skills/ai-audit/references/hacking-agents/math-precision-agent.md +48 -0
  225. package/dist/skills/ai-audit/references/hacking-agents/numerical-gap-agent.md +46 -0
  226. package/dist/skills/ai-audit/references/hacking-agents/periphery-agent.md +27 -0
  227. package/dist/skills/ai-audit/references/hacking-agents/shared-rules.md +61 -0
  228. package/dist/skills/ai-audit/references/hacking-agents/trust-gap-agent.md +40 -0
  229. package/dist/skills/ai-audit/references/hex-board.md +223 -0
  230. package/dist/skills/ai-audit/references/hex-export.sh +71 -0
  231. package/dist/skills/ai-audit/references/judging.md +75 -0
  232. package/dist/skills/ai-audit/references/report-formatting.md +385 -0
  233. package/dist/skills/ai-audit/references/report-language.md +151 -0
  234. package/dist/skills/ai-audit/references/senior-auditor-sop.md +63 -0
  235. package/dist/skills/generate-report.md +9 -3
  236. package/dist/skills/ingest-aa-report.md +11 -2
  237. package/dist/skills/init-audit.md +104 -2
  238. package/dist/skills/validate-all-findings.md +1 -1
  239. package/dist/skills/validate-finding.md +12 -7
  240. package/dist/skills/write-finding.md +8 -6
  241. package/dist/types/index.d.ts +7 -1
  242. package/dist/types/index.d.ts.map +1 -1
  243. package/package.json +2 -1
  244. package/dashboard/.next/server/app/_not-found.html +0 -1
  245. package/dashboard/.next/server/app/_not-found.meta +0 -6
  246. package/dashboard/.next/server/app/_not-found.rsc +0 -12
  247. package/dashboard/.next/server/app/diagram.html +0 -1
  248. package/dashboard/.next/server/app/diagram.meta +0 -5
  249. package/dashboard/.next/server/app/diagram.rsc +0 -10
  250. package/dashboard/.next/server/app/flows.html +0 -1
  251. package/dashboard/.next/server/app/flows.meta +0 -5
  252. package/dashboard/.next/server/app/flows.rsc +0 -10
  253. package/dashboard/.next/server/chunks/44.js +0 -1
  254. package/dashboard/.next/server/pages/404.html +0 -1
  255. package/dashboard/.next/static/ZYqkgvjnS38aMxfanyctA/_buildManifest.js +0 -1
  256. package/dashboard/.next/static/chunks/1015.3ab89142e5f44120.js +0 -226
  257. package/dashboard/.next/static/chunks/1151.b6ef5c786e587ed7.js +0 -1
  258. package/dashboard/.next/static/chunks/1199.a072929dbec89965.js +0 -148
  259. package/dashboard/.next/static/chunks/1375.d4d2f7fc9c9c2ff1.js +0 -43
  260. package/dashboard/.next/static/chunks/1799.83206776abbbf1fc.js +0 -9
  261. package/dashboard/.next/static/chunks/20154aaa.ccc347c04ab5ad4a.js +0 -1
  262. package/dashboard/.next/static/chunks/2077.7011a570c87aa7b1.js +0 -1
  263. package/dashboard/.next/static/chunks/2166.cc0fabeb2e89b840.js +0 -215
  264. package/dashboard/.next/static/chunks/2325.2c55cb9a6282ae3f.js +0 -24
  265. package/dashboard/.next/static/chunks/2694.92bbe252063e4786.js +0 -1
  266. package/dashboard/.next/static/chunks/275.0d761aa0e5b030b8.js +0 -34
  267. package/dashboard/.next/static/chunks/2781.8536b644a480aede.js +0 -93
  268. package/dashboard/.next/static/chunks/2805.a8d71d2f92bb6ba9.js +0 -1
  269. package/dashboard/.next/static/chunks/3017.e55781da9dd32d37.js +0 -1
  270. package/dashboard/.next/static/chunks/3205-728c260fbb4f89c6.js +0 -2
  271. package/dashboard/.next/static/chunks/3236.dff44fa7961d9d5e.js +0 -1
  272. package/dashboard/.next/static/chunks/3480.9451396ad7ee7613.js +0 -1
  273. package/dashboard/.next/static/chunks/3626.ba1cf848a9f2e93d.js +0 -64
  274. package/dashboard/.next/static/chunks/3865.a432a7910a2f5281.js +0 -90
  275. package/dashboard/.next/static/chunks/3887.c22cbfa3f095826c.js +0 -1
  276. package/dashboard/.next/static/chunks/3924-4a05057b5450abe1.js +0 -1
  277. package/dashboard/.next/static/chunks/3948.fe3c7d758568d98b.js +0 -287
  278. package/dashboard/.next/static/chunks/4728.07d87640a3e7dd0d.js +0 -24
  279. package/dashboard/.next/static/chunks/4787.4e5f6a0e0e40a583.js +0 -23
  280. package/dashboard/.next/static/chunks/5060.baca226af35ed016.js +0 -1
  281. package/dashboard/.next/static/chunks/5284.f949ac90c95ff143.js +0 -1
  282. package/dashboard/.next/static/chunks/5715.1524bcc9591e180b.js +0 -115
  283. package/dashboard/.next/static/chunks/6014.700ae4969b64d728.js +0 -104
  284. package/dashboard/.next/static/chunks/6024.4d23707c65514679.js +0 -79
  285. package/dashboard/.next/static/chunks/6177.e5c84cfc4c0dea51.js +0 -1
  286. package/dashboard/.next/static/chunks/618f8807-547c5614e1318888.js +0 -1
  287. package/dashboard/.next/static/chunks/6434.9481771c33195d29.js +0 -1
  288. package/dashboard/.next/static/chunks/6468.f4a3e8fa6accc6da.js +0 -77
  289. package/dashboard/.next/static/chunks/6540.86f367d7390738d4.js +0 -1
  290. package/dashboard/.next/static/chunks/6549.4d0d472df96429a5.js +0 -1
  291. package/dashboard/.next/static/chunks/690f35d0.3e40ca0930e4bbdb.js +0 -119
  292. package/dashboard/.next/static/chunks/7397-f6f4dddc7a20bfc1.js +0 -1
  293. package/dashboard/.next/static/chunks/7498-ea83cb9e30ec5491.js +0 -1
  294. package/dashboard/.next/static/chunks/7802.89aec9ee11680850.js +0 -80
  295. package/dashboard/.next/static/chunks/7973.8b526f589aca5d84.js +0 -79
  296. package/dashboard/.next/static/chunks/8216.1bead812eb126c35.js +0 -5
  297. package/dashboard/.next/static/chunks/8645.a5ca76f11edc9633.js +0 -1
  298. package/dashboard/.next/static/chunks/8928-60c623ee89d2e6ad.js +0 -1
  299. package/dashboard/.next/static/chunks/9173.2486ffca31131ec5.js +0 -1
  300. package/dashboard/.next/static/chunks/9178.469341860bf8caec.js +0 -1
  301. package/dashboard/.next/static/chunks/9466.e904660d38c03eea.js +0 -1
  302. package/dashboard/.next/static/chunks/9660.84a85811380c5f33.js +0 -1
  303. package/dashboard/.next/static/chunks/9720.67d4d0d15a96d691.js +0 -1
  304. package/dashboard/.next/static/chunks/9811.65e1d080c2d256af.js +0 -1
  305. package/dashboard/.next/static/chunks/app/_not-found/page-548ab392d0e890d1.js +0 -1
  306. package/dashboard/.next/static/chunks/app/access/page-3668562e7464eb5d.js +0 -1
  307. package/dashboard/.next/static/chunks/app/calls/page-d07f5b8664cc8303.js +0 -1
  308. package/dashboard/.next/static/chunks/app/conformance/page-2fede1d7b5f9265d.js +0 -1
  309. package/dashboard/.next/static/chunks/app/diagram/page-b228444265546495.js +0 -1
  310. package/dashboard/.next/static/chunks/app/flows/page-fa67783d8cd79cab.js +0 -1
  311. package/dashboard/.next/static/chunks/app/functions/page-686f0296639133a3.js +0 -1
  312. package/dashboard/.next/static/chunks/app/issues/page-98a298e1c1045c91.js +0 -1
  313. package/dashboard/.next/static/chunks/app/layout-49f2496c7637d931.js +0 -1
  314. package/dashboard/.next/static/chunks/app/notes/page-17af94c67ba79c00.js +0 -1
  315. package/dashboard/.next/static/chunks/app/page-24bac51dfe007c66.js +0 -1
  316. package/dashboard/.next/static/chunks/app/progress/page-427fb18da3afb061.js +0 -1
  317. package/dashboard/.next/static/chunks/app/report/page-796f2f4a8a5ac8f7.js +0 -1
  318. package/dashboard/.next/static/chunks/app/stats/page-db81f600a086f252.js +0 -1
  319. package/dashboard/.next/static/chunks/c7ea4e13.5effeeba6618bdb7.js +0 -1
  320. package/dashboard/.next/static/chunks/framework-cf6f5bdca6ba0184.js +0 -33
  321. package/dashboard/.next/static/chunks/main-63ff429eab01f5bf.js +0 -1
  322. package/dashboard/.next/static/chunks/main-app-9d2f6b8a47133e9b.js +0 -1
  323. package/dashboard/.next/static/chunks/pages/_app-6ad2b50514c24ab4.js +0 -1
  324. package/dashboard/.next/static/chunks/pages/_error-d5eb11c5c4626811.js +0 -1
  325. package/dashboard/.next/static/chunks/webpack-08869f2b18792e51.js +0 -1
  326. package/dashboard/.next/static/css/4a38d8f6f6b7a68f.css +0 -3
  327. package/dashboard/.next/static/media/438aa629764e75f3-s.woff2 +0 -0
  328. package/dashboard/.next/static/media/4c9affa5bc8f420e-s.p.woff2 +0 -0
  329. package/dashboard/.next/static/media/51251f8b9793cdb3-s.woff2 +0 -0
  330. package/dashboard/.next/static/media/875ae681bfde4580-s.woff2 +0 -0
  331. package/dashboard/.next/static/media/cc978ac5ee68c2b6-s.woff2 +0 -0
  332. package/dashboard/.next/static/media/e857b654a2caa584-s.woff2 +0 -0
  333. /package/dashboard/.next/static/{ZYqkgvjnS38aMxfanyctA → z5XBev05xDAkDrxWxAjNu}/_ssgManifest.js +0 -0
@@ -0,0 +1,464 @@
1
+ 'use client';
2
+
3
+ import Link from 'next/link';
4
+ import { FilterableTable, type FilterableColumn } from '@/components/FilterableTable';
5
+ import { ConfidenceBadge } from '@/components/ConfidenceBadge';
6
+ import { CodeReference } from '@/components/CodeReference';
7
+ import { MarkdownRenderer, InlineMarkdown } from '@/components/MarkdownRenderer';
8
+ import { SeverityBadge } from '@/components/SeverityBadge';
9
+
10
+ // ─── Types (shape of .hex/diff.json, see src/core/schema.ts DiffSchema) ──
11
+
12
+ interface DiffChange {
13
+ contract: string;
14
+ entity: string;
15
+ kind: string;
16
+ file: string;
17
+ change: 'added' | 'removed' | 'modified' | 'comments_only';
18
+ line_start?: number;
19
+ line_end?: number;
20
+ }
21
+
22
+ interface ImpactReason {
23
+ kind: 'changed' | 'calls' | 'modifier' | 'reads_state' | 'override' | 'inherits';
24
+ via: string;
25
+ }
26
+
27
+ interface Impacted {
28
+ contract: string;
29
+ function: string;
30
+ file: string;
31
+ visibility: string;
32
+ is_entry_point: boolean;
33
+ depth: number;
34
+ reasons: ImpactReason[];
35
+ confidence: string;
36
+ derived_from: string;
37
+ line_start?: number;
38
+ }
39
+
40
+ export interface DiffData {
41
+ generated_at: string;
42
+ base_commit: string;
43
+ head_commit: string;
44
+ warnings?: string[];
45
+ files: Array<{
46
+ path: string;
47
+ status: string;
48
+ old_path?: string;
49
+ additions: number;
50
+ deletions: number;
51
+ }>;
52
+ changes: DiffChange[];
53
+ storage_layout_changes: Array<{ contract: string; file: string; kind: string; detail: string }>;
54
+ impacted: Impacted[];
55
+ summary: {
56
+ files_changed: number;
57
+ additions: number;
58
+ deletions: number;
59
+ functions_added: number;
60
+ functions_modified: number;
61
+ functions_removed: number;
62
+ impacted_functions: number;
63
+ impacted_entry_points: number;
64
+ storage_layout_changes: number;
65
+ };
66
+ }
67
+
68
+ type Severity = 'Critical' | 'High' | 'Medium' | 'Low' | 'Info';
69
+
70
+ export interface PriorReview {
71
+ reviewed_at: string;
72
+ items: Array<{
73
+ id: string;
74
+ title: string;
75
+ severity: Severity;
76
+ status: string;
77
+ reasoning: string;
78
+ issue_id?: string;
79
+ }>;
80
+ }
81
+
82
+ // ─── Small pieces ───────────────────────────────────────────────────
83
+
84
+ const CHANGE_STYLES: Record<string, string> = {
85
+ added: 'bg-accent-subtle text-accent',
86
+ modified: 'bg-[var(--high)]/18 text-[var(--high)]',
87
+ removed: 'bg-[var(--critical)]/18 text-[var(--critical)]',
88
+ comments_only: 'bg-surface-3 text-text-tertiary',
89
+ };
90
+
91
+ const CHANGE_LABELS: Record<string, string> = {
92
+ added: 'Added',
93
+ modified: 'Modified',
94
+ removed: 'Removed',
95
+ comments_only: 'Comments only',
96
+ };
97
+
98
+ function Chip({ className, children }: { className: string; children: React.ReactNode }) {
99
+ return (
100
+ <span
101
+ className={`inline-flex items-center rounded-md px-2 py-0.5 text-caption font-medium ${className}`}
102
+ >
103
+ {children}
104
+ </span>
105
+ );
106
+ }
107
+
108
+ function ChangeBadge({ change }: { change: string }) {
109
+ return (
110
+ <Chip className={CHANGE_STYLES[change] ?? CHANGE_STYLES.comments_only}>
111
+ {CHANGE_LABELS[change] ?? change}
112
+ </Chip>
113
+ );
114
+ }
115
+
116
+ const REASON_LABELS: Record<ImpactReason['kind'], string> = {
117
+ changed: 'Changed',
118
+ calls: 'Calls',
119
+ modifier: 'Uses modifier',
120
+ reads_state: 'Reads state',
121
+ override: 'Dispatches to',
122
+ inherits: 'Inherits',
123
+ };
124
+
125
+ const PRIOR_STATUS: Record<string, { label: string; className: string }> = {
126
+ regressed: { label: 'Regressed', className: 'bg-[var(--critical)]/18 text-[var(--critical)]' },
127
+ acknowledged_still_present: {
128
+ label: 'Still present',
129
+ className: 'bg-[var(--medium)]/18 text-[var(--medium)]',
130
+ },
131
+ fix_touched_ok: { label: 'Fix touched, holds', className: 'bg-accent-subtle text-accent' },
132
+ fixed_unchanged: { label: 'Fixed, untouched', className: 'bg-surface-3 text-text-secondary' },
133
+ code_removed: { label: 'Code removed', className: 'bg-surface-3 text-text-tertiary' },
134
+ };
135
+
136
+ function Stat({ label, value, tone }: { label: string; value: number | string; tone?: 'warn' }) {
137
+ return (
138
+ <div
139
+ className={`rounded-lg border p-4 ${
140
+ tone === 'warn'
141
+ ? 'border-[var(--high)]/30 bg-[var(--high)]/5'
142
+ : 'border-border-subtle bg-surface-1'
143
+ }`}
144
+ >
145
+ <div
146
+ className={`text-display scale-in ${tone === 'warn' ? 'text-[var(--high)]' : 'text-text-primary'}`}
147
+ >
148
+ {value}
149
+ </div>
150
+ <div className="mt-1 text-caption text-text-secondary">{label}</div>
151
+ </div>
152
+ );
153
+ }
154
+
155
+ function Section({ title, children }: { title: string; children: React.ReactNode }) {
156
+ return (
157
+ <section className="mb-sp-6">
158
+ <h3 className="mb-sp-3 text-heading font-medium text-text-primary">{title}</h3>
159
+ {children}
160
+ </section>
161
+ );
162
+ }
163
+
164
+ // ─── Columns ────────────────────────────────────────────────────────
165
+
166
+ const changeColumns: FilterableColumn<DiffChange>[] = [
167
+ {
168
+ id: 'contract',
169
+ header: 'Contract',
170
+ accessorKey: 'contract',
171
+ enableColumnFilter: true,
172
+ cell: (row) => <span className="font-medium text-text-primary">{row.contract}</span>,
173
+ },
174
+ {
175
+ id: 'entity',
176
+ header: 'Entity',
177
+ accessorKey: 'entity',
178
+ cell: (row) => <code className="font-mono text-body text-text-secondary">{row.entity}</code>,
179
+ },
180
+ {
181
+ id: 'kind',
182
+ header: 'Kind',
183
+ accessorKey: 'kind',
184
+ enableColumnFilter: true,
185
+ cell: (row) => (
186
+ <span className="text-body text-text-secondary">{row.kind.replace('_', ' ')}</span>
187
+ ),
188
+ },
189
+ {
190
+ id: 'change',
191
+ header: 'Change',
192
+ accessorKey: 'change',
193
+ enableColumnFilter: true,
194
+ filterOrder: ['added', 'modified', 'removed', 'comments_only'],
195
+ cell: (row) => <ChangeBadge change={row.change} />,
196
+ },
197
+ {
198
+ id: 'location',
199
+ header: 'Location',
200
+ accessorKey: 'file',
201
+ cell: (row) =>
202
+ row.change === 'removed' || !row.line_start ? (
203
+ <code className="font-mono text-caption text-text-tertiary">{row.file}</code>
204
+ ) : (
205
+ <CodeReference file={row.file} lineStart={row.line_start} lineEnd={row.line_end} />
206
+ ),
207
+ },
208
+ ];
209
+
210
+ interface ImpactRow extends Impacted {
211
+ entry: string;
212
+ reason: string;
213
+ }
214
+
215
+ const impactColumns: FilterableColumn<ImpactRow>[] = [
216
+ {
217
+ id: 'contract',
218
+ header: 'Contract',
219
+ accessorKey: 'contract',
220
+ enableColumnFilter: true,
221
+ cell: (row) => <span className="font-medium text-text-primary">{row.contract}</span>,
222
+ },
223
+ {
224
+ id: 'function',
225
+ header: 'Function',
226
+ accessorKey: 'function',
227
+ cell: (row) => <code className="font-mono text-body text-text-secondary">{row.function}</code>,
228
+ },
229
+ {
230
+ id: 'entry',
231
+ header: 'Entry point',
232
+ accessorKey: 'entry',
233
+ enableColumnFilter: true,
234
+ cell: (row) =>
235
+ row.is_entry_point ? (
236
+ <Chip className="bg-accent-subtle text-accent">Entry point</Chip>
237
+ ) : (
238
+ <span className="text-caption text-text-tertiary">{row.visibility}</span>
239
+ ),
240
+ },
241
+ {
242
+ id: 'depth',
243
+ header: 'Depth',
244
+ accessorKey: 'depth',
245
+ cell: (row) => (
246
+ <span className="text-body text-text-secondary">
247
+ {row.depth === 0 ? 'changed' : row.depth}
248
+ </span>
249
+ ),
250
+ },
251
+ {
252
+ id: 'reason',
253
+ header: 'Why',
254
+ accessorKey: 'reason',
255
+ enableColumnFilter: true,
256
+ cell: (row) => (
257
+ <div className="space-y-0.5">
258
+ {row.reasons.slice(0, 2).map((r, i) => (
259
+ <div key={i} className="text-caption text-text-secondary">
260
+ {REASON_LABELS[r.kind] ?? r.kind}{' '}
261
+ {r.kind !== 'changed' && <code className="font-mono text-text-primary">{r.via}</code>}
262
+ {r.kind === 'changed' && <span className="text-text-tertiary">({r.via})</span>}
263
+ </div>
264
+ ))}
265
+ {row.reasons.length > 2 && (
266
+ <div className="text-caption text-text-tertiary">+{row.reasons.length - 2} more</div>
267
+ )}
268
+ </div>
269
+ ),
270
+ },
271
+ {
272
+ id: 'confidence',
273
+ header: 'Confidence',
274
+ accessorKey: 'confidence',
275
+ enableColumnFilter: true,
276
+ filterOrder: ['high', 'medium', 'low'],
277
+ cell: (row) => <ConfidenceBadge level={row.confidence} derivedFrom={row.derived_from} />,
278
+ },
279
+ {
280
+ id: 'location',
281
+ header: 'Location',
282
+ accessorKey: 'file',
283
+ cell: (row) =>
284
+ row.line_start ? (
285
+ <CodeReference file={row.file} lineStart={row.line_start} />
286
+ ) : (
287
+ <code className="font-mono text-caption text-text-tertiary">{row.file}</code>
288
+ ),
289
+ },
290
+ ];
291
+
292
+ // ─── Component ──────────────────────────────────────────────────────
293
+
294
+ export function ChangesClient({
295
+ diff,
296
+ overview,
297
+ review,
298
+ }: {
299
+ diff: DiffData;
300
+ overview: string | null;
301
+ review: PriorReview | null;
302
+ }) {
303
+ const s = diff.summary;
304
+ const base = diff.base_commit.slice(0, 8);
305
+ const head = diff.head_commit.slice(0, 8);
306
+
307
+ const impactRows: ImpactRow[] = diff.impacted.map((i) => ({
308
+ ...i,
309
+ entry: i.is_entry_point ? 'Entry point' : 'Internal',
310
+ reason: REASON_LABELS[i.reasons[0]?.kind] ?? '',
311
+ }));
312
+ const regressed = review?.items.filter((i) => i.status === 'regressed').length ?? 0;
313
+
314
+ return (
315
+ <div>
316
+ <h2 className="mb-sp-2 text-title font-semibold text-text-primary">Changes</h2>
317
+ <div className="mb-sp-5 flex flex-wrap items-center gap-2 text-caption text-text-tertiary">
318
+ <span>Differential audit</span>
319
+ <code className="rounded-md bg-surface-2 px-2 py-0.5 font-mono text-text-secondary">
320
+ {base}
321
+ </code>
322
+ <span aria-hidden="true">→</span>
323
+ <code className="rounded-md bg-surface-2 px-2 py-0.5 font-mono text-text-secondary">
324
+ {head}
325
+ </code>
326
+ <span>
327
+ · +{s.additions} / −{s.deletions} lines
328
+ </span>
329
+ </div>
330
+
331
+ {(diff.warnings ?? []).map((w, i) => (
332
+ <div
333
+ key={i}
334
+ className="mb-sp-3 rounded-lg border border-[var(--high)]/30 bg-[var(--high)]/5 px-4 py-3 text-body text-text-secondary"
335
+ >
336
+ {w}
337
+ </div>
338
+ ))}
339
+
340
+ <div className="mb-sp-6 grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6 stagger">
341
+ <Stat label="Files changed" value={s.files_changed} />
342
+ <Stat label="Functions added" value={s.functions_added} />
343
+ <Stat label="Functions modified" value={s.functions_modified} />
344
+ <Stat label="Functions removed" value={s.functions_removed} />
345
+ <Stat label="Impacted entry points" value={s.impacted_entry_points} />
346
+ <Stat
347
+ label="Storage layout changes"
348
+ value={s.storage_layout_changes}
349
+ tone={s.storage_layout_changes > 0 ? 'warn' : undefined}
350
+ />
351
+ {review && (
352
+ <Stat
353
+ label="Prior findings regressed"
354
+ value={regressed}
355
+ tone={regressed > 0 ? 'warn' : undefined}
356
+ />
357
+ )}
358
+ </div>
359
+
360
+ {overview && (
361
+ <Section title="What changed">
362
+ <div className="rounded-lg border border-border-subtle bg-surface-1 p-6">
363
+ <MarkdownRenderer content={overview} />
364
+ </div>
365
+ </Section>
366
+ )}
367
+
368
+ {diff.storage_layout_changes.length > 0 && (
369
+ <Section title="Storage layout">
370
+ <ul className="divide-y divide-border-subtle rounded-lg border border-border-subtle bg-surface-1">
371
+ {diff.storage_layout_changes.map((l, i) => (
372
+ <li key={i} className="flex flex-wrap items-baseline gap-x-3 gap-y-1 px-4 py-3">
373
+ <span className="font-medium text-text-primary">{l.contract}</span>
374
+ <Chip className="bg-[var(--high)]/18 text-[var(--high)]">
375
+ {l.kind.replace(/_/g, ' ')}
376
+ </Chip>
377
+ <span className="text-body text-text-secondary">
378
+ <InlineMarkdown>{l.detail}</InlineMarkdown>
379
+ </span>
380
+ </li>
381
+ ))}
382
+ </ul>
383
+ </Section>
384
+ )}
385
+
386
+ <Section title="Changed code">
387
+ <p className="mb-sp-3 text-body text-text-secondary">
388
+ {diff.files.length} file{diff.files.length !== 1 ? 's' : ''}:{' '}
389
+ {diff.files.map((f, i) => (
390
+ <span key={f.path}>
391
+ {i > 0 && ', '}
392
+ <code className="font-mono text-caption text-text-primary">{f.path}</code>{' '}
393
+ <span className="text-caption text-text-tertiary">
394
+ ({f.status}
395
+ {f.old_path ? ` from ${f.old_path}` : ''}, +{f.additions}/−{f.deletions})
396
+ </span>
397
+ </span>
398
+ ))}
399
+ </p>
400
+ <FilterableTable columns={changeColumns} data={diff.changes} />
401
+ </Section>
402
+
403
+ <Section title="Impacted flows">
404
+ <p className="mb-sp-3 text-body text-text-secondary">
405
+ Every function the change reaches: changed code (depth 0), then callers, modifier users,
406
+ readers of state the change writes, and inherited entry points. {s.impacted_functions}{' '}
407
+ impacted beyond the changed code.
408
+ </p>
409
+ <FilterableTable columns={impactColumns} data={impactRows} />
410
+ </Section>
411
+
412
+ {review && review.items.length > 0 && (
413
+ <Section title="Prior findings">
414
+ <div className="overflow-x-auto rounded-lg border border-border-subtle bg-surface-1">
415
+ <table className="w-full text-left">
416
+ <thead>
417
+ <tr className="border-b border-border-subtle text-caption text-text-tertiary">
418
+ <th className="px-4 py-2 font-normal">ID</th>
419
+ <th className="px-4 py-2 font-normal">Title</th>
420
+ <th className="px-4 py-2 font-normal">Severity</th>
421
+ <th className="px-4 py-2 font-normal">Status</th>
422
+ <th className="px-4 py-2 font-normal">Card</th>
423
+ </tr>
424
+ </thead>
425
+ <tbody>
426
+ {review.items.map((item) => {
427
+ const st = PRIOR_STATUS[item.status] ?? {
428
+ label: item.status,
429
+ className: 'bg-surface-3 text-text-secondary',
430
+ };
431
+ return (
432
+ <tr
433
+ key={item.id}
434
+ className="border-b border-border-subtle last:border-0 hover:bg-surface-3"
435
+ title={item.reasoning}
436
+ >
437
+ <td className="px-4 py-2 text-body text-text-secondary">{item.id}</td>
438
+ <td className="px-4 py-2 text-body text-text-primary">{item.title}</td>
439
+ <td className="px-4 py-2">
440
+ <SeverityBadge severity={item.severity} />
441
+ </td>
442
+ <td className="px-4 py-2">
443
+ <Chip className={st.className}>{st.label}</Chip>
444
+ </td>
445
+ <td className="px-4 py-2 text-body">
446
+ {item.issue_id ? (
447
+ <Link href="/issues" className="text-accent hover:underline">
448
+ {item.issue_id}
449
+ </Link>
450
+ ) : (
451
+ <span className="text-text-tertiary">—</span>
452
+ )}
453
+ </td>
454
+ </tr>
455
+ );
456
+ })}
457
+ </tbody>
458
+ </table>
459
+ </div>
460
+ </Section>
461
+ )}
462
+ </div>
463
+ );
464
+ }
@@ -0,0 +1,36 @@
1
+ import { readJsonFile, readMarkdownFile } from '@/lib/data';
2
+ import { NotYetGenerated } from '@/components/NotYetGenerated';
3
+ import { ChangesClient, type DiffData, type PriorReview } from './ChangesClient';
4
+
5
+ // Read .hex/ at request time (see app/calls/page.tsx for why).
6
+ export const dynamic = 'force-dynamic';
7
+
8
+ interface ConfigFile {
9
+ project?: { mode?: string; diff?: { base_commit?: string } };
10
+ }
11
+
12
+ export default function ChangesPage() {
13
+ const diff = readJsonFile<DiffData>('diff.json');
14
+ const config = readJsonFile<ConfigFile>('config.json');
15
+
16
+ if (!diff) {
17
+ const base = config?.project?.diff?.base_commit;
18
+ return (
19
+ <div>
20
+ <h2 className="mb-sp-5 text-title font-semibold text-text-primary">Changes</h2>
21
+ <p className="mb-sp-4 text-body text-text-secondary">
22
+ This page is for differential audits: what changed since the previously audited commit,
23
+ and which flows the change reaches.
24
+ </p>
25
+ <NotYetGenerated
26
+ command={base ? 'hex diff' : 'hex init --mode diff --base <commit> --scope "<globs>"'}
27
+ />
28
+ </div>
29
+ );
30
+ }
31
+
32
+ const overview = readMarkdownFile('diff-overview.md');
33
+ const review = readJsonFile<PriorReview>('previous-audit/review.json');
34
+
35
+ return <ChangesClient diff={diff} overview={overview} review={review} />;
36
+ }
@@ -23,7 +23,13 @@ export type IssueStatus =
23
23
  | 'synced'
24
24
  | 'rejected'
25
25
  | 'duplicate';
26
- export type IssueSource = 'manual' | 'auditagent' | 'conformance' | 'github';
26
+ export type IssueSource =
27
+ | 'manual'
28
+ | 'auditagent'
29
+ | 'ai-audit'
30
+ | 'conformance'
31
+ | 'github'
32
+ | 'prior-audit';
27
33
  export type PocStatus = 'passing' | 'failing' | 'not_started';
28
34
 
29
35
  export interface BoardIssue {
@@ -263,9 +269,11 @@ function SourceFilter({
263
269
  const options: Array<{ id: IssueSource | 'all'; label: string }> = [
264
270
  { id: 'all', label: 'All sources' },
265
271
  { id: 'manual', label: 'Manual' },
272
+ { id: 'ai-audit', label: 'AI audit' },
266
273
  { id: 'auditagent', label: 'AuditAgent' },
267
274
  { id: 'conformance', label: 'Conformance' },
268
275
  { id: 'github', label: 'GitHub' },
276
+ { id: 'prior-audit', label: 'Prior audit' },
269
277
  ];
270
278
  return (
271
279
  <div className="flex flex-wrap gap-1.5">
@@ -437,8 +445,10 @@ function SourceChip({ source }: { source: IssueSource }) {
437
445
  const labels: Record<IssueSource, string> = {
438
446
  manual: 'Manual',
439
447
  auditagent: 'AuditAgent',
448
+ 'ai-audit': 'AI audit',
440
449
  conformance: 'Conformance',
441
450
  github: 'GitHub',
451
+ 'prior-audit': 'Prior audit',
442
452
  };
443
453
  return (
444
454
  <span className="rounded-md bg-surface-2 px-1.5 py-0.5 text-text-tertiary">
@@ -4,6 +4,7 @@ import { ThemeProvider } from 'next-themes';
4
4
  import { DashboardLayout } from '@/components/DashboardLayout';
5
5
  import { CommandPalette } from '@/components/CommandPalette';
6
6
  import pkg from '../../package.json';
7
+ import { readJsonFile } from '@/lib/data';
7
8
  import './globals.css';
8
9
 
9
10
  const manrope = Manrope({
@@ -23,6 +24,15 @@ export const metadata: Metadata = {
23
24
  description: 'Local dashboard for Solidity smart contract audits',
24
25
  };
25
26
 
27
+ // The sidebar depends on .hex/config.json (diff mode shows Changes), so every
28
+ // route renders at request time — including /diagram and /flows, which would
29
+ // otherwise be prerendered with whatever config existed at build time.
30
+ export const dynamic = 'force-dynamic';
31
+
32
+ function isDiffAudit(): boolean {
33
+ return readJsonFile<{ project?: { mode?: string } }>('config.json')?.project?.mode === 'diff';
34
+ }
35
+
26
36
  export default function RootLayout({
27
37
  children,
28
38
  }: {
@@ -33,7 +43,9 @@ export default function RootLayout({
33
43
  <body className={`${manrope.variable} ${jetbrainsMono.variable} min-h-screen bg-surface-0 text-text-primary font-sans`}>
34
44
  <ThemeProvider attribute="data-theme" defaultTheme="dark" enableSystem={false}>
35
45
  <CommandPalette />
36
- <DashboardLayout version={pkg.version}>{children}</DashboardLayout>
46
+ <DashboardLayout version={pkg.version} diffMode={isDiffAudit()}>
47
+ {children}
48
+ </DashboardLayout>
37
49
  </ThemeProvider>
38
50
  </body>
39
51
  </html>
@@ -381,6 +381,11 @@ function LeadsSection({
381
381
  className="flex items-start justify-between gap-3 rounded-md border border-border-subtle bg-surface-2 px-3 py-2"
382
382
  >
383
383
  <span className="min-w-0 flex-1 text-body text-text-primary">
384
+ {lead.source === 'ai-audit' && (
385
+ <span className="mr-2 rounded-md bg-surface-3 px-1.5 py-0.5 text-caption text-text-tertiary">
386
+ AI audit
387
+ </span>
388
+ )}
384
389
  <InlineMarkdown>{lead.text}</InlineMarkdown>
385
390
  </span>
386
391
  <button
@@ -17,9 +17,17 @@ interface ProjectConfig {
17
17
  chain: string;
18
18
  solidity_version: string;
19
19
  scope: string[];
20
+ mode?: 'full' | 'diff';
21
+ diff?: { base_commit: string };
20
22
  };
21
23
  }
22
24
 
25
+ interface DiffSummary {
26
+ base_commit: string;
27
+ head_commit: string;
28
+ summary: { files_changed: number; impacted_entry_points: number; storage_layout_changes: number };
29
+ }
30
+
23
31
  interface Stats {
24
32
  totals: {
25
33
  files: number;
@@ -158,6 +166,7 @@ export default function HomePage() {
158
166
  const config = readJsonFile<ProjectConfig>('config.json');
159
167
  const overview = readMarkdownFile('overview.md');
160
168
  const stats = readJsonFile<Stats>('stats.json');
169
+ const diff = config?.project.mode === 'diff' ? readJsonFile<DiffSummary>('diff.json') : null;
161
170
  const findingsData = readJsonFile<FindingsData>('findings.json');
162
171
  const externalCallsData = readJsonFile<ExternalCallsData>('external-calls.json');
163
172
 
@@ -191,6 +200,39 @@ export default function HomePage() {
191
200
  </span>
192
201
  </div>
193
202
  )}
203
+ {config?.project.mode === 'diff' && (
204
+ <Link
205
+ href="/changes"
206
+ className="mt-3 flex flex-wrap items-center gap-2 rounded-lg border border-border-subtle bg-surface-1 px-4 py-3 text-body text-text-secondary hover:border-border-default hover:bg-surface-2"
207
+ >
208
+ <span className="rounded-md bg-accent-subtle px-2.5 py-1 text-caption font-medium text-accent">
209
+ Differential
210
+ </span>
211
+ <code className="font-mono text-caption text-text-primary">
212
+ {(diff?.base_commit ?? config.project.diff?.base_commit ?? '').slice(0, 8)}
213
+ </code>
214
+ <span aria-hidden="true">→</span>
215
+ <code className="font-mono text-caption text-text-primary">
216
+ {(diff?.head_commit ?? config.project.commit).slice(0, 8)}
217
+ </code>
218
+ {diff ? (
219
+ <span>
220
+ · {diff.summary.files_changed} file{diff.summary.files_changed !== 1 ? 's' : ''} changed ·{' '}
221
+ {diff.summary.impacted_entry_points} impacted entry point
222
+ {diff.summary.impacted_entry_points !== 1 ? 's' : ''}
223
+ {diff.summary.storage_layout_changes > 0 && (
224
+ <span className="text-[var(--high)]">
225
+ {' '}
226
+ · {diff.summary.storage_layout_changes} storage layout change
227
+ {diff.summary.storage_layout_changes !== 1 ? 's' : ''}
228
+ </span>
229
+ )}
230
+ </span>
231
+ ) : (
232
+ <span>· run hex diff to compute the change set</span>
233
+ )}
234
+ </Link>
235
+ )}
194
236
  </div>
195
237
 
196
238
  {/* KPI cards */}