History
Save every verify report with --save,
then render a score-over-time trend with paranoid
history: one self-contained HTML file, or a JSON series
for scripting. Everything stays on disk, local to the repo.
Saving reports
verify --save writes the exact same report
verify already computed to
.paranoid/history/<utc-timestamp>-<short-sha>.json,
in addition to whatever --format and
--output already do. The directory is created on
demand. The timestamp is the run's own
generated_at value (the injectable clock every
other deterministic part of this tool already uses), not a
second, independent wall-clock read; the short SHA is the
current HEAD commit, truncated to 7 characters, so
each saved file is readable at a glance and collisions are rare
in practice.
$ paranoid verify --save
...
$ ls .paranoid/history/
20260826T120000Z-3f2a9c1.json
Rendering the trend
paranoid history [path] loads every file under
.paranoid/history/, sorts them oldest to newest by
generated_at, and renders an HTML page with:
- A score-over-time line chart, drawn as inline SVG by hand: no charting library, no remote fetch, nothing but numbers this command already has.
- A runs table: date, base..head, score, verdict, and finding count by category.
- One sparkline per finding category, showing how its count moved across the same runs.
$ paranoid history
$ ls paranoid-history.html
A file that cannot be read, cannot be parsed, or was written by
a build that used a different history_version is
skipped, with one line on stderr naming the file and why. One
corrupt or foreign file never blocks the rest of the series, and
the command never crashes over it.
Determinism
The same history directory always renders the same HTML bytes.
Every value in the page, chart included, comes from the saved
reports themselves (scores, dates, category counts); nothing is
stamped in at render time. Runs are plotted at even, index-based
steps along the x-axis rather than scaled to calendar time,
since verify --save runs are irregular and even
spacing keeps the chart both simple and reproducible.
The history envelope, version 1
Each saved file wraps the full verify report
(identical to --format json's own output, including
its own schema_version) in a small envelope with
its own version number, independent of the report's:
| Field | Type | Meaning |
|---|---|---|
| history_version | integer | Always 1 today |
| report | object | The full verify report, same shape as --format json |
A report schema bump never forces a history envelope version bump, and the reverse is true too, the same relationship the baseline file and the fix-prompt schema already have to the report schema. See Report & schema.
JSON series (--format json)
paranoid history --format json prints the parsed,
derived series instead of rendering HTML: one entry per run,
plus the fixed, alphabetically sorted list of categories every
per-run breakdown uses. To stdout by default, for scripting.
{
"history_version": 1,
"runs": [
{
"generated_at": "2026-08-26T12:00:00Z",
"base": "7db5cfb...",
"head": "worktree",
"score": 90,
"verdict": "pass",
"total_findings": 1,
"findings_by_category": {"test-integrity": 1}
}
],
"categories": ["test-integrity"]
}
Privacy
Everything here is local. Saving, loading, and rendering never
make a network call, and the history directory never leaves
your machine unless you copy it somewhere yourself. Add
.paranoid/ to your repository's
.gitignore; these are personal, local run records,
not something the team needs committed.
Flags
| Flag | Default | Meaning |
|---|---|---|
| --format | html | Output format: html or json |
| --output | paranoid-history.html for html, stdout for json | Write the output to this file instead |
verify itself gains one new flag:
--save (off by default), which has no effect on
verify's own score, verdict, or exit code.