hex-audit 0.5.6 → 0.6.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 (66) hide show
  1. package/DEMO.md +15 -12
  2. package/README.md +16 -13
  3. package/dashboard/.next/BUILD_ID +1 -1
  4. package/dashboard/.next/app-build-manifest.json +20 -20
  5. package/dashboard/.next/app-path-routes-manifest.json +1 -1
  6. package/dashboard/.next/build-manifest.json +4 -4
  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/routes-manifest.json +1 -1
  11. package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  12. package/dashboard/.next/server/app/_not-found.html +1 -1
  13. package/dashboard/.next/server/app/_not-found.rsc +4 -4
  14. package/dashboard/.next/server/app/access/page_client-reference-manifest.js +1 -1
  15. package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +1 -1
  16. package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +1 -1
  17. package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +1 -1
  18. package/dashboard/.next/server/app/diagram.html +1 -1
  19. package/dashboard/.next/server/app/diagram.rsc +4 -4
  20. package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +1 -1
  21. package/dashboard/.next/server/app/flows.html +1 -1
  22. package/dashboard/.next/server/app/flows.rsc +4 -4
  23. package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +1 -1
  24. package/dashboard/.next/server/app/issues/page.js +1 -1
  25. package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -1
  26. package/dashboard/.next/server/app/notes/page_client-reference-manifest.js +1 -1
  27. package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
  28. package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +1 -1
  29. package/dashboard/.next/server/app/report/page.js +1 -0
  30. package/dashboard/.next/server/app/report/page_client-reference-manifest.js +1 -0
  31. package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +1 -1
  32. package/dashboard/.next/server/app-paths-manifest.json +10 -10
  33. package/dashboard/.next/server/chunks/530.js +1 -1
  34. package/dashboard/.next/server/functions-config-manifest.json +1 -1
  35. package/dashboard/.next/server/middleware-build-manifest.js +1 -1
  36. package/dashboard/.next/server/pages/404.html +1 -1
  37. package/dashboard/.next/server/pages/500.html +1 -1
  38. package/dashboard/.next/server/server-reference-manifest.js +1 -1
  39. package/dashboard/.next/server/server-reference-manifest.json +1 -1
  40. package/dashboard/.next/static/chunks/app/issues/{page-d1607f57783782ae.js → page-98a298e1c1045c91.js} +1 -1
  41. package/dashboard/.next/static/chunks/app/{layout-a95b696089e278c3.js → layout-49f2496c7637d931.js} +1 -1
  42. package/dashboard/.next/static/chunks/app/report/page-796f2f4a8a5ac8f7.js +1 -0
  43. package/dashboard/.next/static/chunks/{main-9a811c95265dbd11.js → main-63ff429eab01f5bf.js} +1 -1
  44. package/dashboard/app/issues/IssuesBoardClient.tsx +1 -1
  45. package/dashboard/app/{overleaf/OverleafClient.tsx → report/ReportClient.tsx} +15 -7
  46. package/dashboard/app/report/page.tsx +35 -0
  47. package/dashboard/components/DashboardLayout.tsx +1 -1
  48. package/dist/commands/init.js +2 -2
  49. package/dist/commands/init.js.map +1 -1
  50. package/dist/core/schema.d.ts +14 -0
  51. package/dist/core/schema.d.ts.map +1 -1
  52. package/dist/core/schema.js +2 -0
  53. package/dist/core/schema.js.map +1 -1
  54. package/dist/skills/{generate-overleaf.md → generate-report.md} +186 -32
  55. package/dist/skills/init-audit.md +1 -1
  56. package/dist/skills/sync-issues.md +1 -1
  57. package/dist/skills/validate-all-findings.md +1 -1
  58. package/dist/skills/validate-finding.md +1 -1
  59. package/package.json +1 -1
  60. package/dashboard/.next/server/app/overleaf/page.js +0 -1
  61. package/dashboard/.next/server/app/overleaf/page_client-reference-manifest.js +0 -1
  62. package/dashboard/.next/static/chunks/app/overleaf/page-bcea12a80c97b92f.js +0 -1
  63. package/dashboard/app/overleaf/page.tsx +0 -32
  64. /package/dashboard/.next/server/app/{overleaf → report}/page.js.nft.json +0 -0
  65. /package/dashboard/.next/static/{hV9GBuhq9vm6hXiHOWEfE → hU4ffTc1ImuXgNi8GX6_t}/_buildManifest.js +0 -0
  66. /package/dashboard/.next/static/{hV9GBuhq9vm6hXiHOWEfE → hU4ffTc1ImuXgNi8GX6_t}/_ssgManifest.js +0 -0
@@ -1,23 +1,44 @@
1
1
  ---
2
- description: "Generate the four LaTeX section files for the final audit report (Overleaf-ready)"
2
+ description: "Generate the LaTeX report sections for the final audit report (Overleaf-ready)"
3
3
  ---
4
4
 
5
- # Skill: Generate Overleaf
5
+ # Skill: Generate Report
6
6
 
7
7
  **Recommended model:** Sonnet
8
8
 
