hex-audit 0.4.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 (486) hide show
  1. package/CLAUDE.md +105 -0
  2. package/DEMO.md +141 -0
  3. package/README.md +378 -0
  4. package/dashboard/.next/BUILD_ID +1 -0
  5. package/dashboard/.next/app-build-manifest.json +99 -0
  6. package/dashboard/.next/app-path-routes-manifest.json +1 -0
  7. package/dashboard/.next/build-manifest.json +32 -0
  8. package/dashboard/.next/cache/.tsbuildinfo +1 -0
  9. package/dashboard/.next/cache/webpack/client-production/0.pack +0 -0
  10. package/dashboard/.next/cache/webpack/client-production/index.pack +0 -0
  11. package/dashboard/.next/cache/webpack/edge-server-production/0.pack +0 -0
  12. package/dashboard/.next/cache/webpack/edge-server-production/index.pack +0 -0
  13. package/dashboard/.next/cache/webpack/server-production/0.pack +0 -0
  14. package/dashboard/.next/cache/webpack/server-production/1.pack +0 -0
  15. package/dashboard/.next/cache/webpack/server-production/2.pack +0 -0
  16. package/dashboard/.next/cache/webpack/server-production/index.pack +0 -0
  17. package/dashboard/.next/cache/webpack/server-production/index.pack.old +0 -0
  18. package/dashboard/.next/export-marker.json +1 -0
  19. package/dashboard/.next/images-manifest.json +1 -0
  20. package/dashboard/.next/next-minimal-server.js.nft.json +1 -0
  21. package/dashboard/.next/next-server.js.nft.json +1 -0
  22. package/dashboard/.next/package.json +1 -0
  23. package/dashboard/.next/prerender-manifest.js +1 -0
  24. package/dashboard/.next/prerender-manifest.json +1 -0
  25. package/dashboard/.next/react-loadable-manifest.json +300 -0
  26. package/dashboard/.next/required-server-files.json +1 -0
  27. package/dashboard/.next/routes-manifest.json +1 -0
  28. package/dashboard/.next/server/app/_not-found/page.js +1 -0
  29. package/dashboard/.next/server/app/_not-found/page.js.nft.json +1 -0
  30. package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  31. package/dashboard/.next/server/app/_not-found.html +1 -0
  32. package/dashboard/.next/server/app/_not-found.meta +6 -0
  33. package/dashboard/.next/server/app/_not-found.rsc +12 -0
  34. package/dashboard/.next/server/app/access/page.js +1 -0
  35. package/dashboard/.next/server/app/access/page.js.nft.json +1 -0
  36. package/dashboard/.next/server/app/access/page_client-reference-manifest.js +1 -0
  37. package/dashboard/.next/server/app/access.html +1 -0
  38. package/dashboard/.next/server/app/access.meta +5 -0
  39. package/dashboard/.next/server/app/access.rsc +8 -0
  40. package/dashboard/.next/server/app/api/code/route.js +1 -0
  41. package/dashboard/.next/server/app/api/code/route.js.nft.json +1 -0
  42. package/dashboard/.next/server/app/api/flows/route.js +1 -0
  43. package/dashboard/.next/server/app/api/flows/route.js.nft.json +1 -0
  44. package/dashboard/.next/server/app/api/flows.body +1 -0
  45. package/dashboard/.next/server/app/api/flows.meta +1 -0
  46. package/dashboard/.next/server/app/api/github-status/route.js +1 -0
  47. package/dashboard/.next/server/app/api/github-status/route.js.nft.json +1 -0
  48. package/dashboard/.next/server/app/api/issues/[id]/move/route.js +1 -0
  49. package/dashboard/.next/server/app/api/issues/[id]/move/route.js.nft.json +1 -0
  50. package/dashboard/.next/server/app/api/issues/[id]/route.js +1 -0
  51. package/dashboard/.next/server/app/api/issues/[id]/route.js.nft.json +1 -0
  52. package/dashboard/.next/server/app/api/mermaid/route.js +1 -0
  53. package/dashboard/.next/server/app/api/mermaid/route.js.nft.json +1 -0
  54. package/dashboard/.next/server/app/api/progress/route.js +1 -0
  55. package/dashboard/.next/server/app/api/progress/route.js.nft.json +1 -0
  56. package/dashboard/.next/server/app/api/watch/route.js +3 -0
  57. package/dashboard/.next/server/app/api/watch/route.js.nft.json +1 -0
  58. package/dashboard/.next/server/app/calls/page.js +1 -0
  59. package/dashboard/.next/server/app/calls/page.js.nft.json +1 -0
  60. package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +1 -0
  61. package/dashboard/.next/server/app/calls.html +1 -0
  62. package/dashboard/.next/server/app/calls.meta +5 -0
  63. package/dashboard/.next/server/app/calls.rsc +8 -0
  64. package/dashboard/.next/server/app/conformance/page.js +1 -0
  65. package/dashboard/.next/server/app/conformance/page.js.nft.json +1 -0
  66. package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +1 -0
  67. package/dashboard/.next/server/app/conformance.html +1 -0
  68. package/dashboard/.next/server/app/conformance.meta +5 -0
  69. package/dashboard/.next/server/app/conformance.rsc +8 -0
  70. package/dashboard/.next/server/app/diagram/page.js +1 -0
  71. package/dashboard/.next/server/app/diagram/page.js.nft.json +1 -0
  72. package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +1 -0
  73. package/dashboard/.next/server/app/diagram.html +1 -0
  74. package/dashboard/.next/server/app/diagram.meta +5 -0
  75. package/dashboard/.next/server/app/diagram.rsc +10 -0
  76. package/dashboard/.next/server/app/flows/page.js +1 -0
  77. package/dashboard/.next/server/app/flows/page.js.nft.json +1 -0
  78. package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +1 -0
  79. package/dashboard/.next/server/app/flows.html +1 -0
  80. package/dashboard/.next/server/app/flows.meta +5 -0
  81. package/dashboard/.next/server/app/flows.rsc +10 -0
  82. package/dashboard/.next/server/app/functions/page.js +1 -0
  83. package/dashboard/.next/server/app/functions/page.js.nft.json +1 -0
  84. package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +1 -0
  85. package/dashboard/.next/server/app/functions.html +1 -0
  86. package/dashboard/.next/server/app/functions.meta +5 -0
  87. package/dashboard/.next/server/app/functions.rsc +8 -0
  88. package/dashboard/.next/server/app/icon.svg/route.js +12 -0
  89. package/dashboard/.next/server/app/icon.svg/route.js.nft.json +1 -0
  90. package/dashboard/.next/server/app/icon.svg.body +18 -0
  91. package/dashboard/.next/server/app/icon.svg.meta +1 -0
  92. package/dashboard/.next/server/app/index.html +1 -0
  93. package/dashboard/.next/server/app/index.meta +5 -0
  94. package/dashboard/.next/server/app/index.rsc +9 -0
  95. package/dashboard/.next/server/app/issues/page.js +1 -0
  96. package/dashboard/.next/server/app/issues/page.js.nft.json +1 -0
  97. package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -0
  98. package/dashboard/.next/server/app/issues.html +1 -0
  99. package/dashboard/.next/server/app/issues.meta +5 -0
  100. package/dashboard/.next/server/app/issues.rsc +8 -0
  101. package/dashboard/.next/server/app/page.js +20 -0
  102. package/dashboard/.next/server/app/page.js.nft.json +1 -0
  103. package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -0
  104. package/dashboard/.next/server/app/progress/page.js +1 -0
  105. package/dashboard/.next/server/app/progress/page.js.nft.json +1 -0
  106. package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +1 -0
  107. package/dashboard/.next/server/app/progress.html +1 -0
  108. package/dashboard/.next/server/app/progress.meta +5 -0
  109. package/dashboard/.next/server/app/progress.rsc +8 -0
  110. package/dashboard/.next/server/app/stats/page.js +1 -0
  111. package/dashboard/.next/server/app/stats/page.js.nft.json +1 -0
  112. package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +1 -0
  113. package/dashboard/.next/server/app/stats.html +1 -0
  114. package/dashboard/.next/server/app/stats.meta +5 -0
  115. package/dashboard/.next/server/app/stats.rsc +8 -0
  116. package/dashboard/.next/server/app-paths-manifest.json +22 -0
  117. package/dashboard/.next/server/chunks/431.js +1 -0
  118. package/dashboard/.next/server/chunks/557.js +1 -0
  119. package/dashboard/.next/server/chunks/645.js +6 -0
  120. package/dashboard/.next/server/chunks/649.js +2 -0
  121. package/dashboard/.next/server/chunks/665.js +13 -0
  122. package/dashboard/.next/server/chunks/786.js +12 -0
  123. package/dashboard/.next/server/chunks/818.js +6 -0
  124. package/dashboard/.next/server/chunks/916.js +2 -0
  125. package/dashboard/.next/server/chunks/font-manifest.json +1 -0
  126. package/dashboard/.next/server/font-manifest.json +1 -0
  127. package/dashboard/.next/server/functions-config-manifest.json +1 -0
  128. package/dashboard/.next/server/interception-route-rewrite-manifest.js +1 -0
  129. package/dashboard/.next/server/middleware-build-manifest.js +1 -0
  130. package/dashboard/.next/server/middleware-manifest.json +6 -0
  131. package/dashboard/.next/server/middleware-react-loadable-manifest.js +1 -0
  132. package/dashboard/.next/server/next-font-manifest.js +1 -0
  133. package/dashboard/.next/server/next-font-manifest.json +1 -0
  134. package/dashboard/.next/server/pages/404.html +1 -0
  135. package/dashboard/.next/server/pages/500.html +1 -0
  136. package/dashboard/.next/server/pages/_app.js +1 -0
  137. package/dashboard/.next/server/pages/_app.js.nft.json +1 -0
  138. package/dashboard/.next/server/pages/_document.js +1 -0
  139. package/dashboard/.next/server/pages/_document.js.nft.json +1 -0
  140. package/dashboard/.next/server/pages/_error.js +1 -0
  141. package/dashboard/.next/server/pages/_error.js.nft.json +1 -0
  142. package/dashboard/.next/server/pages-manifest.json +1 -0
  143. package/dashboard/.next/server/server-reference-manifest.js +1 -0
  144. package/dashboard/.next/server/server-reference-manifest.json +1 -0
  145. package/dashboard/.next/server/webpack-runtime.js +1 -0
  146. package/dashboard/.next/static/0IZAlhEwk5-v4myUvWKBd/_buildManifest.js +1 -0
  147. package/dashboard/.next/static/0IZAlhEwk5-v4myUvWKBd/_ssgManifest.js +1 -0
  148. package/dashboard/.next/static/chunks/1.8868c4d131111be7.js +36 -0
  149. package/dashboard/.next/static/chunks/1015.3ab89142e5f44120.js +226 -0
  150. package/dashboard/.next/static/chunks/1151.b6ef5c786e587ed7.js +1 -0
  151. package/dashboard/.next/static/chunks/1199.a072929dbec89965.js +148 -0
  152. package/dashboard/.next/static/chunks/1375.d4d2f7fc9c9c2ff1.js +43 -0
  153. package/dashboard/.next/static/chunks/1799.83206776abbbf1fc.js +9 -0
  154. package/dashboard/.next/static/chunks/20154aaa.ccc347c04ab5ad4a.js +1 -0
  155. package/dashboard/.next/static/chunks/2077.7011a570c87aa7b1.js +1 -0
  156. package/dashboard/.next/static/chunks/2166.cc0fabeb2e89b840.js +215 -0
  157. package/dashboard/.next/static/chunks/2291.85a70cb0c228157b.js +29 -0
  158. package/dashboard/.next/static/chunks/2325.2c55cb9a6282ae3f.js +24 -0
  159. package/dashboard/.next/static/chunks/2383.62c035a052272594.js +1 -0
  160. package/dashboard/.next/static/chunks/2694.92bbe252063e4786.js +1 -0
  161. package/dashboard/.next/static/chunks/275.0d761aa0e5b030b8.js +34 -0
  162. package/dashboard/.next/static/chunks/2781.8536b644a480aede.js +93 -0
  163. package/dashboard/.next/static/chunks/2805.a8d71d2f92bb6ba9.js +1 -0
  164. package/dashboard/.next/static/chunks/2879.51436986f93981d9.js +1 -0
  165. package/dashboard/.next/static/chunks/3017.e55781da9dd32d37.js +1 -0
  166. package/dashboard/.next/static/chunks/3205-728c260fbb4f89c6.js +2 -0
  167. package/dashboard/.next/static/chunks/3236.dff44fa7961d9d5e.js +1 -0
  168. package/dashboard/.next/static/chunks/3480.9451396ad7ee7613.js +1 -0
  169. package/dashboard/.next/static/chunks/3626.ba1cf848a9f2e93d.js +64 -0
  170. package/dashboard/.next/static/chunks/3865.a432a7910a2f5281.js +90 -0
  171. package/dashboard/.next/static/chunks/3887.c22cbfa3f095826c.js +1 -0
  172. package/dashboard/.next/static/chunks/3924-4a05057b5450abe1.js +1 -0
  173. package/dashboard/.next/static/chunks/3948.fe3c7d758568d98b.js +287 -0
  174. package/dashboard/.next/static/chunks/4728.07d87640a3e7dd0d.js +24 -0
  175. package/dashboard/.next/static/chunks/4787.4e5f6a0e0e40a583.js +23 -0
  176. package/dashboard/.next/static/chunks/5060.baca226af35ed016.js +1 -0
  177. package/dashboard/.next/static/chunks/5284.f949ac90c95ff143.js +1 -0
  178. package/dashboard/.next/static/chunks/5715.1524bcc9591e180b.js +115 -0
  179. package/dashboard/.next/static/chunks/6014.700ae4969b64d728.js +104 -0
  180. package/dashboard/.next/static/chunks/6024.4d23707c65514679.js +79 -0
  181. package/dashboard/.next/static/chunks/6052.033a6f1013c666eb.js +141 -0
  182. package/dashboard/.next/static/chunks/6177.e5c84cfc4c0dea51.js +1 -0
  183. package/dashboard/.next/static/chunks/618f8807-547c5614e1318888.js +1 -0
  184. package/dashboard/.next/static/chunks/6434.9481771c33195d29.js +1 -0
  185. package/dashboard/.next/static/chunks/6468.f4a3e8fa6accc6da.js +77 -0
  186. package/dashboard/.next/static/chunks/6540.86f367d7390738d4.js +1 -0
  187. package/dashboard/.next/static/chunks/6549.4d0d472df96429a5.js +1 -0
  188. package/dashboard/.next/static/chunks/690f35d0.3e40ca0930e4bbdb.js +119 -0
  189. package/dashboard/.next/static/chunks/7020.831e16e26d91abc1.js +166 -0
  190. package/dashboard/.next/static/chunks/7397-f6f4dddc7a20bfc1.js +1 -0
  191. package/dashboard/.next/static/chunks/7498-ea83cb9e30ec5491.js +1 -0
  192. package/dashboard/.next/static/chunks/7802.89aec9ee11680850.js +80 -0
  193. package/dashboard/.next/static/chunks/7973.8b526f589aca5d84.js +79 -0
  194. package/dashboard/.next/static/chunks/7a04ac15.1c6cea694301806c.js +62 -0
  195. package/dashboard/.next/static/chunks/8216.1bead812eb126c35.js +5 -0
  196. package/dashboard/.next/static/chunks/8233babc.780b8e272eda298f.js +92 -0
  197. package/dashboard/.next/static/chunks/8452-e616b5f43bceb95f.js +13 -0
  198. package/dashboard/.next/static/chunks/8645.a5ca76f11edc9633.js +1 -0
  199. package/dashboard/.next/static/chunks/8928-60c623ee89d2e6ad.js +1 -0
  200. package/dashboard/.next/static/chunks/9173.2486ffca31131ec5.js +1 -0
  201. package/dashboard/.next/static/chunks/9178.469341860bf8caec.js +1 -0
  202. package/dashboard/.next/static/chunks/9466.e904660d38c03eea.js +1 -0
  203. package/dashboard/.next/static/chunks/9660.84a85811380c5f33.js +1 -0
  204. package/dashboard/.next/static/chunks/9717.6cf5c8c89403b651.js +1 -0
  205. package/dashboard/.next/static/chunks/9720.67d4d0d15a96d691.js +1 -0
  206. package/dashboard/.next/static/chunks/9811.65e1d080c2d256af.js +1 -0
  207. package/dashboard/.next/static/chunks/app/_not-found/page-548ab392d0e890d1.js +1 -0
  208. package/dashboard/.next/static/chunks/app/access/page-3668562e7464eb5d.js +1 -0
  209. package/dashboard/.next/static/chunks/app/calls/page-d07f5b8664cc8303.js +1 -0
  210. package/dashboard/.next/static/chunks/app/conformance/page-2fede1d7b5f9265d.js +1 -0
  211. package/dashboard/.next/static/chunks/app/diagram/page-b228444265546495.js +1 -0
  212. package/dashboard/.next/static/chunks/app/flows/page-fa67783d8cd79cab.js +1 -0
  213. package/dashboard/.next/static/chunks/app/functions/page-686f0296639133a3.js +1 -0
  214. package/dashboard/.next/static/chunks/app/issues/page-dc110d4cc0a5c398.js +1 -0
  215. package/dashboard/.next/static/chunks/app/layout-e7b50543ba216d12.js +1 -0
  216. package/dashboard/.next/static/chunks/app/page-a0f25953d4457935.js +1 -0
  217. package/dashboard/.next/static/chunks/app/progress/page-f07ac39d1d27b480.js +1 -0
  218. package/dashboard/.next/static/chunks/app/stats/page-db81f600a086f252.js +1 -0
  219. package/dashboard/.next/static/chunks/b7167ec1.7afbab6f609e3326.js +153 -0
  220. package/dashboard/.next/static/chunks/c7ea4e13.5effeeba6618bdb7.js +1 -0
  221. package/dashboard/.next/static/chunks/framework-cf6f5bdca6ba0184.js +33 -0
  222. package/dashboard/.next/static/chunks/main-70c6d841ad572657.js +1 -0
  223. package/dashboard/.next/static/chunks/main-app-9d2f6b8a47133e9b.js +1 -0
  224. package/dashboard/.next/static/chunks/pages/_app-6ad2b50514c24ab4.js +1 -0
  225. package/dashboard/.next/static/chunks/pages/_error-d5eb11c5c4626811.js +1 -0
  226. package/dashboard/.next/static/chunks/polyfills-78c92fac7aa8fdd8.js +1 -0
  227. package/dashboard/.next/static/chunks/webpack-08869f2b18792e51.js +1 -0
  228. package/dashboard/.next/static/css/e6cb67f77f13ae8e.css +3 -0
  229. package/dashboard/.next/static/media/0aa834ed78bf6d07-s.woff2 +0 -0
  230. package/dashboard/.next/static/media/438aa629764e75f3-s.woff2 +0 -0
  231. package/dashboard/.next/static/media/4c9affa5bc8f420e-s.p.woff2 +0 -0
  232. package/dashboard/.next/static/media/51251f8b9793cdb3-s.woff2 +0 -0
  233. package/dashboard/.next/static/media/67957d42bae0796d-s.woff2 +0 -0
  234. package/dashboard/.next/static/media/875ae681bfde4580-s.woff2 +0 -0
  235. package/dashboard/.next/static/media/886030b0b59bc5a7-s.woff2 +0 -0
  236. package/dashboard/.next/static/media/939c4f875ee75fbb-s.woff2 +0 -0
  237. package/dashboard/.next/static/media/bb3ef058b751a6ad-s.p.woff2 +0 -0
  238. package/dashboard/.next/static/media/cc978ac5ee68c2b6-s.woff2 +0 -0
  239. package/dashboard/.next/static/media/e857b654a2caa584-s.woff2 +0 -0
  240. package/dashboard/.next/static/media/f911b923c6adde36-s.woff2 +0 -0
  241. package/dashboard/.next/trace +80 -0
  242. package/dashboard/.next/types/app/access/page.ts +79 -0
  243. package/dashboard/.next/types/app/api/code/route.ts +343 -0
  244. package/dashboard/.next/types/app/api/flows/route.ts +343 -0
  245. package/dashboard/.next/types/app/api/github-status/route.ts +343 -0
  246. package/dashboard/.next/types/app/api/issues/[id]/move/route.ts +343 -0
  247. package/dashboard/.next/types/app/api/issues/[id]/route.ts +343 -0
  248. package/dashboard/.next/types/app/api/mermaid/route.ts +343 -0
  249. package/dashboard/.next/types/app/api/progress/route.ts +343 -0
  250. package/dashboard/.next/types/app/api/watch/route.ts +343 -0
  251. package/dashboard/.next/types/app/calls/page.ts +79 -0
  252. package/dashboard/.next/types/app/conformance/page.ts +79 -0
  253. package/dashboard/.next/types/app/diagram/page.ts +79 -0
  254. package/dashboard/.next/types/app/flows/page.ts +79 -0
  255. package/dashboard/.next/types/app/functions/page.ts +79 -0
  256. package/dashboard/.next/types/app/issues/page.ts +79 -0
  257. package/dashboard/.next/types/app/page.ts +79 -0
  258. package/dashboard/.next/types/app/progress/page.ts +79 -0
  259. package/dashboard/.next/types/app/stats/page.ts +79 -0
  260. package/dashboard/.next/types/package.json +1 -0
  261. package/dashboard/app/access/AccessClient.tsx +402 -0
  262. package/dashboard/app/access/ReadOnlyFunctions.tsx +114 -0
  263. package/dashboard/app/access/page.tsx +118 -0
  264. package/dashboard/app/api/code/route.ts +35 -0
  265. package/dashboard/app/api/flows/route.ts +28 -0
  266. package/dashboard/app/api/github-status/route.ts +23 -0
  267. package/dashboard/app/api/issues/[id]/move/route.ts +74 -0
  268. package/dashboard/app/api/issues/[id]/route.ts +109 -0
  269. package/dashboard/app/api/mermaid/route.ts +25 -0
  270. package/dashboard/app/api/progress/route.ts +36 -0
  271. package/dashboard/app/api/watch/route.ts +52 -0
  272. package/dashboard/app/calls/CallsClient.tsx +170 -0
  273. package/dashboard/app/calls/page.tsx +50 -0
  274. package/dashboard/app/conformance/ConformanceTable.tsx +214 -0
  275. package/dashboard/app/conformance/page.tsx +179 -0
  276. package/dashboard/app/diagram/page.tsx +65 -0
  277. package/dashboard/app/flows/page.tsx +102 -0
  278. package/dashboard/app/functions/FunctionsClient.tsx +167 -0
  279. package/dashboard/app/functions/page.tsx +171 -0
  280. package/dashboard/app/globals.css +157 -0
  281. package/dashboard/app/icon.svg +18 -0
  282. package/dashboard/app/issues/IssuesBoardClient.tsx +636 -0
  283. package/dashboard/app/issues/page.tsx +239 -0
  284. package/dashboard/app/layout.tsx +40 -0
  285. package/dashboard/app/page.tsx +259 -0
  286. package/dashboard/app/progress/ProgressClient.tsx +333 -0
  287. package/dashboard/app/progress/page.tsx +118 -0
  288. package/dashboard/app/stats/StatsClient.tsx +452 -0
  289. package/dashboard/app/stats/page.tsx +43 -0
  290. package/dashboard/components/AutoRefresh.tsx +37 -0
  291. package/dashboard/components/CodeReference.tsx +129 -0
  292. package/dashboard/components/CommandPalette.tsx +135 -0
  293. package/dashboard/components/ConfidenceBadge.tsx +53 -0
  294. package/dashboard/components/DashboardLayout.tsx +450 -0
  295. package/dashboard/components/FilterableTable.tsx +293 -0
  296. package/dashboard/components/LiveStatus.tsx +99 -0
  297. package/dashboard/components/MarkdownRenderer.tsx +40 -0
  298. package/dashboard/components/MermaidViewer.tsx +267 -0
  299. package/dashboard/components/NotYetGenerated.tsx +32 -0
  300. package/dashboard/components/SeverityBadge.tsx +28 -0
  301. package/dashboard/components/SignalBars.tsx +27 -0
  302. package/dashboard/components/SortableTable.tsx +122 -0
  303. package/dashboard/lib/conformance-tokens.ts +49 -0
  304. package/dashboard/lib/data.ts +102 -0
  305. package/dashboard/lib/watcher.ts +45 -0
  306. package/dashboard/next-env.d.ts +5 -0
  307. package/dashboard/next.config.mjs +9 -0
  308. package/dashboard/postcss.config.cjs +6 -0
  309. package/dashboard/tailwind.config.ts +79 -0
  310. package/dashboard/tsconfig.json +21 -0
  311. package/dist/analysis/access-control.d.ts +24 -0
  312. package/dist/analysis/access-control.d.ts.map +1 -0
  313. package/dist/analysis/access-control.js +378 -0
  314. package/dist/analysis/access-control.js.map +1 -0
  315. package/dist/analysis/attack-surface.d.ts +51 -0
  316. package/dist/analysis/attack-surface.d.ts.map +1 -0
  317. package/dist/analysis/attack-surface.js +206 -0
  318. package/dist/analysis/attack-surface.js.map +1 -0
  319. package/dist/analysis/constraint-extraction.d.ts +25 -0
  320. package/dist/analysis/constraint-extraction.d.ts.map +1 -0
  321. package/dist/analysis/constraint-extraction.js +398 -0
  322. package/dist/analysis/constraint-extraction.js.map +1 -0
  323. package/dist/analysis/context-assembler.d.ts +16 -0
  324. package/dist/analysis/context-assembler.d.ts.map +1 -0
  325. package/dist/analysis/context-assembler.js +88 -0
  326. package/dist/analysis/context-assembler.js.map +1 -0
  327. package/dist/analysis/dependency-graph.d.ts +31 -0
  328. package/dist/analysis/dependency-graph.d.ts.map +1 -0
  329. package/dist/analysis/dependency-graph.js +223 -0
  330. package/dist/analysis/dependency-graph.js.map +1 -0
  331. package/dist/analysis/erc-detection.d.ts +16 -0
  332. package/dist/analysis/erc-detection.d.ts.map +1 -0
  333. package/dist/analysis/erc-detection.js +81 -0
  334. package/dist/analysis/erc-detection.js.map +1 -0
  335. package/dist/analysis/external-calls.d.ts +8 -0
  336. package/dist/analysis/external-calls.d.ts.map +1 -0
  337. package/dist/analysis/external-calls.js +124 -0
  338. package/dist/analysis/external-calls.js.map +1 -0
  339. package/dist/analysis/nsloc.d.ts +46 -0
  340. package/dist/analysis/nsloc.d.ts.map +1 -0
  341. package/dist/analysis/nsloc.js +106 -0
  342. package/dist/analysis/nsloc.js.map +1 -0
  343. package/dist/analysis/pattern-detection.d.ts +20 -0
  344. package/dist/analysis/pattern-detection.d.ts.map +1 -0
  345. package/dist/analysis/pattern-detection.js +236 -0
  346. package/dist/analysis/pattern-detection.js.map +1 -0
  347. package/dist/analysis/state-variables.d.ts +33 -0
  348. package/dist/analysis/state-variables.d.ts.map +1 -0
  349. package/dist/analysis/state-variables.js +179 -0
  350. package/dist/analysis/state-variables.js.map +1 -0
  351. package/dist/commands/access.d.ts +3 -0
  352. package/dist/commands/access.d.ts.map +1 -0
  353. package/dist/commands/access.js +99 -0
  354. package/dist/commands/access.js.map +1 -0
  355. package/dist/commands/ai-status.d.ts +3 -0
  356. package/dist/commands/ai-status.d.ts.map +1 -0
  357. package/dist/commands/ai-status.js +172 -0
  358. package/dist/commands/ai-status.js.map +1 -0
  359. package/dist/commands/analyze.d.ts +3 -0
  360. package/dist/commands/analyze.d.ts.map +1 -0
  361. package/dist/commands/analyze.js +101 -0
  362. package/dist/commands/analyze.js.map +1 -0
  363. package/dist/commands/calls.d.ts +3 -0
  364. package/dist/commands/calls.d.ts.map +1 -0
  365. package/dist/commands/calls.js +92 -0
  366. package/dist/commands/calls.js.map +1 -0
  367. package/dist/commands/claude.d.ts +3 -0
  368. package/dist/commands/claude.d.ts.map +1 -0
  369. package/dist/commands/claude.js +42 -0
  370. package/dist/commands/claude.js.map +1 -0
  371. package/dist/commands/constraints.d.ts +3 -0
  372. package/dist/commands/constraints.d.ts.map +1 -0
  373. package/dist/commands/constraints.js +32 -0
  374. package/dist/commands/constraints.js.map +1 -0
  375. package/dist/commands/context.d.ts +3 -0
  376. package/dist/commands/context.d.ts.map +1 -0
  377. package/dist/commands/context.js +57 -0
  378. package/dist/commands/context.js.map +1 -0
  379. package/dist/commands/dashboard.d.ts +3 -0
  380. package/dist/commands/dashboard.d.ts.map +1 -0
  381. package/dist/commands/dashboard.js +95 -0
  382. package/dist/commands/dashboard.js.map +1 -0
  383. package/dist/commands/deps.d.ts +3 -0
  384. package/dist/commands/deps.d.ts.map +1 -0
  385. package/dist/commands/deps.js +67 -0
  386. package/dist/commands/deps.js.map +1 -0
  387. package/dist/commands/doctor.d.ts +17 -0
  388. package/dist/commands/doctor.d.ts.map +1 -0
  389. package/dist/commands/doctor.js +154 -0
  390. package/dist/commands/doctor.js.map +1 -0
  391. package/dist/commands/init.d.ts +3 -0
  392. package/dist/commands/init.d.ts.map +1 -0
  393. package/dist/commands/init.js +330 -0
  394. package/dist/commands/init.js.map +1 -0
  395. package/dist/commands/patterns.d.ts +3 -0
  396. package/dist/commands/patterns.d.ts.map +1 -0
  397. package/dist/commands/patterns.js +40 -0
  398. package/dist/commands/patterns.js.map +1 -0
  399. package/dist/commands/state.d.ts +3 -0
  400. package/dist/commands/state.d.ts.map +1 -0
  401. package/dist/commands/state.js +92 -0
  402. package/dist/commands/state.js.map +1 -0
  403. package/dist/commands/stats.d.ts +3 -0
  404. package/dist/commands/stats.d.ts.map +1 -0
  405. package/dist/commands/stats.js +347 -0
  406. package/dist/commands/stats.js.map +1 -0
  407. package/dist/commands/surface.d.ts +3 -0
  408. package/dist/commands/surface.d.ts.map +1 -0
  409. package/dist/commands/surface.js +45 -0
  410. package/dist/commands/surface.js.map +1 -0
  411. package/dist/commands/update-skills.d.ts +3 -0
  412. package/dist/commands/update-skills.d.ts.map +1 -0
  413. package/dist/commands/update-skills.js +40 -0
  414. package/dist/commands/update-skills.js.map +1 -0
  415. package/dist/commands/update.d.ts +3 -0
  416. package/dist/commands/update.d.ts.map +1 -0
  417. package/dist/commands/update.js +157 -0
  418. package/dist/commands/update.js.map +1 -0
  419. package/dist/core/config.d.ts +24 -0
  420. package/dist/core/config.d.ts.map +1 -0
  421. package/dist/core/config.js +70 -0
  422. package/dist/core/config.js.map +1 -0
  423. package/dist/core/errors.d.ts +17 -0
  424. package/dist/core/errors.d.ts.map +1 -0
  425. package/dist/core/errors.js +113 -0
  426. package/dist/core/errors.js.map +1 -0
  427. package/dist/core/external-tools.d.ts +39 -0
  428. package/dist/core/external-tools.d.ts.map +1 -0
  429. package/dist/core/external-tools.js +151 -0
  430. package/dist/core/external-tools.js.map +1 -0
  431. package/dist/core/logger.d.ts +16 -0
  432. package/dist/core/logger.d.ts.map +1 -0
  433. package/dist/core/logger.js +22 -0
  434. package/dist/core/logger.js.map +1 -0
  435. package/dist/core/output.d.ts +13 -0
  436. package/dist/core/output.d.ts.map +1 -0
  437. package/dist/core/output.js +45 -0
  438. package/dist/core/output.js.map +1 -0
  439. package/dist/core/paths.d.ts +21 -0
  440. package/dist/core/paths.d.ts.map +1 -0
  441. package/dist/core/paths.js +32 -0
  442. package/dist/core/paths.js.map +1 -0
  443. package/dist/core/progress.d.ts +34 -0
  444. package/dist/core/progress.d.ts.map +1 -0
  445. package/dist/core/progress.js +119 -0
  446. package/dist/core/progress.js.map +1 -0
  447. package/dist/core/schema.d.ts +3197 -0
  448. package/dist/core/schema.d.ts.map +1 -0
  449. package/dist/core/schema.js +420 -0
  450. package/dist/core/schema.js.map +1 -0
  451. package/dist/core/skills.d.ts +28 -0
  452. package/dist/core/skills.d.ts.map +1 -0
  453. package/dist/core/skills.js +82 -0
  454. package/dist/core/skills.js.map +1 -0
  455. package/dist/index.d.ts +3 -0
  456. package/dist/index.d.ts.map +1 -0
  457. package/dist/index.js +43 -0
  458. package/dist/index.js.map +1 -0
  459. package/dist/parsers/lcov.d.ts +27 -0
  460. package/dist/parsers/lcov.d.ts.map +1 -0
  461. package/dist/parsers/lcov.js +68 -0
  462. package/dist/parsers/lcov.js.map +1 -0
  463. package/dist/parsers/slither.d.ts +63 -0
  464. package/dist/parsers/slither.d.ts.map +1 -0
  465. package/dist/parsers/slither.js +160 -0
  466. package/dist/parsers/slither.js.map +1 -0
  467. package/dist/parsers/solc.d.ts +19 -0
  468. package/dist/parsers/solc.d.ts.map +1 -0
  469. package/dist/parsers/solc.js +43 -0
  470. package/dist/parsers/solc.js.map +1 -0
  471. package/dist/parsers/solidity-parser.d.ts +77 -0
  472. package/dist/parsers/solidity-parser.d.ts.map +1 -0
  473. package/dist/parsers/solidity-parser.js +357 -0
  474. package/dist/parsers/solidity-parser.js.map +1 -0
  475. package/dist/skills/generate-overleaf.md +326 -0
  476. package/dist/skills/generate-poc.md +186 -0
  477. package/dist/skills/ingest-aa-report.md +172 -0
  478. package/dist/skills/init-audit.md +271 -0
  479. package/dist/skills/sync-issues.md +266 -0
  480. package/dist/skills/validate-issue.md +149 -0
  481. package/dist/skills/write-finding.md +142 -0
  482. package/dist/types/index.d.ts +30 -0
  483. package/dist/types/index.d.ts.map +1 -0
  484. package/dist/types/index.js +2 -0
  485. package/dist/types/index.js.map +1 -0
  486. package/package.json +81 -0
