From f2ef08cbd0fa9131020d8f46bd407227b09313f9 Mon Sep 17 00:00:00 2001
From: Chumaniac <121109854+Chumaniac@users.noreply.github.com>
Date: Wed, 21 Oct 2026 14:31:29 +0800
Subject: [PATCH 1/2] feat(reports): open offline findings by review priority
---
CHANGELOG.md | 7 +++++++
src/reporters/verification-html.ts | 21 ++++++++++++++-------
tests/reporters/verification-html.test.ts | 23 +++++++++++++++++++++++
3 files changed, 44 insertions(+), 7 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 700263c..ca4b71b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## Unreleased source - 2026-10-21
+
+- Open offline verification reports at the first priority needing review and
+ jump directly to other severity groups, including without JavaScript.
+- Keep complete counts and the existing detail budget; omit empty groups and
+ use readable status labels. Redaction and verification outcomes are unchanged.
+
## 0.3.0 - 2026-10-20
- Review all validated cross-file declarations and inspection limits in offline HTML, text and JSON reports, including CSV summaries, reference metadata and keyed integer allocations.
diff --git a/src/reporters/verification-html.ts b/src/reporters/verification-html.ts
index 95338e3..009c186 100644
--- a/src/reporters/verification-html.ts
+++ b/src/reporters/verification-html.ts
@@ -15,12 +15,19 @@ export function renderVerificationHtml(input: VerificationReport): string {
const report = redactLocalPaths(input);
const issues = report.issues?.length ? report.issues : toIssues(report.findings);
const counts = report.summary;
+ const priorities = [
+ { severity: "critical", label: "Critical issues", help: "Resolve these issues before reusing this Skill." },
+ { severity: "error", label: "Errors", help: "Fix the failed checks, then verify again." },
+ { severity: "warn", label: "Warnings", help: "Review these warnings against your intended use." },
+ { severity: "info", label: "Information", help: "Review the recorded checks and notes." },
+ ].map(priority => ({ ...priority, issues: issues.filter(issue => issue.finding.severity === priority.severity) }))
+ .filter(priority => priority.issues.length > 0);
+ const links = priorities.length ? `${priorities.map(priority => `${priority.label} ${priority.issues.length} `).join("")} ` : "";
let remaining = DETAIL_LIMIT;
- const groups = (["critical", "error", "warn", "info"] as const).map(severity => {
- const all = issues.filter(issue => issue.finding.severity === severity);
+ const groups = priorities.map(({ severity, label, help, issues: all }, groupIndex) => {
const shown = all.slice(0, remaining);
remaining -= shown.length;
- return `${severity.toUpperCase()} · ${all.length} issues ${shown.map((issue, index) => {
+ return `${label} · ${all.length} issues ${help}
${shown.map((issue, index) => {
const f = issue.finding;
const resolution = issue.resolutions[0];
const steps = resolution?.kind === "manual" ? resolution.steps.slice(0, 8) : [];
@@ -29,14 +36,14 @@ export function renderVerificationHtml(input: VerificationReport): string {
${text(issue.explanation.cause)}
Next step: ${text(resolution?.title ?? f.remediation ?? issue.explanation.impact)}
${steps.length ? `${steps.map(step => `${text(step)} `).join("")} ` : ""}
Issue reference ${text(issue.id)}${text(issue.location?.path ?? "Location not included")}
`;
- }).join("")}${all.length > shown.length ? `Showing ${shown.length} of ${all.length} issues in this group. Use JSON for complete evidence.
` : ""}${all.length ? "" : "No issues in this group.
"} `;
+ }).join("")}${all.length > shown.length ? `Showing ${shown.length} of ${all.length} issues in this group. Use JSON for complete evidence.
` : ""} `;
}).join("");
const title = report.exitCode === 2 ? "Verification setup required" : counts.fail ? "Changes require attention" : counts.unknown || counts.warn ? "Review incomplete evidence" : "Declared checks passed";
return `
SkillSync · ${title}
-
+
-${title} Read the cause and next step for each issue. These deterministic checks do not establish runtime safety, authenticated provenance, or approval.
${(["pass", "fail", "warn", "unknown"] as const).map(key => `
${text(counts[key])} ${key}
`).join("")}
${text(counts.total)} findings · ${text(issues.length)} deduplicated issues · exit code ${report.exitCode}
-Issues and next steps Groups are ordered by severity. At most ${DETAIL_LIMIT} issues are shown. Expand information groups to review successful checks.
${groups}
+${title} These checks read declared metadata. They do not establish runtime safety, authenticated provenance, or approval.
${([{ key: "pass", label: "Passed" }, { key: "fail", label: "Failed" }, { key: "warn", label: "Warnings" }, { key: "unknown", label: "Unverified" }] as const).map(({ key, label }) => `
${text(counts[key])} ${label}
`).join("")}
${text(counts.total)} findings · ${text(issues.length)} deduplicated issues · exit code ${report.exitCode}
${links}
+Issues and next steps ${priorities.length ? `The first group is open. Choose a priority above to open another group. At most ${DETAIL_LIMIT} issue details are included; use JSON for the full report.
${groups}` : "No issues were reported. Review the scope and selected targets below.
"}
Scope and evidence ${report.targets.length} selected targets. ${text(report.generated_at)}
Local paths and raw evidence contents are excluded. No Skill was executed and no fix was applied by this report.
Generated from local verification metadata. No scripts, external assets, or network requests. Keep the JSON report for complete machine-readable evidence.