9
- This skill produces the four LaTeX section files an auditor uploads into the Nethermind Overleaf template at the end of an engagement. It runs from the GitHub-synced issues (the report's source of truth), after findings have been pushed via /sync-issues.
9
+ This skill produces the LaTeX section files an auditor assembles into the Nethermind Overleaf report template at the end of an engagement. It runs from the GitHub-synced issues (the report's source of truth), after findings have been pushed via /sync-issues, and reuses the analysis Hex already produced during /init-audit (`overview.md`, `stats.json`, `access-control.json`, `deps.json`).
10
10
 
11
11
  ## What it writes
12
12
 
13
- Four `.txt` files in `<output_dir>/overleaf/`:
13
+ Seven report sections in `<output_dir>/report/`, each emitted in **two forms** (see "Output convention"):
14
14
 
15
- 1. `executive_summary.txt` — `\section{Executive Summary}` body with project synopsis, severity histogram, status histogram, summary table of audit metadata.
16
- 2. `audited_files.txt` — `\section{Audited Files}` body with a LaTeX table of in-scope files (LoC, comments, ratio, blank, total).
17
- 3. `summary_of_findings.txt` — `\section{Summary of Issues}` body with hyperlinked finding rows.
18
- 4. `findings.txt` — `\section{Issues}` body with one `\subsection{[Sev] title}\label{issue:N}` per synced finding, including description, code blocks, recommendation, status, client update.
15
+ 1. **Executive Summary** (§1) — project synopsis, severity histogram, status histogram, summary table of audit metadata.
16
+ 2. **Audited Files** (§2) — a LaTeX table of in-scope files (LoC, comments, ratio, blank, total).
17
+ 3. **Summary of Issues** (§3) — hyperlinked finding rows.
18
+ 4. **System Overview** (§4) — descriptive protocol architecture: components, actors & roles, per-module or per-flow subsections. Built from `overview.md` + access-control/deps analysis.
19
+ 5. **Issues** (§6) — one `\subsection{[Sev] title}\label{issue:N}` per synced finding, with description, code blocks, recommendation, status, client update.
20
+ 6. **Documentation Evaluation** (§7) — a `tcolorbox` remarks paragraph about the client's documentation.
21
+ 7. **Test Suite Evaluation** (§8) — coverage summary and automated-tooling note, generated from `stats.json.test_coverage`.
19
22
 
20
- Output is plain `.txt` so the auditor pastes content into the matching Overleaf template slots. The skill does NOT compile LaTeX itself.
23
+ The skill does NOT compile LaTeX itself. Sections §5 (risk methodology) and §9 (conclusion) are static in the Overleaf template and are not generated here.
24
+
25
+ ## Output convention
26
+
27
+ Every section is generated **once** as a LaTeX string, then written to two paths in `<output_dir>/report/`:
28
+
29
+ | Section | `.txt` (dashboard viewer / copy-paste) | `.tex` (`\input{}` into `main.tex`) |
30
+ |---|---|---|
31
+ | §1 Executive Summary | `executive_summary.txt` | `01-executive-summary.tex` |
32
+ | §2 Audited Files | `audited_files.txt` | `02-audited-files.tex` |
33
+ | §3 Summary of Issues | `summary_of_findings.txt` | `03-summary-of-findings.tex` |
34
+ | §4 System Overview | `system_overview.txt` | `04-system-overview.tex` |
35
+ | §6 Issues | `findings.txt` | `06-issues.tex` |
36
+ | §7 Documentation Evaluation | `documentation_eval.txt` | `07-documentation-eval.tex` |
37
+ | §8 Test Suite Evaluation | `test_suite.txt` | `08-test-suite.tex` |
38
+
39
+ The `.txt` and `.tex` bodies are byte-identical. The `.txt` copies power the dashboard `/report` viewer (with copy buttons); the `.tex` copies drop straight into an Overleaf `main.tex` that `\input`s the numbered files.
40
+
41
+ All prose written by this skill must follow the project writing style (no em dashes, "Consider..." recommendations, banned-word list in the project CLAUDE.md).
21
42
 
22
43
  ## Phase 0 — Gather report metadata
23
44
 
@@ -31,12 +52,14 @@ Read `<output_dir>/config.json`. Look under `settings.report.*` for:
31
52
  - `audit_type` — defaults to `Security Review`.
32
53
  - `doc_assessment` — `High` / `Medium` / `Low`.
33
54
  - `test_assessment` — `High` / `Medium` / `Low`.
55
+ - `kickoff_call` — optional focus note for the §7 kick-off sentence (e.g. "with a focus on the upgrade changes"). Empty means omit the kick-off sentence.
56
+ - `client_availability` — optional free-text for the §7 closing sentence. Empty falls back to the standard availability sentence.
34
57
 
35
58
  For each missing field, use **AskUserQuestion** to prompt the auditor. After collection, persist all values back to `config.json` under `settings.report.*` so re-runs don't re-prompt.
36
59
 
37
60
  If `repository_url` is not set, also offer to derive it from the project's git remote (`git -C <project_dir> remote get-url origin`).
38
61
 
39
- ## Phase 0.5 — Require synced issues (GitHub is the source of truth)
62
+ ## Phase 1 — Require synced issues (GitHub is the source of truth)
40
63
 
41
64
  The report is generated **only** from issues that are synced to GitHub (`tracking.status === "synced"`). GitHub is the single source of truth for finding content; the local Potential/Verified columns are a staging area.
42
65
 
@@ -44,7 +67,7 @@ Before doing anything else:
44
67
  - If `settings.github.repo` is not set, **abort**: "The report is generated from GitHub-synced issues. Configure `settings.github.repo` (or pass `--github-repo` to `hex init`) and run `/sync-issues` first."
45
68
  - If there are zero `synced` findings, **abort**: "No synced issues found. Verify findings, then run `/sync-issues` to push them to GitHub before generating the report."
46
69
 
47
- ## Phase 1 — Compute the histograms and counts
70
+ ## Phase 2 — Compute the histograms and counts
48
71
 
49
72
  Read `<output_dir>/findings.json` and `<output_dir>/tracking.json`.
50
73
 
@@ -62,9 +85,9 @@ Resolution histogram (count of synced findings per `resolution` field):
62
85
  ```
63
86
  Findings without a `resolution` field count as `Unresolved`.
64
87
 
65
- ## Phase 2 — Build the protocol synopsis paragraph
88
+ ## Phase 3 — Build the protocol synopsis paragraph
66
89
 
67
- Read `<output_dir>/overview.md`. Produce a roughly half-page (~120-180 words) plain-language summary of what the protocol does and the security-relevant mechanics. This becomes the second paragraph of `executive_summary.txt`. Match the tone of the Nethermind example:
90
+ Read `<output_dir>/overview.md`. Produce a roughly half-page (~120-180 words) plain-language summary of what the protocol does and the security-relevant mechanics. This becomes the second paragraph of the Executive Summary. Match the tone of the Nethermind example:
68
91
 
69
92
  - Open with one sentence on the project's purpose and the in-scope contract(s).
70
93
  - Use a short `\begin{itemize}[leftmargin=*,itemsep=4pt] ... \end{itemize}` to list 2-3 of the security-relevant axes (e.g., access-control gates, asset-flow surfaces, upgradeability boundaries).
@@ -75,7 +98,9 @@ Style hints:
75
98
  - Bold key terms with `\textbf{...}`.
76
99
  - No code blocks in this paragraph — those belong in the per-finding sections.
77
100
 
78
- ## Phase 3 — Write `executive_summary.txt`
101
+ ## Phase 4 — Write the Executive Summary (§1)
102
+
103
+ Write to `executive_summary.txt` **and** `01-executive-summary.tex`.
79
104
 
80
105
  ```latex
81
106
  \pagebreak \vspace*{0cm}
@@ -84,7 +109,7 @@ Style hints:
84
109
  \black
85
110
  This document presents the results of the security review conducted by \href{https://www.nethermind.io/smart-contract-audits}{Nethermind Security} for <PROJECT_NAME>'s <SCOPE_DESCRIPTION>.
86
111
 
87
- <AI-GENERATED PROTOCOL SYNOPSIS PARAGRAPH FROM PHASE 2>
112
+ <AI-GENERATED PROTOCOL SYNOPSIS PARAGRAPH FROM PHASE 3>
88
113
 
89
114
  \textbf{The audit comprises <TOTAL_NSLOC>} lines of Solidity code. \textbf{The audit was performed using} (a)~manual analysis of the codebase, and (b)~automated analysis tools.
90
115
 
@@ -143,7 +168,7 @@ The issues are summarized in Fig.~1.
143
168
  \textbf{Final Commit} & \href{<REPOSITORY_URL>/commit/<FINAL_COMMIT>}{<FINAL_COMMIT_SHORT>} \\
144
169
  \textbf{Documentation Assessment} & <DOC_ASSESSMENT> \\
145
170
  \textbf{Test Suite Assessment} & <TEST_ASSESSMENT> \\ \hline
146
- \end{longtable>
171
+ \end{longtable}
147
172
  \color{black}
148
173
  ```
149
174
 
@@ -157,7 +182,9 @@ Substitutions:
157
182
  - `<INITIAL_COMMIT_SHORT>` ← first 7 chars of the commit hash.
158
183
  - `<FIRST_SCOPE_FILE>` ← relative path of the first file in `config.json.project.scope` (for the initial commit hyperref, which the template anchors to a specific file).
159
184
 
160
- ## Phase 4 — Write `audited_files.txt`
185
+ ## Phase 5 — Write the Audited Files table (§2)
186
+
187
+ Write to `audited_files.txt` **and** `02-audited-files.tex`.
161
188
 
162
189
  Compute per-file line counts from each scope file. For each in-scope file in `config.json.project.scope`:
163
190
 
@@ -200,9 +227,11 @@ Render the table:
200
227
  - Number rows sequentially `1, 2, 3 ...`.
201
228
  - Aggregate ratio = `round(sum-comments * 100 / max(sum-code, 1), 0)`.
202
229
 
203
- ## Phase 5 — Write `summary_of_findings.txt`
230
+ ## Phase 6 — Write the Summary of Issues (§3)
204
231
 
205
- For each synced finding in severity-sorted order (Critical → Info), assign a sequential `issue:N` label starting at `issue:0`. This same label is used in `findings.txt` for the `\hyperref`.
232
+ Write to `summary_of_findings.txt` **and** `03-summary-of-findings.tex`.
233
+
234
+ For each synced finding in severity-sorted order (Critical → Info), assign a sequential `issue:N` label starting at `issue:0`. This same label is used in the Issues section for the `\hyperref`.
206
235
 
207
236
  ```latex
208
237
  %\pagebreak \vspace*{0cm}
@@ -228,13 +257,59 @@ For each synced finding in severity-sorted order (Critical → Info), assign a s
228
257
  ```
229
258
 
230
259
  - `<N>` is the 1-based row counter.
231
- - `<I>` matches the `\label{issue:N}` index used in `findings.txt`.
260
+ - `<I>` matches the `\label{issue:N}` index used in the Issues section.
232
261
  - `<Severity-display>` maps `Info` → `Info`, others use their name as-is.
233
262
  - `<Resolution-display>` maps the `resolution` field directly (`Fixed`, `Acknowledged`, `Mitigated`, `Not Fixed`); blank/`Unresolved` shows `Unresolved`.
234
263
 
235
- ## Phase 6 — Write `findings.txt`
264
+ ## Phase 7 — Write the System Overview (§4)
265
+
266
+ Write to `system_overview.txt` **and** `04-system-overview.tex`.
236
267
 
237
- For each synced finding in the same order (severity-sorted), render one subsection. Use the index `i` (0-based) matching `summary_of_findings.txt`.
268
+ Primary source: `<output_dir>/overview.md` (produced by /init-audit — it already carries an intro, a `## Key Contracts` table, `## External Dependencies`, and `## Architecture Notes`). Enrich the actors/roles material from `<output_dir>/access-control.json` (roles, modifiers, gated functions) and cross-contract relationships from `<output_dir>/deps.json`.
269
+
270
+ **If `overview.md` is absent, abort**: "System Overview needs `<output_dir>/overview.md`. Run `/init-audit` first, then re-run `/generate-report`."
271
+
272
+ This section is descriptive only: no vulnerability observations (those live in Issues), no findings, no severities.
273
+
274
+ Structure the LaTeX:
275
+
276
+ ```latex
277
+ \pagebreak \vspace*{0cm}
278
+ \sectioncolor
279
+ \section{System Overview}
280
+ \black
281
+
282
+ <intro paragraph(s): what the protocol does; if scope is a subset, focus on scope. State what each in-scope contract inherits from using \texttt{}.>
283
+
284
+ <a short paragraph or itemize listing the main components: one line each — \texttt{ContractName}: responsibility.>
285
+
286
+ \subsectioncolor
287
+ \subsection{Actors and Roles}
288
+ \black
289
+ <bullet list of actors, their permissions, the functions they can trigger, trust level. If there is a formal access-control system, name the library and explain the role model, using \texttt{ROLE\_NAME} for role constants.>
290
+
291
+ \subsectioncolor
292
+ \subsection{<Module or Flow Name>}
293
+ \black
294
+ <one subsection per module (Option A) or per flow (Option B). Choose per gauss's rule: if explaining each contract independently makes the system clear, use per-module; if the contracts only make sense together in motion, use per-flow. For each: entry points as a bullet list (functionName: one-line description), main internal flows, key state owned/mutated, how it interfaces with other modules. Use \begin{minted}[linenos]{solidity} ... \end{minted} for signature-only snippets when a flow depends on the parameters. Do not include full function bodies.>
295
+
296
+ ... (repeat subsections) ...
297
+ ```
298
+
299
+ Formatting rules (from gauss `to-latex.md`):
300
+ - Each `\subsection{}` is preceded by `\subsectioncolor` and followed by `\black`. Subsection titles use title case.
301
+ - Contract / function / variable / interface names in `\texttt{}`. Hex values and constants in `\texttt{}`. Standard identifiers (ERC-1271, UUPS, etc.) as-is.
302
+ - Do not start a subsection with a bullet list — add an introductory sentence first.
303
+ - For a genuinely central formula, use an `equation` block. Do not do this for every calculation.
304
+ - Keep it under ~1 page for simple systems, up to ~2 pages for complex ones.
305
+
306
+ Apply the markdown → LaTeX conversion rules (below) to any prose carried over from `overview.md`.
307
+
308
+ ## Phase 8 — Write the Issues section (§6)
309
+
310
+ Write to `findings.txt` **and** `06-issues.tex`.
311
+
312
+ For each synced finding in the same order (severity-sorted), render one subsection. Use the index `i` (0-based) matching the Summary of Issues.
238
313
 
239
314
  ```latex
240
315
  \pagebreak \vspace*{0cm}
@@ -297,7 +372,7 @@ Apply to `description`, `recommendation`, and `update_from_client` (in that orde
297
372
 
298
373
  End list items with `;` (replace trailing `.` with `;`). Last item still ends with `;`.
299
374
 
300
- The markdown-to-LaTeX logic matches the spirit of the Python script `create-section-findings.py` referenced by the auditor — port that semantically into the skill's instructions rather than calling it.
375
+ These conversion rules match the spirit of the Python script `create-section-findings.py` referenced by the auditor — port that semantically into these instructions rather than calling it. The same rules apply to the System Overview prose in Phase 7.
301
376
 
302
377
  ### Severity-display mapping
303
378
  - `Critical` → `Critical`
@@ -306,16 +381,93 @@ The markdown-to-LaTeX logic matches the spirit of the Python script `create-sect
306
381
  - `Low` → `Low`
307
382
  - `Info` → `Info` (the Nethermind template uses `Info` in the subsection headers and `Informational` in the histogram caption)
308
383
 
309
- ## Phase 7 — Final report
384
+ ## Phase 9 — Write the Documentation Evaluation (§7)
385
+
386
+ Write to `documentation_eval.txt` **and** `07-documentation-eval.tex`.
387
+
388
+ Determine what documentation was available:
389
+ - NatSpec presence: infer from `stats.json.totals.comment_lines` (a high comment ratio suggests NatSpec) and by skimming 2-3 in-scope files from `config.json.project.scope`.
390
+ - README / external docs: `config.json.project.docs_url` if set, and any README in the repo describing the in-scope system.
391
+ - Kick-off call: only if `settings.report.kickoff_call` is set (append its text as the focus).
392
+ - Client availability: `settings.report.client_availability` if set, otherwise the standard closing sentence.
393
+
394
+ Emit the exact `tcolorbox` wrapper (from gauss `documentation-eval.md`):
395
+
396
+ ```latex
397
+ \pagebreak \vspace*{0cm}
398
+ \sectioncolor
399
+ \section{Documentation Evaluation}
400
+ \black
401
+
402
+ \begin{tcolorbox}[colback=blue!5,colframe=blue!50!black!70,title=Remarks about <CLIENT> <PRODUCT> documentation]
403
+ <one paragraph describing the documentation actually provided — NatSpec, README/docs, and what the README covers (high-level overview, objectives, architecture). Only mention what exists and is relevant to the code in scope.>
404
+ \vspace{0.3em}
405
+
406
+ <kick-off call sentence, only if settings.report.kickoff_call is set. Example: "Additionally, the <CLIENT> team provided a general overview of the system during the kick-off call <kickoff_call>.">
407
+ \vspace{0.3em}
408
+
409
+ <closing sentence on team availability. Use settings.report.client_availability if set, else: "Moreover, the team addressed all questions and concerns raised by the Nethermind Security team, providing valuable insights and a comprehensive understanding of the project's technical aspects.">
410
+ \end{tcolorbox}
411
+ ```
412
+
413
+ - `<CLIENT>` ← client/org name (derive from `repository_url` org or `project.name`).
414
+ - `<PRODUCT>` ← `config.json.project.name`.
415
+ - Do not include full file paths when referring to a file — use the basename.
416
+ - Keep it factual: do not claim documentation exists that the analysis does not support.
417
+
418
+ ## Phase 10 — Write the Test Suite Evaluation (§8)
419
+
420
+ Write to `test_suite.txt` **and** `08-test-suite.tex`.
421
+
422
+ Read `stats.json.test_coverage`.
423
+
424
+ If `test_coverage.status === "available"`:
425
+ - Report `overall_line_pct` and `overall_branch_pct`.
426
+ - Render a per-contract coverage table from `test_coverage.per_contract[]` (`contract`, `line_pct`, `branch_pct`).
427
+
428
+ If `test_coverage.status !== "available"` (`failed` / `skipped` / null):
429
+ - State plainly that automated coverage could not be collected (include `failure_reason` if present), and describe the test suite qualitatively, falling back to the `settings.report.test_assessment` grade.
430
+
431
+ Always close with an automated-tools paragraph: manual analysis plus automated tooling. If `config.json.settings.ai.auditagent_scan_id` is set, name Nethermind AuditAgent explicitly.
432
+
433
+ ```latex
434
+ \pagebreak \vspace*{0cm}
435
+ \sectioncolor
436
+ \section{Test Suite Evaluation}
437
+ \black
438
+
439
+ <paragraph on the test suite: overall line/branch coverage, or the reason coverage is unavailable, plus a qualitative read tied to the Test Suite Assessment grade.>
440
+
441
+ \begin{table}[H]
442
+ \centering
443
+ \begin{footnotesize}
444
+ \begin{tabular}{|p{9cm}|p{2cm}|p{2cm}|}
445
+ \hline
446
+ \textbf{Contract} & \textbf{Line \%} & \textbf{Branch \%} \\ \hline
447
+ \texttt{<contract>} & <line_pct>\% & <branch_pct>\% \\ \hline
448
+ ...
449
+ \end{tabular}
450
+ \end{footnotesize}
451
+ \end{table}
452
+
453
+ <automated-tools paragraph: manual review + automated analysis; name Nethermind AuditAgent if a scan id is configured.>
454
+ ```
455
+
456
+ (Omit the coverage table entirely when coverage is unavailable.)
457
+
458
+ ## Phase 11 — Final report
310
459
 
311
- After writing all four files, print:
460
+ After writing all sections, print:
312
461
 
313
462
  ```
314
- Wrote 4 LaTeX section files to <output_dir>/overleaf/:
315
- - executive_summary.txt (<N> bytes)
316
- - audited_files.txt (<N> bytes)
317
- - summary_of_findings.txt (<N> bytes)
318
- - findings.txt (<N> bytes)
463
+ Wrote 7 report sections (14 files) to <output_dir>/report/:
464
+ §1 Executive Summary executive_summary.txt 01-executive-summary.tex
465
+ §2 Audited Files audited_files.txt 02-audited-files.tex
466
+ §3 Summary of Issues summary_of_findings.txt 03-summary-of-findings.tex
467
+ §4 System Overview system_overview.txt 04-system-overview.tex
468
+ §6 Issues findings.txt 06-issues.tex
469
+ §7 Documentation Eval documentation_eval.txt 07-documentation-eval.tex
470
+ §8 Test Suite Evaluation test_suite.txt 08-test-suite.tex
319
471
 
320
472
  Synced findings included: <count>
321
473
  Critical=<C> High=<H> Medium=<M> Low=<L> Info=<I>
@@ -323,12 +475,14 @@ Synced findings included: <count>
323
475
  Status distribution:
324
476
  Fixed=<F> Acknowledged=<A> Mitigated=<MI> Unresolved=<U>
325
477
 
326
- Upload these into your Overleaf project's Section 1 / 2 / 3 / 6 slots respectively.
478
+ Read the sections on the dashboard's /report page, or \input the NN-*.tex files into your
479
+ Nethermind Overleaf main.tex. Sections 5 (risk methodology) and 9 (conclusion) are template-static.
327
480
  ```
328
481
 
329
482
  ## What this skill does NOT do
330
483
 
331
484
  - Does not compile LaTeX (no `pdflatex` invocation).
332
- - Does not modify any file outside `<output_dir>/overleaf/` and (with permission) `config.json` under `settings.report.*`.
485
+ - Does not generate §5 (risk rating methodology) or §9 (conclusion) — those are static in the Overleaf template.
486
+ - Does not modify any file outside `<output_dir>/report/` and (with permission) `config.json` under `settings.report.*`.
333
487
  - Does not push to Overleaf, GitHub, or any remote — output is local plain-text.
334
488
  - Does not include `rejected`, `duplicate`, `pending_validation`, `unverified`, or `verified`-but-not-yet-synced findings. Only `synced` (on GitHub) makes the cut.
@@ -25,7 +25,7 @@ Ask the auditor for:
25
25
  - **Commit hash** — the specific commit being audited (default: HEAD).
26
26
  - **Chain** — target chain (default: ethereum).
27
27
  - **Documentation URL** — if available.
28
- - **GitHub repo** (optional) — the `owner/repo` the audit's findings sync to (e.g. `nethermind/audit-vaultx`). Pass it to `hex init --github-repo` so `/sync-issues` and `/generate-overleaf` work later. Leave blank if the engagement isn't using GitHub.
28
+ - **GitHub repo** (optional) — the `owner/repo` the audit's findings sync to (e.g. `nethermind/audit-vaultx`). Pass it to `hex init --github-repo` so `/sync-issues` and `/generate-report` work later. Leave blank if the engagement isn't using GitHub.
29
29
 
30
30
  ### 1.2 Audit dependencies (BEFORE compiling)
31
31
 
@@ -10,7 +10,7 @@ Hex's GitHub Issues integration. Hex never authenticates with GitHub — you aut
10
10
 
11
11
  ## The model: GitHub is the source of truth, identity is the issue number
12
12
 
13
- Once an issue is on GitHub it is **read-only in Hex** (status `synced`, locked on the board). Edits — severity, description, recommendation, status — happen on GitHub; this skill pulls them back into the local finding. `/generate-overleaf` reports **only** from synced issues.
13
+ Once an issue is on GitHub it is **read-only in Hex** (status `synced`, locked on the board). Edits — severity, description, recommendation, status — happen on GitHub; this skill pulls them back into the local finding. `/generate-report` reports **only** from synced issues.
14
14
 
15
15
  **Identity is the GitHub issue number `#N`.** There is no hidden footer in the issue body (auditors create issues by hand, so a footer can't be relied on). Reconciliation matches a local finding to the issue number it has stored in `github.issue_number`. The body is exactly the five-field template, nothing hidden.
16
16
 
@@ -61,4 +61,4 @@ Validated N Potential issues:
61
61
  → Left for review (uncertain): U
62
62
  ```
63
63
 
64
- Remind the auditor of the next steps: `/sync-issues` to push the Verified findings to GitHub, then `/generate-overleaf` for the report.
64
+ Remind the auditor of the next steps: `/sync-issues` to push the Verified findings to GitHub, then `/generate-report` for the report.
@@ -204,4 +204,4 @@ The board reflects the new state automatically (the dashboard watches `tracking.
204
204
 
205
205
  - Move on to the next Potential card.
206
206
  - Run `/sync-issues` to push the newly Verified finding to GitHub if `settings.github.repo` is configured.
207
- - Run `/generate-overleaf` once all verifications are done, to produce the LaTeX report sections.
207
+ - Run `/generate-report` once all verifications are done, to produce the LaTeX report sections.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hex-audit",
3
- "version": "0.5.6",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "CLI toolkit for Solidity smart contract auditors",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- (()=>{var e={};e.id=529,e.ids=[529],e.modules={7849:e=>{"use strict";e.exports=require("next/dist/client/components/action-async-storage.external")},2934:e=>{"use strict";e.exports=require("next/dist/client/components/action-async-storage.external.js")},5403:e=>{"use strict";e.exports=require("next/dist/client/components/request-async-storage.external")},4580:e=>{"use strict";e.exports=require("next/dist/client/components/request-async-storage.external.js")},4749:e=>{"use strict";e.exports=require("next/dist/client/components/static-generation-async-storage.external")},5869:e=>{"use strict";e.exports=require("next/dist/client/components/static-generation-async-storage.external.js")},399:e=>{"use strict";e.exports=require("next/dist/compiled/next-server/app-page.runtime.prod.js")},7561:e=>{"use strict";e.exports=require("node:fs")},9411:e=>{"use strict";e.exports=require("node:path")},1017:e=>{"use strict";e.exports=require("path")},7310:e=>{"use strict";e.exports=require("url")},7547:(e,t,r)=>{"use strict";r.r(t),r.d(t,{GlobalError:()=>i.a,__next_app__:()=>x,originalPathname:()=>u,pages:()=>c,routeModule:()=>m,tree:()=>d}),r(4636),r(819),r(2874);var a=r(7105),s=r(5265),n=r(157),i=r.n(n),o=r(4665),l={};for(let e in o)0>["default","tree","pages","GlobalError","originalPathname","__next_app__","routeModule"].indexOf(e)&&(l[e]=()=>o[e]);r.d(t,l);let d=["",{children:["overleaf",{children:["__PAGE__",{},{page:[()=>Promise.resolve().then(r.bind(r,4636)),"/home/dx/Work/hex/dashboard/app/overleaf/page.tsx"]}]},{metadata:{icon:[async e=>(await Promise.resolve().then(r.bind(r,2950))).default(e)],apple:[],openGraph:[],twitter:[],manifest:void 0}}]},{layout:[()=>Promise.resolve().then(r.bind(r,819)),"/home/dx/Work/hex/dashboard/app/layout.tsx"],"not-found":[()=>Promise.resolve().then(r.t.bind(r,2874,23)),"next/dist/client/components/not-found-error"],metadata:{icon:[async e=>(await Promise.resolve().then(r.bind(r,2950))).default(e)],apple:[],openGraph:[],twitter:[],manifest:void 0}}],c=["/home/dx/Work/hex/dashboard/app/overleaf/page.tsx"],u="/overleaf/page",x={require:r,loadChunk:()=>Promise.resolve()},m=new a.AppPageRouteModule({definition:{kind:s.x.APP_PAGE,page:"/overleaf/page",pathname:"/overleaf",bundlePath:"",filename:"",appPaths:[]},userland:{loaderTree:d}})},6178:(e,t,r)=>{Promise.resolve().then(r.bind(r,6131))},6131:(e,t,r)=>{"use strict";r.d(t,{OverleafClient:()=>i});var a=r(9899),s=r(5507);let n=[{key:"executive_summary",label:"Executive Summary",file:"executive_summary.txt"},{key:"audited_files",label:"Audited Files",file:"audited_files.txt"},{key:"summary_of_findings",label:"Summary of Issues",file:"summary_of_findings.txt"},{key:"findings",label:"Issues",file:"findings.txt"}];function i({sections:e}){let[t,r]=(0,s.useState)("executive_summary"),[i,o]=(0,s.useState)(!1),l=e[t],d=async()=>{if(l)try{await navigator.clipboard.writeText(l),o(!0),setTimeout(()=>o(!1),1500)}catch{}};return(0,a.jsxs)("div",{children:[(0,a.jsxs)("header",{className:"mb-6",children:[a.jsx("h1",{className:"text-title font-semibold text-text-primary",children:"Overleaf"}),(0,a.jsxs)("p",{className:"mt-1 text-body text-text-secondary",children:["LaTeX report sections from ",a.jsx("span",{className:"font-mono text-caption",children:".hex/overleaf/"}),". Copy each into the matching slot of the Nethermind Overleaf template."]})]}),a.jsx("div",{className:"mb-4 flex flex-wrap gap-1.5",children:n.map(s=>{let n=s.key===t,i=!!e[s.key];return a.jsx("button",{type:"button",onClick:()=>r(s.key),className:`rounded-md px-3 py-1.5 text-caption font-medium ${n?"bg-accent text-surface-0":"bg-surface-2 text-text-secondary hover:text-text-primary"} ${i?"":"opacity-50"}`,children:s.label},s.key)})}),(0,a.jsxs)("div",{className:"rounded-lg border border-border-subtle bg-surface-1",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between border-b border-border-subtle px-4 py-2.5",children:[a.jsx("span",{className:"font-mono text-caption text-text-tertiary",children:n.find(e=>e.key===t)?.file}),a.jsx("button",{type:"button",onClick:d,disabled:!l,className:"rounded-md border border-border-default px-2.5 py-1 text-caption text-text-secondary hover:bg-surface-2 hover:text-text-primary disabled:opacity-50",children:i?"Copied!":"Copy"})]}),l?a.jsx("pre",{className:"max-h-[70vh] overflow-auto p-4 font-mono text-caption leading-relaxed text-text-secondary whitespace-pre-wrap break-words",children:l}):(0,a.jsxs)("p",{className:"p-4 text-body text-text-tertiary",children:["This section has not been generated yet. Run"," ",a.jsx("span",{className:"font-mono text-caption",children:"/generate-overleaf"}),"."]})]})]})}},4636:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>x,dynamic:()=>u});var a=r(5023),s=r(1720),n=r(446),i=r(2772);let o=(0,i.createProxy)(String.raw`/home/dx/Work/hex/dashboard/app/overleaf/OverleafClient.tsx`),{__esModule:l,$$typeof:d}=o;o.default;let c=(0,i.createProxy)(String.raw`/home/dx/Work/hex/dashboard/app/overleaf/OverleafClient.tsx#OverleafClient`),u="force-dynamic";function x(){let e={executive_summary:(0,s.ws)("overleaf/executive_summary.txt"),audited_files:(0,s.ws)("overleaf/audited_files.txt"),summary_of_findings:(0,s.ws)("overleaf/summary_of_findings.txt"),findings:(0,s.ws)("overleaf/findings.txt")};return Object.values(e).some(Boolean)?a.jsx(c,{sections:e}):(0,a.jsxs)("div",{children:[(0,a.jsxs)("header",{className:"mb-6",children:[a.jsx("h1",{className:"text-title font-semibold text-text-primary",children:"Overleaf"}),a.jsx("p",{className:"mt-1 text-body text-text-secondary",children:"LaTeX report sections, ready to paste into the Nethermind Overleaf template."})]}),a.jsx(n.v,{command:"/generate-overleaf"})]})}},446:(e,t,r)=>{"use strict";r.d(t,{v:()=>s});var a=r(5023);function s({command:e}){return(0,a.jsxs)("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)"},children:[a.jsx("svg",{className:"mb-4 h-12 w-12 text-text-tertiary",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:a.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",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"})}),a.jsx("h3",{className:"mb-2 text-heading font-medium text-text-primary",children:"Data not yet generated"}),a.jsx("p",{className:"mb-4 text-body text-text-secondary",children:"Run the following command to generate this data:"}),a.jsx("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)"},children:e})]})}},1720:(e,t,r)=>{"use strict";r.d(t,{ki:()=>m,ZN:()=>p,J1:()=>f,gn:()=>c,ws:()=>u,V9:()=>h,au:()=>x});var a=r(7561),s=r.n(a),n=r(9411),i=r.n(n);let o=[".hex",".solaudit","solaudit-output"];function l(e){return e.replace(/\\/g,"/")}function d(){try{let e=function(e=process.cwd()){let t=i().resolve(e);for(;;){let e=function(e){for(let t of[...o.map(t=>i().join(e,t,"config.json")),i().join(e,"config.json")])if(s().existsSync(t))return l(t);return null}(t);if(e)return l(i().dirname(e));let r=i().dirname(t);if(r===t)return null;t=r}}(process.cwd());if(e)return e}catch{}return i().join(process.cwd(),".hex")}function c(e){try{let t=i().join(d(),e),r=s().readFileSync(t,"utf-8");return JSON.parse(r)}catch{return null}}function u(e){try{let t=i().join(d(),e);return s().readFileSync(t,"utf-8")}catch{return null}}function x(e,t){let r=i().join(d(),e);s().writeFileSync(r,JSON.stringify(t,null,2),"utf-8")}function m(e){try{let t=i().join(d(),e);return s().existsSync(t)}catch{return!1}}function p(){return d()}function f(e){try{let t=i().join(d(),e);if(!s().existsSync(t))return[];return s().readdirSync(t,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name)}catch{return[]}}function h(e){try{let t=i().join(d(),e),r=s().readFileSync(t,"utf-8");return JSON.parse(r)}catch{return null}}},2950:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>s});var a=r(1645);let s=e=>[{type:"image/svg+xml",sizes:"any",url:(0,a.fillMetadataSegment)(".",e.params,"icon.svg")+"?83fa4bf1ef0d214d"}]}};var t=require("../../webpack-runtime.js");t.C(e);var r=e=>t(t.s=e),a=t.X(0,[916,649,645,530],()=>r(7547));module.exports=a})();
@@ -1 +0,0 @@
1
- globalThis.__RSC_MANIFEST=(globalThis.__RSC_MANIFEST||{});globalThis.__RSC_MANIFEST["/overleaf/page"]={"moduleLoading":{"prefix":"/_next/","crossOrigin":null},"ssrModuleMapping":{"9":{"*":{"id":"6131","name":"*","chunks":[],"async":false}},"1076":{"*":{"id":"9323","name":"*","chunks":[],"async":false}},"1187":{"*":{"id":"7918","name":"*","chunks":[],"async":false}},"1447":{"*":{"id":"5915","name":"*","chunks":[],"async":false}},"2024":{"*":{"id":"2857","name":"*","chunks":[],"async":false}},"2198":{"*":{"id":"9915","name":"*","chunks":[],"async":false}},"3297":{"*":{"id":"1611","name":"*","chunks":[],"async":false}},"3362":{"*":{"id":"5289","name":"*","chunks":[],"async":false}},"3443":{"*":{"id":"7406","name":"*","chunks":[],"async":false}},"3719":{"*":{"id":"526","name":"*","chunks":[],"async":false}},"4595":{"*":{"id":"1388","name":"*","chunks":[],"async":false}},"5268":{"*":{"id":"3817","name":"*","chunks":[],"async":false}},"5276":{"*":{"id":"820","name":"*","chunks":[],"async":false}},"7063":{"*":{"id":"618","name":"*","chunks":[],"async":false}},"7498":{"*":{"id":"696","name":"*","chunks":[],"async":false}},"7542":{"*":{"id":"9555","name":"*","chunks":[],"async":false}},"7701":{"*":{"id":"8530","name":"*","chunks":[],"async":false}},"7780":{"*":{"id":"8664","name":"*","chunks":[],"async":false}},"9487":{"*":{"id":"6844","name":"*","chunks":[],"async":false}},"9690":{"*":{"id":"2204","name":"*","chunks":[],"async":false}},"9745":{"*":{"id":"4136","name":"*","chunks":[],"async":false}},"9922":{"*":{"id":"8033","name":"*","chunks":[],"async":false}}},"edgeSSRModuleMapping":{},"clientModules":{"/home/dx/Work/hex/node_modules/next/dist/client/components/app-router.js":{"id":5268,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/app-router.js":{"id":5268,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/client-page.js":{"id":1076,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/client-page.js":{"id":1076,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/error-boundary.js":{"id":9690,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/error-boundary.js":{"id":9690,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/layout-router.js":{"id":5276,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/layout-router.js":{"id":5276,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/not-found-boundary.js":{"id":1447,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/not-found-boundary.js":{"id":1447,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/components/render-from-template-context.js":{"id":3297,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/components/render-from-template-context.js":{"id":3297,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/globals.css":{"id":3812,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/dashboard/components/CommandPalette.tsx":{"id":2198,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/dashboard/components/DashboardLayout.tsx":{"id":1187,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/node_modules/next-themes/dist/index.mjs":{"id":4595,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/node_modules/next/font/google/target.css?{\"path\":\"app/layout.tsx\",\"import\":\"Manrope\",\"arguments\":[{\"subsets\":[\"latin\"],\"variable\":\"--font-sans\",\"display\":\"swap\"}],\"variableName\":\"manrope\"}":{"id":8414,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/node_modules/next/font/google/target.css?{\"path\":\"app/layout.tsx\",\"import\":\"JetBrains_Mono\",\"arguments\":[{\"subsets\":[\"latin\"],\"variable\":\"--font-mono\",\"display\":\"swap\"}],\"variableName\":\"jetbrainsMono\"}":{"id":5256,"name":"*","chunks":["7498","static/chunks/7498-ea83cb9e30ec5491.js","3185","static/chunks/app/layout-a95b696089e278c3.js"],"async":false},"/home/dx/Work/hex/dashboard/app/diagram/page.tsx":{"id":3719,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/flows/page.tsx":{"id":3443,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/access/AccessClient.tsx":{"id":9745,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/calls/CallsClient.tsx":{"id":3362,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/notes/NotesClient.tsx":{"id":2024,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/overleaf/OverleafClient.tsx":{"id":9,"name":"*","chunks":["529","static/chunks/app/overleaf/page-bcea12a80c97b92f.js"],"async":false},"/home/dx/Work/hex/dashboard/app/functions/FunctionsClient.tsx":{"id":7780,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/conformance/ConformanceTable.tsx":{"id":7542,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/stats/StatsClient.tsx":{"id":9922,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/progress/ProgressClient.tsx":{"id":7701,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/app/issues/IssuesBoardClient.tsx":{"id":7063,"name":"*","chunks":[],"async":false},"/home/dx/Work/hex/dashboard/components/MarkdownRenderer.tsx":{"id":9487,"name":"*","chunks":["7397","static/chunks/7397-f6f4dddc7a20bfc1.js","7498","static/chunks/7498-ea83cb9e30ec5491.js","1931","static/chunks/app/page-24bac51dfe007c66.js"],"async":false},"/home/dx/Work/hex/node_modules/next/dist/client/link.js":{"id":7498,"name":"*","chunks":["7397","static/chunks/7397-f6f4dddc7a20bfc1.js","7498","static/chunks/7498-ea83cb9e30ec5491.js","1931","static/chunks/app/page-24bac51dfe007c66.js"],"async":false},"/home/dx/Work/hex/node_modules/next/dist/esm/client/link.js":{"id":7498,"name":"*","chunks":["7397","static/chunks/7397-f6f4dddc7a20bfc1.js","7498","static/chunks/7498-ea83cb9e30ec5491.js","1931","static/chunks/app/page-24bac51dfe007c66.js"],"async":false}},"entryCSSFiles":{"/home/dx/Work/hex/dashboard/":[],"/home/dx/Work/hex/dashboard/app/layout":["static/css/4a38d8f6f6b7a68f.css"],"/home/dx/Work/hex/dashboard/app/page":[],"/home/dx/Work/hex/dashboard/app/overleaf/page":[]}}
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[529],{9531:function(e,t,a){Promise.resolve().then(a.bind(a,9))},9:function(e,t,a){"use strict";a.d(t,{OverleafClient:function(){return i}});var s=a(7821),r=a(8078);let n=[{key:"executive_summary",label:"Executive Summary",file:"executive_summary.txt"},{key:"audited_files",label:"Audited Files",file:"audited_files.txt"},{key:"summary_of_findings",label:"Summary of Issues",file:"summary_of_findings.txt"},{key:"findings",label:"Issues",file:"findings.txt"}];function i(e){var t;let{sections:a}=e,[i,o]=(0,r.useState)("executive_summary"),[l,c]=(0,r.useState)(!1),d=a[i],x=async()=>{if(d)try{await navigator.clipboard.writeText(d),c(!0),setTimeout(()=>c(!1),1500)}catch(e){}};return(0,s.jsxs)("div",{children:[(0,s.jsxs)("header",{className:"mb-6",children:[(0,s.jsx)("h1",{className:"text-title font-semibold text-text-primary",children:"Overleaf"}),(0,s.jsxs)("p",{className:"mt-1 text-body text-text-secondary",children:["LaTeX report sections from ",(0,s.jsx)("span",{className:"font-mono text-caption",children:".hex/overleaf/"}),". Copy each into the matching slot of the Nethermind Overleaf template."]})]}),(0,s.jsx)("div",{className:"mb-4 flex flex-wrap gap-1.5",children:n.map(e=>{let t=e.key===i,r=!!a[e.key];return(0,s.jsx)("button",{type:"button",onClick:()=>o(e.key),className:"rounded-md px-3 py-1.5 text-caption font-medium ".concat(t?"bg-accent text-surface-0":"bg-surface-2 text-text-secondary hover:text-text-primary"," ").concat(r?"":"opacity-50"),children:e.label},e.key)})}),(0,s.jsxs)("div",{className:"rounded-lg border border-border-subtle bg-surface-1",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between border-b border-border-subtle px-4 py-2.5",children:[(0,s.jsx)("span",{className:"font-mono text-caption text-text-tertiary",children:null===(t=n.find(e=>e.key===i))||void 0===t?void 0:t.file}),(0,s.jsx)("button",{type:"button",onClick:x,disabled:!d,className:"rounded-md border border-border-default px-2.5 py-1 text-caption text-text-secondary hover:bg-surface-2 hover:text-text-primary disabled:opacity-50",children:l?"Copied!":"Copy"})]}),d?(0,s.jsx)("pre",{className:"max-h-[70vh] overflow-auto p-4 font-mono text-caption leading-relaxed text-text-secondary whitespace-pre-wrap break-words",children:d}):(0,s.jsxs)("p",{className:"p-4 text-body text-text-tertiary",children:["This section has not been generated yet. Run"," ",(0,s.jsx)("span",{className:"font-mono text-caption",children:"/generate-overleaf"}),"."]})]})]})}}},function(e){e.O(0,[7115,3205,1744],function(){return e(e.s=9531)}),_N_E=e.O()}]);
@@ -1,32 +0,0 @@
1
- import { readMarkdownFile } from '@/lib/data';
2
- import { NotYetGenerated } from '@/components/NotYetGenerated';
3
- import { OverleafClient, type OverleafSections } from './OverleafClient';
4
-
5
- // Read .hex/overleaf/ at request time, not at build time.
6
- export const dynamic = 'force-dynamic';
7
-
8
- export default function OverleafPage() {
9
- const sections: OverleafSections = {
10
- executive_summary: readMarkdownFile('overleaf/executive_summary.txt'),
11
- audited_files: readMarkdownFile('overleaf/audited_files.txt'),
12
- summary_of_findings: readMarkdownFile('overleaf/summary_of_findings.txt'),
13
- findings: readMarkdownFile('overleaf/findings.txt'),
14
- };
15
-
16
- const anyPresent = Object.values(sections).some(Boolean);
17
- if (!anyPresent) {
18
- return (
19
- <div>
20
- <header className="mb-6">
21
- <h1 className="text-title font-semibold text-text-primary">Overleaf</h1>
22
- <p className="mt-1 text-body text-text-secondary">
23
- LaTeX report sections, ready to paste into the Nethermind Overleaf template.
24
- </p>
25
- </header>
26
- <NotYetGenerated command="/generate-overleaf" />
27
- </div>
28
- );
29
- }
30
-
31
- return <OverleafClient sections={sections} />;
32
- }