@@ -0,0 +1,267 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useRef, useState, useCallback, useMemo } from 'react';
4
+
5
+ /* ── Terminal loading indicator (reusable) ── */
6
+ export function LoadingSpinner({ label = 'loading...' }: { label?: string }) {
7
+ return (
8
+ <div className="flex flex-col items-center justify-center gap-3 py-sp-8">
9
+ <svg className="h-5 w-5 animate-spin text-accent" viewBox="0 0 24 24" fill="none">
10
+ <circle className="opacity-20" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="3" />
11
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
12
+ </svg>
13
+ <span className="text-body text-text-secondary">{label}</span>
14
+ </div>
15
+ );
16
+ }
17
+
18
+ interface MermaidViewerProps {
19
+ syntax: string;
20
+ }
21
+
22
+ function parseMermaidComments(raw: string) {
23
+ const lines = raw.split('\n');
24
+ const overview: string[] = [];
25
+ const legend: string[] = [];
26
+ const mermaid: string[] = [];
27
+ let inLegend = false;
28
+
29
+ for (const line of lines) {
30
+ if (inLegend) {
31
+ if (line.startsWith('%%')) {
32
+ legend.push(line.replace(/^%%\s*/, ''));
33
+ }
34
+ continue;
35
+ }
36
+ if (line.trim().startsWith('%% --- Legend')) {
37
+ inLegend = true;
38
+ continue;
39
+ }
40
+ if (line.startsWith('%%') && mermaid.length === 0) {
41
+ overview.push(line.replace(/^%%\s*/, ''));
42
+ } else {
43
+ mermaid.push(line);
44
+ }
45
+ }
46
+
47
+ return {
48
+ overview: overview.join(' ').trim(),
49
+ legend: legend.filter((l) => l.trim()).map((l) => l.trim()),
50
+ syntax: mermaid.join('\n'),
51
+ };
52
+ }
53
+
54
+ export function MermaidViewer({ syntax }: MermaidViewerProps) {
55
+ const containerRef = useRef<HTMLDivElement>(null);
56
+ const svgRef = useRef<HTMLDivElement>(null);
57
+ const [error, setError] = useState<string | null>(null);
58
+ const [rendering, setRendering] = useState(true);
59
+ const [scale, setScale] = useState(1);
60
+ const [translate, setTranslate] = useState({ x: 0, y: 0 });
61
+ const [dragging, setDragging] = useState(false);
62
+ const dragStart = useRef({ x: 0, y: 0 });
63
+ const translateStart = useRef({ x: 0, y: 0 });
64
+
65
+ const parsed = useMemo(() => parseMermaidComments(syntax), [syntax]);
66
+
67
+ useEffect(() => {
68
+ let cancelled = false;
69
+ setRendering(true);
70
+
71
+ async function render() {
72
+ try {
73
+ const mermaid = (await import('mermaid')).default;
74
+ mermaid.initialize({
75
+ startOnLoad: false,
76
+ theme: 'base',
77
+ themeVariables: {
78
+ background: '#1c1c1e',
79
+ mainBkg: '#27272a',
80
+ primaryColor: '#27272a',
81
+ primaryBorderColor: 'rgba(91,108,240,0.35)',
82
+ primaryTextColor: '#ecedf0',
83
+ lineColor: 'rgba(91,108,240,0.45)',
84
+ secondaryColor: '#313135',
85
+ tertiaryColor: '#3c3c42',
86
+ clusterBkg: '#222225',
87
+ clusterBorder: 'rgba(91,108,240,0.15)',
88
+ edgeLabelBackground: '#1c1c1e',
89
+ titleColor: '#9b9ca6',
90
+ fontFamily: 'Manrope, system-ui, sans-serif',
91
+ fontSize: '12px',
92
+ labelTextColor: '#ecedf0',
93
+ nodeBorder: 'rgba(91,108,240,0.35)',
94
+ actorBkg: '#27272a',
95
+ actorBorder: 'rgba(91,108,240,0.35)',
96
+ actorTextColor: '#ecedf0',
97
+ actorLineColor: 'rgba(91,108,240,0.25)',
98
+ signalColor: 'rgba(91,108,240,0.45)',
99
+ signalTextColor: '#9b9ca6',
100
+ },
101
+ securityLevel: 'loose',
102
+ fontFamily: 'Manrope, system-ui, sans-serif',
103
+ });
104
+
105
+ const id = `mermaid-${Date.now()}`;
106
+ const { svg } = await mermaid.render(id, parsed.syntax);
107
+
108
+ if (!cancelled && svgRef.current) {
109
+ svgRef.current.innerHTML = svg;
110
+ const svgEl = svgRef.current.querySelector('svg');
111
+ if (svgEl) {
112
+ svgEl.style.maxWidth = 'none';
113
+ svgEl.style.height = 'auto';
114
+
115
+ // Auto-fit: scale down to fit container if diagram overflows
116
+ if (containerRef.current) {
117
+ const padding = 48;
118
+ const containerW = containerRef.current.clientWidth - padding;
119
+ const containerH = containerRef.current.clientHeight - padding;
120
+ const svgW = svgEl.width.baseVal.value || svgEl.getBoundingClientRect().width;
121
+ const svgH = svgEl.height.baseVal.value || svgEl.getBoundingClientRect().height;
122
+ if (svgW > 0 && svgH > 0) {
123
+ const fitScale = Math.min(containerW / svgW, containerH / svgH, 1);
124
+ setScale(fitScale);
125
+ setTranslate({ x: 0, y: 0 });
126
+ }
127
+ }
128
+ }
129
+ setRendering(false);
130
+ }
131
+ } catch (err) {
132
+ if (!cancelled) {
133
+ setError(err instanceof Error ? err.message : String(err));
134
+ setRendering(false);
135
+ }
136
+ }
137
+ }
138
+
139
+ render();
140
+ return () => { cancelled = true; };
141
+ }, [parsed.syntax]);
142
+
143
+ const zoom = useCallback((delta: number) => {
144
+ setScale((s) => Math.min(Math.max(0.25, s + delta), 4));
145
+ }, []);
146
+
147
+ const resetView = useCallback(() => {
148
+ setScale(1);
149
+ setTranslate({ x: 0, y: 0 });
150
+ }, []);
151
+
152
+ const handleWheel = useCallback((e: React.WheelEvent) => {
153
+ e.preventDefault();
154
+ const delta = e.deltaY > 0 ? -0.1 : 0.1;
155
+ zoom(delta);
156
+ }, [zoom]);
157
+
158
+ const handleMouseDown = useCallback((e: React.MouseEvent) => {
159
+ if (e.button !== 0) return;
160
+ setDragging(true);
161
+ dragStart.current = { x: e.clientX, y: e.clientY };
162
+ translateStart.current = { ...translate };
163
+ }, [translate]);
164
+
165
+ const handleMouseMove = useCallback((e: React.MouseEvent) => {
166
+ if (!dragging) return;
167
+ setTranslate({
168
+ x: translateStart.current.x + (e.clientX - dragStart.current.x),
169
+ y: translateStart.current.y + (e.clientY - dragStart.current.y),
170
+ });
171
+ }, [dragging]);
172
+
173
+ const handleMouseUp = useCallback(() => {
174
+ setDragging(false);
175
+ }, []);
176
+
177
+ if (error) {
178
+ return (
179
+ <div className="flex h-[600px] items-center justify-center rounded-md border border-severity-critical/30 bg-severity-critical/5">
180
+ <div className="max-w-lg text-center">
181
+ <p className="mb-2 text-severity-critical">Failed to render diagram</p>
182
+ <pre className="whitespace-pre-wrap text-caption text-severity-critical/60">{error}</pre>
183
+ </div>
184
+ </div>
185
+ );
186
+ }
187
+
188
+ return (
189
+ <div>
190
+ {/* Overview */}
191
+ {parsed.overview && (
192
+ <p className="mb-2 text-body text-text-secondary">{parsed.overview}</p>
193
+ )}
194
+
195
+ {/* Full-bleed canvas */}
196
+ <div className="relative rounded-md border border-border-default bg-surface-1">
197
+ {/* Rendering overlay */}
198
+ {rendering && (
199
+ <div className="absolute inset-0 z-20 flex items-center justify-center bg-surface-1">
200
+ <LoadingSpinner label="rendering diagram" />
201
+ </div>
202
+ )}
203
+
204
+ {/* Diagram viewport */}
205
+ <div
206
+ ref={containerRef}
207
+ className="h-[700px] overflow-hidden cursor-grab active:cursor-grabbing"
208
+ onWheel={handleWheel}
209
+ onMouseDown={handleMouseDown}
210
+ onMouseMove={handleMouseMove}
211
+ onMouseUp={handleMouseUp}
212
+ onMouseLeave={handleMouseUp}
213
+ >
214
+ <div
215
+ ref={svgRef}
216
+ className="flex h-full w-full items-center justify-center p-sp-6"
217
+ style={{
218
+ transform: `translate(${translate.x}px, ${translate.y}px) scale(${scale})`,
219
+ transformOrigin: 'center center',
220
+ transition: dragging ? 'none' : 'transform 0.1s ease-out',
221
+ }}
222
+ />
223
+ </div>
224
+
225
+ {/* Floating zoom controls — bottom right */}
226
+ <div className="absolute bottom-3 right-3 z-10 flex items-center gap-1 rounded-md bg-surface-2 p-1 shadow-lg border border-border-default">
227
+ <button
228
+ type="button"
229
+ onClick={() => zoom(0.2)}
230
+ aria-label="Zoom in"
231
+ className="rounded px-3 py-1.5 text-body text-text-secondary hover:bg-surface-3 hover:text-text-primary"
232
+ >
233
+ +
234
+ </button>
235
+ <button
236
+ type="button"
237
+ onClick={() => zoom(-0.2)}
238
+ aria-label="Zoom out"
239
+ className="rounded px-3 py-1.5 text-body text-text-secondary hover:bg-surface-3 hover:text-text-primary"
240
+ >
241
+ −
242
+ </button>
243
+ <button
244
+ type="button"
245
+ onClick={resetView}
246
+ aria-label="Reset zoom"
247
+ className="rounded px-3 py-1.5 text-body text-text-secondary hover:bg-surface-3 hover:text-text-primary"
248
+ >
249
+ ⟳
250
+ </button>
251
+ <span className="px-2 text-caption text-text-tertiary">
252
+ {Math.round(scale * 100)}%
253
+ </span>
254
+ </div>
255
+
256
+ {/* Floating legend overlay — bottom left */}
257
+ {parsed.legend.length > 0 && (
258
+ <div className="absolute bottom-3 left-3 z-10 flex flex-wrap gap-x-3 gap-y-1 rounded-md bg-surface-2 px-3 py-2 text-caption font-mono text-text-tertiary border border-border-default">
259
+ {parsed.legend.map((line, i) => (
260
+ <span key={i}>{line}</span>
261
+ ))}
262
+ </div>
263
+ )}
264
+ </div>
265
+ </div>
266
+ );
267
+ }
@@ -0,0 +1,32 @@
1
+ interface NotYetGeneratedProps {
2
+ command: string;
3
+ }
4
+
5
+ export function NotYetGenerated({ command }: NotYetGeneratedProps) {
6
+ return (
7
+ <div className="flex flex-col items-center justify-center border border-dashed border-border-default bg-surface-1 px-sp-5 py-sp-8 text-center" style={{ borderRadius: 'var(--radius-sm)' }}>
8
+ <svg
9
+ className="mb-4 h-12 w-12 text-text-tertiary"
10
+ fill="none"
11
+ viewBox="0 0 24 24"
12
+ stroke="currentColor"
13
+ strokeWidth={1.5}
14
+ >
15
+ <path
16
+ strokeLinecap="round"
17
+ strokeLinejoin="round"
18
+ d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m6.75 12H9.75m3 0H9.75m0 0v3m-3-6h1.5m-1.5 0v3m6-6h.008v.008H15V9.75Z"
19
+ />
20
+ </svg>
21
+ <h3 className="mb-2 text-heading font-medium text-text-primary">
22
+ Data not yet generated
23
+ </h3>
24
+ <p className="mb-4 text-body text-text-secondary">
25
+ Run the following command to generate this data:
26
+ </p>
27
+ <code className="border border-border-default bg-surface-0 px-sp-4 py-sp-2 font-mono text-body text-accent" style={{ borderRadius: 'var(--radius-sm)' }}>
28
+ {command}
29
+ </code>
30
+ </div>
31
+ );
32
+ }
@@ -0,0 +1,28 @@
1
+ type Severity = 'Critical' | 'High' | 'Medium' | 'Low' | 'Info';
2
+
3
+ interface SeverityBadgeProps {
4
+ severity: Severity;
5
+ }
6
+
7
+ // /18 opacity (a touch above /15) keeps WCAG AA contrast for severity text in
8
+ // both dark and light themes — verified in light mode where the Manrope-400
9
+ // caption on /15 was borderline.
10
+ const STYLES: Record<Severity, string> = {
11
+ Critical: 'bg-[var(--critical)]/18 text-[var(--critical)]',
12
+ High: 'bg-[var(--high)]/18 text-[var(--high)]',
13
+ Medium: 'bg-[var(--medium)]/18 text-[var(--medium)]',
14
+ Low: 'bg-[var(--low)]/18 text-[var(--low)]',
15
+ Info: 'bg-[var(--info)]/18 text-[var(--info)]',
16
+ };
17
+
18
+ export function SeverityBadge({ severity }: SeverityBadgeProps) {
19
+ const style = STYLES[severity] ?? STYLES.Info;
20
+
21
+ return (
22
+ <span
23
+ className={`inline-flex items-center rounded-md px-2 py-0.5 text-caption font-medium ${style}`}
24
+ >
25
+ {severity}
26
+ </span>
27
+ );
28
+ }
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+
3
+ interface SignalBarsProps {
4
+ level: string; // 'high' | 'medium' | 'low'
5
+ }
6
+
7
+ export function SignalBars({ level }: SignalBarsProps) {
8
+ const normalized = level.toLowerCase();
9
+ const activeBars = normalized === 'high' ? 3 : normalized === 'medium' ? 2 : 1;
10
+
11
+ return (
12
+ <span className="inline-flex items-end gap-0.5" title={`Confidence: ${level}`}>
13
+ {[1, 2, 3].map((bar) => (
14
+ <span
15
+ key={bar}
16
+ className={`inline-block rounded-sm ${
17
+ bar <= activeBars ? 'bg-accent' : 'bg-text-tertiary'
18
+ }`}
19
+ style={{
20
+ width: '4px',
21
+ height: `${bar * 5 + 3}px`,
22
+ }}
23
+ />
24
+ ))}
25
+ </span>
26
+ );
27
+ }
@@ -0,0 +1,122 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import {
5
+ flexRender,
6
+ getCoreRowModel,
7
+ getSortedRowModel,
8
+ useReactTable,
9
+ type ColumnDef,
10
+ type SortingState,
11
+ } from '@tanstack/react-table';
12
+
13
+ interface SortableTableProps<T> {
14
+ columns: ColumnDef<T, any>[];
15
+ data: T[];
16
+ }
17
+
18
+ export function SortableTable<T>({ columns, data }: SortableTableProps<T>) {
19
+ const [sorting, setSorting] = useState<SortingState>([]);
20
+
21
+ const table = useReactTable({
22
+ data,
23
+ columns,
24
+ state: { sorting },
25
+ onSortingChange: setSorting,
26
+ getCoreRowModel: getCoreRowModel(),
27
+ getSortedRowModel: getSortedRowModel(),
28
+ });
29
+
30
+ return (
31
+ <div className="overflow-x-auto border border-border-default" style={{ borderRadius: 'var(--radius-sm)' }}>
32
+ <table className="w-full text-left text-body">
33
+ <thead className="border-b border-border-default bg-surface-2 text-caption font-medium uppercase tracking-wider text-text-tertiary">
34
+ {table.getHeaderGroups().map((headerGroup) => (
35
+ <tr key={headerGroup.id}>
36
+ {headerGroup.headers.map((header) => (
37
+ <th
38
+ key={header.id}
39
+ scope="col"
40
+ aria-sort={
41
+ header.column.getIsSorted() === 'asc' ? 'ascending'
42
+ : header.column.getIsSorted() === 'desc' ? 'descending'
43
+ : undefined
44
+ }
45
+ className="px-sp-4 py-sp-2 font-medium"
46
+ style={{ width: header.getSize() !== 150 ? header.getSize() : undefined }}
47
+ >
48
+ {header.isPlaceholder ? null : header.column.getCanSort() ? (
49
+ <button
50
+ type="button"
51
+ className="inline-flex cursor-pointer select-none items-center gap-1 hover:text-text-secondary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent rounded-sm"
52
+ onClick={header.column.getToggleSortingHandler()}
53
+ >
54
+ {flexRender(header.column.columnDef.header, header.getContext())}
55
+ {{
56
+ asc: <SortAscIcon />,
57
+ desc: <SortDescIcon />,
58
+ }[header.column.getIsSorted() as string] ?? <SortNeutralIcon />}
59
+ </button>
60
+ ) : (
61
+ <span className="inline-flex items-center gap-1">
62
+ {flexRender(header.column.columnDef.header, header.getContext())}
63
+ </span>
64
+ )}
65
+ </th>
66
+ ))}
67
+ </tr>
68
+ ))}
69
+ </thead>
70
+ <tbody className="divide-y divide-border-subtle">
71
+ {table.getRowModel().rows.length === 0 ? (
72
+ <tr>
73
+ <td
74
+ colSpan={columns.length}
75
+ className="px-sp-4 py-sp-6 text-center text-text-tertiary"
76
+ >
77
+ No data
78
+ </td>
79
+ </tr>
80
+ ) : (
81
+ table.getRowModel().rows.map((row) => (
82
+ <tr
83
+ key={row.id}
84
+ className="min-h-9 bg-surface-1 hover:bg-surface-3"
85
+ >
86
+ {row.getVisibleCells().map((cell) => (
87
+ <td key={cell.id} className="px-sp-4 py-sp-2 text-text-secondary align-top">
88
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
89
+ </td>
90
+ ))}
91
+ </tr>
92
+ ))
93
+ )}
94
+ </tbody>
95
+ </table>
96
+ </div>
97
+ );
98
+ }
99
+
100
+ function SortAscIcon() {
101
+ return (
102
+ <svg className="h-3.5 w-3.5" aria-hidden="true" viewBox="0 0 16 16" fill="currentColor">
103
+ <path d="M8 4l4 6H4l4-6z" />
104
+ </svg>
105
+ );
106
+ }
107
+
108
+ function SortDescIcon() {
109
+ return (
110
+ <svg className="h-3.5 w-3.5" aria-hidden="true" viewBox="0 0 16 16" fill="currentColor">
111
+ <path d="M8 12L4 6h8l-4 6z" />
112
+ </svg>
113
+ );
114
+ }
115
+
116
+ function SortNeutralIcon() {
117
+ return (
118
+ <svg className="h-3.5 w-3.5 text-text-tertiary" aria-hidden="true" viewBox="0 0 16 16" fill="currentColor">
119
+ <path d="M8 3l3 4H5l3-4zm0 10L5 9h6l-3 4z" />
120
+ </svg>
121
+ );
122
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Shared conformance-status color tokens, used by the `/conformance` page summary
3
+ * pills and the table itself. Keeping them in one module prevents the two
4
+ * surfaces from drifting visually.
5
+ *
6
+ * Status keys mirror the values used in `spec-conformance.json` items.
7
+ */
8
+
9
+ export const CONFORMANCE_STATUSES = [
10
+ 'DEVIATES',
11
+ 'PARTIAL',
12
+ 'UNVERIFIABLE',
13
+ 'UNDOCUMENTED',
14
+ 'CONFORMS',
15
+ ] as const;
16
+
17
+ export type ConformanceStatus = (typeof CONFORMANCE_STATUSES)[number];
18
+
19
+ export const CONFORMANCE_STATUS_DOT: Record<ConformanceStatus, string> = {
20
+ DEVIATES: 'bg-[var(--critical)]',
21
+ PARTIAL: 'bg-[var(--medium)]',
22
+ UNVERIFIABLE: 'bg-accent',
23
+ UNDOCUMENTED: 'bg-[var(--neutral)]',
24
+ CONFORMS: 'bg-[var(--success)]',
25
+ };
26
+
27
+ export const CONFORMANCE_STATUS_TEXT: Record<ConformanceStatus, string> = {
28
+ DEVIATES: 'text-[var(--critical)]',
29
+ PARTIAL: 'text-[var(--medium)]',
30
+ UNVERIFIABLE: 'text-accent',
31
+ UNDOCUMENTED: 'text-text-secondary',
32
+ CONFORMS: 'text-[var(--success)]',
33
+ };
34
+
35
+ export const CONFORMANCE_STATUS_BADGE: Record<ConformanceStatus, string> = {
36
+ DEVIATES: 'bg-[var(--critical)]/18 text-[var(--critical)]',
37
+ PARTIAL: 'bg-[var(--medium)]/18 text-[var(--medium)]',
38
+ UNVERIFIABLE: 'bg-accent/18 text-accent',
39
+ UNDOCUMENTED: 'bg-[var(--neutral)]/18 text-[var(--neutral)]',
40
+ CONFORMS: 'bg-[var(--success)]/18 text-[var(--success)]',
41
+ };
42
+
43
+ export const CONFORMANCE_STATUS_ROW_BG: Record<ConformanceStatus, string> = {
44
+ DEVIATES: 'bg-[var(--critical)]/5',
45
+ PARTIAL: 'bg-[var(--medium)]/5',
46
+ UNVERIFIABLE: 'bg-accent/5',
47
+ UNDOCUMENTED: 'bg-surface-1',
48
+ CONFORMS: 'bg-[var(--success)]/5',
49
+ };
@@ -0,0 +1,102 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ function getProjectDir(): string {
5
+ return process.env.HEX_PROJECT_DIR ?? process.env.SOLAUDIT_PROJECT_DIR ?? process.cwd();
6
+ }
7
+
8
+ function getOutputDir(): string {
9
+ const projectDir = getProjectDir();
10
+ // Try .hex/ first, fall back to .solaudit/ for backwards compat
11
+ try {
12
+ const hexConfigPath = path.join(projectDir, '.hex', 'config.json');
13
+ if (fs.existsSync(hexConfigPath)) {
14
+ return path.join(projectDir, '.hex');
15
+ }
16
+ const legacyConfigPath = path.join(projectDir, '.solaudit', 'config.json');
17
+ if (fs.existsSync(legacyConfigPath)) {
18
+ return path.join(projectDir, '.solaudit');
19
+ }
20
+ } catch { /* ignore */ }
21
+ return path.join(projectDir, '.hex');
22
+ }
23
+
24
+ /**
25
+ * Read and parse a JSON file from the output directory.
26
+ */
27
+ export function readJsonFile<T>(filename: string): T | null {
28
+ try {
29
+ const filePath = path.join(getOutputDir(), filename);
30
+ const content = fs.readFileSync(filePath, 'utf-8');
31
+ return JSON.parse(content) as T;
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Read a markdown file from the output directory.
39
+ */
40
+ export function readMarkdownFile(filename: string): string | null {
41
+ try {
42
+ const filePath = path.join(getOutputDir(), filename);
43
+ return fs.readFileSync(filePath, 'utf-8');
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Write a JSON file to the output directory.
51
+ */
52
+ export function writeJsonFile(filename: string, data: unknown): void {
53
+ const filePath = path.join(getOutputDir(), filename);
54
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
55
+ }
56
+
57
+ /**
58
+ * Check if a file exists in the output directory.
59
+ */
60
+ export function fileExists(filename: string): boolean {
61
+ try {
62
+ const filePath = path.join(getOutputDir(), filename);
63
+ return fs.existsSync(filePath);
64
+ } catch {
65
+ return false;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Get the output directory path.
71
+ */
72
+ export function getOutputDirPath(): string {
73
+ return getOutputDir();
74
+ }
75
+
76
+ /**
77
+ * List subdirectory names within a directory relative to the output dir.
78
+ */
79
+ export function listSubdirs(dir: string): string[] {
80
+ try {
81
+ const fullPath = path.join(getOutputDir(), dir);
82
+ if (!fs.existsSync(fullPath)) return [];
83
+ return fs.readdirSync(fullPath, { withFileTypes: true })
84
+ .filter((d) => d.isDirectory())
85
+ .map((d) => d.name);
86
+ } catch {
87
+ return [];
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Read a JSON file from a nested path within the output directory.
93
+ */
94
+ export function readNestedJsonFile<T>(nestedPath: string): T | null {
95
+ try {
96
+ const filePath = path.join(getOutputDir(), nestedPath);
97
+ const content = fs.readFileSync(filePath, 'utf-8');
98
+ return JSON.parse(content) as T;
99
+ } catch {
100
+ return null;
101
+ }
102
+ }
@@ -0,0 +1,45 @@
1
+ import chokidar from 'chokidar';
2
+ import path from 'node:path';
3
+
4
+ let watcher: chokidar.FSWatcher | null = null;
5
+ const listeners = new Set<(file: string) => void>();
6
+
7
+ /**
8
+ * Initialize file watcher for the output directory.
9
+ */
10
+ export function initWatcher(outputDir: string): void {
11
+ if (watcher) return;
12
+
13
+ watcher = chokidar.watch(
14
+ path.join(outputDir, '**/*.{json,md,mmd}'),
15
+ {
16
+ ignoreInitial: true,
17
+ awaitWriteFinish: {
18
+ stabilityThreshold: 300,
19
+ pollInterval: 100,
20
+ },
21
+ },
22
+ );
23
+
24
+ watcher.on('change', (filePath) => {
25
+ const relative = path.relative(outputDir, filePath).replace(/\\/g, '/');
26
+ for (const listener of listeners) {
27
+ listener(relative);
28
+ }
29
+ });
30
+
31
+ watcher.on('add', (filePath) => {
32
+ const relative = path.relative(outputDir, filePath).replace(/\\/g, '/');
33
+ for (const listener of listeners) {
34
+ listener(relative);
35
+ }
36
+ });
37
+ }
38
+
39
+ /**
40
+ * Subscribe to file change events.
41
+ */
42
+ export function onFileChange(callback: (file: string) => void): () => void {
43
+ listeners.add(callback);
44
+ return () => listeners.delete(callback);
45
+ }
@@ -0,0 +1,5 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // NOTE: This file should not be edited
5
+ // see https://nextjs.org/docs/basic-features/typescript for more information.
@@ -0,0 +1,9 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: true,
4
+ experimental: {
5
+ serverComponentsExternalPackages: ['chokidar'],
6
+ },
7
+ };
8
+
9
+ export default nextConfig;