hex-audit 0.5.5 → 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 (77) hide show
  1. package/DEMO.md +20 -17
  2. package/README.md +25 -22
  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 +5 -5
  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 +8 -8
  33. package/dashboard/.next/server/chunks/42.js +1 -1
  34. package/dashboard/.next/server/chunks/530.js +1 -1
  35. package/dashboard/.next/server/functions-config-manifest.json +1 -1
  36. package/dashboard/.next/server/middleware-build-manifest.js +1 -1
  37. package/dashboard/.next/server/pages/404.html +1 -1
  38. package/dashboard/.next/server/pages/500.html +1 -1
  39. package/dashboard/.next/server/server-reference-manifest.js +1 -1
  40. package/dashboard/.next/server/server-reference-manifest.json +1 -1
  41. package/dashboard/.next/static/chunks/app/issues/page-98a298e1c1045c91.js +1 -0
  42. package/dashboard/.next/static/chunks/app/{layout-a95b696089e278c3.js → layout-49f2496c7637d931.js} +1 -1
  43. package/dashboard/.next/static/chunks/app/report/page-796f2f4a8a5ac8f7.js +1 -0
  44. package/dashboard/.next/static/chunks/{main-9a811c95265dbd11.js → main-63ff429eab01f5bf.js} +1 -1
  45. package/dashboard/app/issues/IssuesBoardClient.tsx +19 -3
  46. package/dashboard/app/{overleaf/OverleafClient.tsx → report/ReportClient.tsx} +15 -7
  47. package/dashboard/app/report/page.tsx +35 -0
  48. package/dashboard/components/DashboardLayout.tsx +1 -1
  49. package/dist/commands/init.js +4 -4
  50. package/dist/commands/init.js.map +1 -1
  51. package/dist/commands/issue.js +2 -2
  52. package/dist/commands/issue.js.map +1 -1
  53. package/dist/core/issues.d.ts +1 -1
  54. package/dist/core/issues.d.ts.map +1 -1
  55. package/dist/core/issues.js +2 -1
  56. package/dist/core/issues.js.map +1 -1
  57. package/dist/core/schema.d.ts +14 -0
  58. package/dist/core/schema.d.ts.map +1 -1
  59. package/dist/core/schema.js +2 -0
  60. package/dist/core/schema.js.map +1 -1
  61. package/dist/skills/diane.md +1 -1
  62. package/dist/skills/{generate-overleaf.md → generate-report.md} +186 -32
  63. package/dist/skills/ingest-aa-report.md +2 -2
  64. package/dist/skills/init-audit.md +2 -2
  65. package/dist/skills/sync-issues.md +1 -1
  66. package/dist/skills/validate-all-findings.md +24 -10
  67. package/dist/skills/{validate-issue.md → validate-finding.md} +72 -26
  68. package/dist/skills/write-finding.md +3 -3
  69. package/package.json +2 -2
  70. package/dashboard/.next/server/app/overleaf/page.js +0 -1
  71. package/dashboard/.next/server/app/overleaf/page_client-reference-manifest.js +0 -1
  72. package/dashboard/.next/static/chunks/app/issues/page-72089090c04e96ee.js +0 -1
  73. package/dashboard/.next/static/chunks/app/overleaf/page-bcea12a80c97b92f.js +0 -1
  74. package/dashboard/app/overleaf/page.tsx +0 -32
  75. /package/dashboard/.next/server/app/{overleaf → report}/page.js.nft.json +0 -0
  76. /package/dashboard/.next/static/{ZvCvC4cMbL3GR8kloB9OJ → hU4ffTc1ImuXgNi8GX6_t}/_buildManifest.js +0 -0
  77. /package/dashboard/.next/static/{ZvCvC4cMbL3GR8kloB9OJ → 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.
@@ -142,7 +142,7 @@ Then record the match in `<output_dir>/comparison.json` under `duplicates`. The
142
142
 
143
143
  If `comparison.json` doesn't exist, create it with `{ "duplicates": [], "novel": [], "rejected": [] }`.
144
144
 
145
- For entries that don't match anything, leave them as `status: "unverified"` (the auditor will run `/validate-issue AA-<NNN>` on them).
145
+ For entries that don't match anything, leave them as `status: "unverified"` (the auditor will run `/validate-finding AA-<NNN>` on them).
146
146
 
147
147
  ## Step 7 — Report
148
148
 
@@ -154,7 +154,7 @@ Ingested N AuditAgent findings (scan <scan_id>).
154
154
  - K flagged as Duplicate of existing entries
155
155
  - 0 errors
156
156
 
157
- Run /validate-issue <id> on any new finding to confirm and promote it to Verified.
157
+ Run /validate-finding <id> on any new finding to confirm and promote it to Verified.
158
158
  ```
159
159
 
160
160
  ## Outputs (recap)
@@ -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
 
@@ -247,7 +247,7 @@ npx hex issue new --source conformance --source-ref "<spec-item-id, e.g. SC-001>
247
247
  --severity "<spec-item.severity_hint, default Info>"
248
248
  ```
249
249
 
250
- `--source-ref` is the spec item's own id (e.g. `SC-001`) — Hex keeps that as the back-reference; the board card itself gets the uniform `H-NNN`. These appear on the Issues board as Potential cards immediately; the auditor validates them later with `/validate-issue <id>` (or `/validate-all-findings`).
250
+ `--source-ref` is the spec item's own id (e.g. `SC-001`) — Hex keeps that as the back-reference; the board card itself gets the uniform `H-NNN`. These appear on the Issues board as Potential cards immediately; the auditor validates them later with `/validate-finding <id>` (or `/validate-all-findings`).
251
251
 
252
252
  **Idempotency:** before creating, check whether a tracking entry already has this `source_ref` (re-running `/init-audit` shouldn't double-create). Skip items whose `source_ref` is already present.
253
253
 
@@ -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
 
@@ -6,7 +6,9 @@ description: "Walk every Potential issue on the board and validate them one by o
6
6
 
7
7
  **Recommended model:** Opus
8
8
 
9
- Runs `/validate-issue` over every issue currently in the **Potential** column, one at a time, so the auditor can clear the backlog in a single pass without naming each id.
9
+ Runs `/validate-finding` over every issue currently in the **Potential** column, one at a time, so the auditor can clear the backlog in a single pass without naming each id.
10
+
11
+ Each issue gets `/validate-finding`'s full two-axis verdict — correctness **and** the Step-2.5 security-relevance gate. **`auditagent` / `github` findings skew recall-over-precision, so the realism gate is mandatory for them**; `manual` / `conformance` items already passed an auditor's eye and can lean lighter.
10
12
 
11
13
  ## Step 1 — Build the work list
12
14
 
@@ -14,6 +16,16 @@ Read `<output_dir>/tracking.json`. The Potential column is every entry whose `st
14
16
 
15
17
  If `N` is 0, report "No Potential issues to validate." and stop.
16
18
 
19
+ ## Step 1.5 — Cheap realism pre-pass
20
+
21
+ Before deep-diving, do a fast first pass over all `N` and emit a one-line realism read per issue — the Step-2.5 reality-gate take only, no full code trace yet:
22
+
23
+ ```
24
+ <id> [<sev>] <title> — likely: security | by-design | self-inflicted | incorrect | unsure
25
+ ```
26
+
27
+ Print it as a table. This front-loads "which of these even deserve a deep trace" so effort concentrates on the genuine security candidates instead of spreading evenly. It's a triage hint, not a verdict — every issue still gets its real verdict in Step 2.
28
+
17
29
  ## Step 2 — Loop
18
30
 
19
31
  For each issue `i` of `N` (1-based), print a header:
@@ -22,15 +34,16 @@ For each issue `i` of `N` (1-based), print a header:
22
34
  ── Validating i/N: <id> [<severity>] <title> ──
23
35
  ```
24
36
 
25
- Then run the full **`/validate-issue`** flow for that `<id>` exactly as that skill defines it:
37
+ Then run the full **`/validate-finding`** flow for that `<id>` exactly as that skill defines it:
26
38
  1. Assemble context (the tracking entry + its source record + the affected source).
27
39
  2. Trace the claim in the code.
28
- 3. Reach a verdict:
29
- - **Valid** → ask PoC-vs-memo (AskUserQuestion), write the validation memo, optionally generate the PoC, then `hex issue patch <id> ...` + `hex issue move <id> --to verified`; offer the severity-adjustment prompt.
30
- - **Invalid** → `hex issue move <id> --to invalid`, memo records why.
40
+ 3. Reach a verdict (correctness + the Step-2.5 security-relevance gate):
41
+ - **Verified** (true + security-relevant) → re-rate severity, ask PoC-vs-memo, write the memo, `hex issue patch <id> ...` + `hex issue move <id> --to verified`.
42
+ - **Rejected — by-design** (true, not security-relevant) → memo with `Disposition: by-design`, `hex issue patch <id> --resolution Acknowledged` + `hex issue move <id> --to rejected`.
43
+ - **Rejected — incorrect** (false) → `hex issue move <id> --to rejected` (no resolution), memo records why.
31
44
  - **Uncertain** → leave in place, `hex issue patch <id> --notes "<open questions>"`.
32
45
 
33
- Do not batch or skip the interactive prompts — this skill is the same per-issue UX as `/validate-issue`, just iterated. The auditor stays in control of each verdict.
46
+ Batch by tier — don't rubber-stamp. **Security-relevant candidates get the full per-issue prompt flow** (PoC-vs-memo and severity), one at a time — the auditor stays in control of every real finding. **Info / by-design / self-inflicted items may be batched**: collect them and confirm their dispositions (and any PoC/severity calls) in a single consolidated **AskUserQuestion** instead of N separate modals. That keeps a large sweep controllable without diluting scrutiny on the findings that matter.
34
47
 
35
48
  ## Step 3 — Resume safety
36
49
 
@@ -42,9 +55,10 @@ After the loop, print a tally:
42
55
 
43
56
  ```
44
57
  Validated N Potential issues:
45
- → Verified: V
46
- → Invalid: X
47
- → Left for review (uncertain): U
58
+ → Verified: V
59
+ → Rejected (incorrect): X
60
+ → Rejected (valid, not security): B
61
+ → Left for review (uncertain): U
48
62
  ```
49
63
 
50
- 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.
@@ -1,8 +1,8 @@
1
1
  ---
2
- description: "Validate any potential issue on the board (manual / auditagent / conformance / github) and promote it to Verified or Invalid"
2
+ description: "Validate any potential finding on the board (manual / auditagent / conformance / github): check both correctness and security relevance, then route to Verified, Rejected, or leave Uncertain"
3
3
  ---
4
4
 
5
- # Skill: Validate Issue
5
+ # Skill: Validate Finding
6
6
 
7
7
  **Recommended model:** Opus
8
8
 
@@ -15,17 +15,17 @@ Takes a single potential issue from the dashboard's Issues board and runs an ind
15
15
  - **Conformance** (materialized by `/init-audit`) — `source: "conformance"`, `status: "pending_validation"`.
16
16
  - **GitHub** (teammate findings via `/sync-issues`) — `source: "github"`, `status: "pending_validation"`.
17
17
 
18
- The skill writes a validation memo (always), optionally generates a PoC, and updates the tracking entry to `verified` or `rejected`. Card moves on the board.
18
+ The skill judges **two** things, not one: first **correctness** (is the claim true?), then for true claims **security relevance** (is it actually a vuln worth reporting, or true-but-by-design / a missing feature / self-inflicted?). It writes a validation memo (always), optionally generates a PoC, and moves the card. Outcomes: **Verified** (true + security-relevant), **Rejected** (either factually incorrect, *or* true-but-not-a-security-issue), or **Uncertain**. Both Rejected kinds land in the board's **Rejected** column, distinguished by disposition.
19
19
 
20
20
  ## Invocation
21
21
 
22
22
  The auditor invokes by id or by free-text reference:
23
23
 
24
24
  ```
25
- /validate-issue F003
26
- /validate-issue SC-007
27
- /validate-issue AA-N002
28
- /validate-issue for the rounding issue in Vault.sol
25
+ /validate-finding F003
26
+ /validate-finding SC-007
27
+ /validate-finding AA-N002
28
+ /validate-finding for the rounding issue in Vault.sol
29
29
  ```
30
30
 
31
31
  Resolve to a single tracking entry by:
@@ -65,12 +65,35 @@ For conformance items, the "claim" is `spec_text` + the finding paragraph — i.
65
65
  - Check existing protections (modifiers, reentrancy guards, input validation, economic constraints).
66
66
  - For conformance items: re-read the cited spec section, compare to the implementation.
67
67
 
68
+ ### 2.5 Reality gate — is it security-relevant?
69
+
70
+ Correctness is not enough. AI scanners (and sometimes teammates) surface claims that are **factually true but not security issues** — by-design behavior, missing features, defense-in-depth nice-to-haves, or risks only the deployer can inflict on themselves. This is the precision pass. **Run it for every finding; treat it as mandatory for `source: auditagent | github`** (those skew recall-over-precision). `manual` / `conformance` items already passed an auditor's eye, so they can lean lighter.
71
+
72
+ For a claim you found **true**, run these five checks — each one pushes toward *not-security-relevant*:
73
+
74
+ - **Trigger model.** Can only the deployer/owner harm their own deployment? Then it's self-inflicted, not an attack.
75
+ - **Out-of-scope dependency.** Does the impact require an out-of-scope component (e.g. the integrating contract) to be buggy or malicious — and if so, does the finding grant a capability that component didn't already have? No capability gain → defense-in-depth noise.
76
+ - **Trivial workaround.** Is there an integrator-controlled or already-documented mitigation (a constructor param, a config, standard usage)?
77
+ - **Class.** Defect, deliberate design decision, or missing feature? Only defects are findings.
78
+ - **Net test.** Would a senior auditor put this in a client report as a security issue, as an informational note, or not at all?
79
+
80
+ Carry the answers into the verdict and the memo (Triggerability / Depends-on-out-of-scope / Disposition).
81
+
68
82
  ### 3. Verdict
69
83
 
70
- **Valid:**
84
+ Combine the two axes — correctness (Step 2) and security relevance (Step 2.5):
85
+
86
+ | Correctness | Security-relevant? | → Outcome |
87
+ |---|---|---|
88
+ | True | Yes | **Verified** |
89
+ | True | No | **Rejected** (by-design / informational) |
90
+ | False | — | **Rejected** (incorrect) |
91
+ | Uncertain | — | **Uncertain** |
92
+
93
+ **Verified — true and security-relevant:**
71
94
 
72
95
  1. Use **AskUserQuestion** to ask:
73
- > The issue appears **VALID**. How would you like to proceed?
96
+ > The finding appears **VALID and security-relevant**. How would you like to proceed?
74
97
  >
75
98
  > 1. Generate a full PoC test, then promote to Verified.
76
99
  > 2. Accept with rational verification only — validation memo, no PoC.
@@ -81,7 +104,9 @@ For conformance items, the "claim" is `spec_text` + the finding paragraph — i.
81
104
 
82
105
  3. **If memo-only chosen:** no PoC file.
83
106
 
84
- 4. **Persist via the CLI — do not hand-edit `findings.json` or `tracking.json`.** The `hex issue` command is the single source of truth for board mutations; it materializes a `findings.json` entry from the source record (conformance / auditagent / github) when one does not exist yet, and routes fields correctly. Write the validation memo and the recommendation to temp files, then:
107
+ 4. **Calibrate severity — don't inherit it.** The source's severity (especially AuditAgent's) is a *hypothesis*, not authoritative. Re-derive it from realistic impact × likelihood; many technically-true findings collapse to Info. A finding whose worst case is self-inflicted or chain-conditional must say so and re-rate accordingly.
108
+
109
+ 5. **Persist via the CLI — do not hand-edit `findings.json` or `tracking.json`.** The `hex issue` command is the single source of truth for board mutations; it materializes a `findings.json` entry from the source record (conformance / auditagent / github) when one does not exist yet, and routes fields correctly. Write the validation memo and the recommendation to temp files, then:
85
110
 
86
111
  ```bash
87
112
  # Land the editable fields (materializes a finding for conformance/auditagent/github ids):
@@ -99,21 +124,34 @@ For conformance items, the "claim" is `spec_text` + the finding paragraph — i.
99
124
 
100
125
  Hex does not write `@audit-issue` comments into the client's source files — the board and finding record are the only place the issue lives.
101
126
 
102
- 5. Use **AskUserQuestion** to ask:
127
+ 6. Use **AskUserQuestion** to ask:
103
128
  > Issue verified as **\<id\>** with severity **\<current severity\>**.
104
129
  >
105
130
  > Would you like to change the severity? Reply with the new severity (Critical / High / Medium / Low / Info), or **no** to keep it.
106
131
 
107
- 6. If the user provides a new severity, run `npx hex issue patch <id> --severity <NewSeverity>`.
132
+ 7. If the user provides a new severity, run `npx hex issue patch <id> --severity <NewSeverity>`.
108
133
 
109
- **Invalid:**
134
+ **Rejected — true but not a security issue (by-design / informational):**
110
135
 
111
- 1. Explain why:
112
- - Is the attack path blocked? By what specifically (modifier, require, state check)?
113
- - Are the preconditions impossible? Why?
114
- - Is the impact assessment wrong? What actually happens?
115
- 2. Move it to the Invalid column: `npx hex issue move <id> --to invalid`.
116
- 3. Do NOT write a finding body. The memo alone records the reasoning.
136
+ The claim is correct, but Step 2.5 says it isn't a vuln worth reporting (self-inflicted, design decision, missing feature, defense-in-depth noise). This is **not** the same as "incorrect" — give it its own disposition so it's distinguishable from a false positive and AuditAgent gets honest feedback.
137
+
138
+ 1. Write the memo with `Disposition: by-design` (or `informational`) and the Step-2.5 reasoning.
139
+ 2. Mark the disposition and move it:
140
+ ```bash
141
+ npx hex issue patch <id> --resolution Acknowledged
142
+ npx hex issue move <id> --to rejected
143
+ ```
144
+ `Acknowledged` on a Rejected card means "AA was right, but it's by-design / not a security issue" — the board shows a **By-design** chip. (A Rejected card with *no* resolution = factually incorrect; see below.)
145
+ 3. Do NOT write a finding body or carry it into the report.
146
+
147
+ **Rejected — incorrect (false positive):**
148
+
149
+ The claim is factually wrong. Explain why:
150
+ - Is the attack path blocked? By what specifically (modifier, require, state check)?
151
+ - Are the preconditions impossible? Why?
152
+ - Is the impact assessment wrong? What actually happens?
153
+
154
+ Move it to the Rejected column with **no** resolution (the board shows an **Invalid** chip): `npx hex issue move <id> --to rejected`. Do NOT write a finding body — the memo records the reasoning.
117
155
 
118
156
  **Uncertain:**
119
157
 
@@ -126,11 +164,15 @@ For conformance items, the "claim" is `spec_text` + the finding paragraph — i.
126
164
  Write `<output_dir>/validations/<id>_memo.md` (always — for valid, invalid, and uncertain verdicts):
127
165
 
128
166
  ```markdown
129
- # Issue Validation: <ID> — <Title>
167
+ # Finding Validation: <ID> — <Title>
130
168
 
131
169
  **Source:** <manual | auditagent | conformance | github>
132
170
  **Original record:** <pointer to the specific record being validated — e.g., findings.json#F003, ai-results/auditagent/findings.json#AA-014>
133
- **Verdict:** Valid / Invalid / Uncertain
171
+ **Correctness:** True / False / Uncertain
172
+ **Security relevance:** security-relevant / not-security-relevant / n/a
173
+ **Triggerability:** external | self-inflicted
174
+ **Depends on out-of-scope component:** no | yes (capability gain: yes/no)
175
+ **Disposition:** security-finding | by-design | informational | false
134
176
  **Date:** <YYYY-MM-DD>
135
177
 
136
178
  ## Claim being validated
@@ -142,13 +184,17 @@ Write `<output_dir>/validations/<id>_memo.md` (always — for valid, invalid, an
142
184
  ## Protections evaluated
143
185
  [Access control, reentrancy guards, input validation, economic constraints, etc.]
144
186
 
187
+ ## Reality gate
188
+ [The five Step-2.5 checks for true claims: trigger model, out-of-scope dependency, trivial workaround, class, net test. Skip with "n/a (claim is false)" for incorrect findings.]
189
+
145
190
  ## Verdict reasoning
146
- [Why valid / invalid / uncertain]
191
+ [Why Verified / Rejected (by-design or incorrect) / Uncertain — tie it to the two axes above]
147
192
 
148
193
  ## Action taken
149
- [If valid + PoC: PoC at <path>, test passing, finding F<NNN> updated/created]
150
- [If valid + memo-only: finding F<NNN> updated/created, no PoC]
151
- [If invalid: tracking entry rejected, no finding written]
194
+ [If Verified + PoC: PoC at <path>, test passing, finding updated/created; severity re-rated to <X>]
195
+ [If Verified + memo-only: finding updated/created, no PoC; severity <X>]
196
+ [If Rejected by-design: moved to Rejected with resolution Acknowledged, no finding written]
197
+ [If Rejected incorrect: moved to Rejected, no resolution, no finding written]
152
198
  [If uncertain: open questions listed; tracking status unchanged]
153
199
  ```
154
200
 
@@ -158,4 +204,4 @@ The board reflects the new state automatically (the dashboard watches `tracking.
158
204
 
159
205
  - Move on to the next Potential card.
160
206
  - Run `/sync-issues` to push the newly Verified finding to GitHub if `settings.github.repo` is configured.
161
- - 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.