---
title: Reading a proof
description: "Every pipeline run produces a proof \u2014 a JSON record committed to your repo that captures what was built, how it was verified, and whether it can be trusted. This guide walks through security-hardening so you know what each part means."
readingTime: 5
---

## What you see in the terminal

After `ana work complete`, run `ana proof <slug>` to see the summary:

<div style={{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",margin:"8px 0 18px",fontFamily:"var(--font-mono)",fontSize:"12.5px",lineHeight:1.65,overflow:"hidden"}}>
<div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 14px",borderBottom:"1px solid var(--hairline)",background:"var(--bg-elev)",fontSize:"11px",color:"var(--ink-60)"}}>
<span style={{color:"var(--ink-45)",textTransform:"uppercase",letterSpacing:"0.06em",fontSize:"10px"}}>bash</span>
</div>
<pre style={{padding:"14px 16px",color:"var(--ink-75)",overflowX:"auto",whiteSpace:"pre",margin:0,background:"transparent",fontSize:"inherit",lineHeight:"inherit",fontFamily:"inherit"}}>
{"$ "}<span style={{color:"var(--pass)"}}>ana proof</span>{" security-hardening\n\n  Result: PASS\n  27/27 satisfied · 0 unsatisfied · 0 deviated\n\n  "}<span style={{color:"var(--pass)"}}>✓</span>{" Slugs with shell injection characters are rejected before any operation\n  "}<span style={{color:"var(--pass)"}}>✓</span>{" Valid kebab-case slugs pass validation\n  "}<span style={{color:"var(--pass)"}}>✓</span>{" No direct shell execution calls remain in command or utility files\n"}<span style={{color:"var(--ink-45)"}}>{"    ...24 more"}</span>{"\n\n  Timing: 74m (Think 2m · Plan 15m · Build 53m · Verify 5m)\n\n  [debt · scope] No dedicated integration tests for...\n  [obs · monitor] getCurrentBranch still uses execSync\n"}<span style={{color:"var(--ink-45)"}}>{"    ...and 8 more findings"}</span>
</pre>
</div>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}><code>ana work complete</code> now ends with a <code>View the full proof: ana proof &lt;slug&gt;</code> hint, so the command to read what you just shipped is always one copy away. To skip naming the slug, <code>ana proof --last</code> (alias <code>--latest</code>) shows the most recently completed proof — handy right after a run, or in scripts that always want the newest entry.</p>

The proof page on the docs site shows the same data with more detail. Each section below maps to a part of that page.

## The hero

Six numbers at the top of every proof page:

<div style={{display:"grid",gridTemplateColumns:"repeat(3, 1fr)",gap:"10px",margin:"16px 0 20px"}}>
<div style={{padding:"10px 12px",borderRadius:"var(--radius-sm)",background:"var(--bg-card)",border:"1px solid var(--border-soft)"}}>
<div style={{fontSize:"11px",color:"var(--ink-45)",textTransform:"uppercase",letterSpacing:"0.04em"}}>Verdict</div>
<div style={{fontSize:"15px",fontWeight:600,color:"var(--pass)"}}>PASS</div>
</div>
<div style={{padding:"10px 12px",borderRadius:"var(--radius-sm)",background:"var(--bg-card)",border:"1px solid var(--border-soft)"}}>
<div style={{fontSize:"11px",color:"var(--ink-45)",textTransform:"uppercase",letterSpacing:"0.04em"}}>Score</div>
<div style={{fontSize:"15px",fontWeight:600,color:"var(--fg)"}}>27 / 27</div>
</div>
<div style={{padding:"10px 12px",borderRadius:"var(--radius-sm)",background:"var(--bg-card)",border:"1px solid var(--border-soft)"}}>
<div style={{fontSize:"11px",color:"var(--ink-45)",textTransform:"uppercase",letterSpacing:"0.04em"}}>Findings</div>
<div style={{fontSize:"15px",fontWeight:600,color:"var(--fg)"}}>10 <span style={{fontSize:"12px",color:"var(--ink-45)",fontWeight:400}}>3 debt · 7 obs</span></div>
</div>
<div style={{padding:"10px 12px",borderRadius:"var(--radius-sm)",background:"var(--bg-card)",border:"1px solid var(--border-soft)"}}>
<div style={{fontSize:"11px",color:"var(--ink-45)",textTransform:"uppercase",letterSpacing:"0.04em"}}>Duration</div>
<div style={{fontSize:"15px",fontWeight:600,color:"var(--fg)"}}>74m</div>
</div>
<div style={{padding:"10px 12px",borderRadius:"var(--radius-sm)",background:"var(--bg-card)",border:"1px solid var(--border-soft)"}}>
<div style={{fontSize:"11px",color:"var(--ink-45)",textTransform:"uppercase",letterSpacing:"0.04em"}}>Rejections</div>
<div style={{fontSize:"15px",fontWeight:600,color:"var(--fg)"}}>0</div>
</div>
<div style={{padding:"10px 12px",borderRadius:"var(--radius-sm)",background:"var(--bg-card)",border:"1px solid var(--border-soft)"}}>
<div style={{fontSize:"11px",color:"var(--ink-45)",textTransform:"uppercase",letterSpacing:"0.04em"}}>Shipped</div>
<div style={{fontSize:"15px",fontWeight:600,color:"var(--fg)"}}>may 4</div>
</div>
</div>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}>Monorepo projects show one additional label: the surface that was verified.</p>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}>Score is contract assertions satisfied. Findings are independent observations from Verify — they don't block shipping. Rejections count how many times Build had to fix and re-verify. A proof with rejection cycles shows a longer build and a **Previous Findings Resolution** section — see [proof-promote](/docs/proof/proof-promote) for that story.</p>

## The timeline

Four bars showing Think, Plan, Build, and Verify. The shape tells you what kind of work this was. Security-hardening: Think 2m, Plan 15m, Build 53m, Verify 5m — a heavy build, light verification. Compare with [worktree-isolation](/docs/proof/worktree-isolation): Think 3m, Plan 22m, Build 63m, Verify 11m — similar build but double the verification time because the contract had 45 assertions.

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}>**What each phase measures.** Each bar spans from session start to artifact save for that agent. Think begins when Ana opens the scope conversation and ends when the scope is committed. Plan begins when AnaPlan starts and ends when the spec and contract are saved. Build and Verify follow the same pattern — session open to artifact save.</p>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}>**Why duration exceeds the sum of phases.** The header duration is wall-clock time from the first `_started_at` timestamp to the last artifact save. The bars show active session time only. Idle time between sessions — the gap between Plan finishing and Build starting, lunch breaks, overnight pauses — inflates the header but doesn't appear in any bar. A proof showing 2h 9m in the header and 21m in the bars means 1h 48m was idle time between sessions.</p>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}>**Multi-phase timing.** Some proofs split Build or Verify into numbered phases (Build 1, Build 2). Each phase gets its own bar, measured from that phase's session start to its artifact save. The bars are proportional to active time — a 3-minute verify phase next to a 53-minute build renders at roughly 5% width, not stretched to fill the remaining space.</p>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}>The median across all <DocsStat value="proofCount" /> proofs: <DocsStat value="medianThink" />m think, <DocsStat value="medianPlan" />m plan, <DocsStat value="medianBuild" />m build, <DocsStat value="medianVerify" />m verify.</p>

## The assertion ledger

Every contract assertion, independently evaluated. The `says` field is human-readable; the status is mechanical.

<div style={{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",margin:"8px 0 18px",fontFamily:"var(--font-mono)",fontSize:"12.5px",lineHeight:1.65,overflow:"hidden"}}>
<div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 14px",borderBottom:"1px solid var(--hairline)",background:"var(--bg-elev)",fontSize:"11px",color:"var(--ink-60)"}}>
<span style={{color:"var(--ink-45)",textTransform:"uppercase",letterSpacing:"0.06em",fontSize:"10px"}}></span>
</div>
<pre style={{padding:"14px 16px",color:"var(--ink-75)",overflowX:"auto",whiteSpace:"pre",margin:0,background:"transparent",fontSize:"inherit",lineHeight:"inherit",fontFamily:"inherit"}}>
<span style={{color:"var(--pass)"}}>✓</span>{" A001  Slugs with shell injection characters are rejected before any operation\n"}<span style={{color:"var(--pass)"}}>✓</span>{" A003  Valid kebab-case slugs pass validation\n"}<span style={{color:"var(--pass)"}}>✓</span>{" A023  No direct shell execution calls remain in command or utility files\n"}<span style={{color:"var(--ink-45)"}}>{"  ...24 more, all satisfied"}</span>
</pre>
</div>

The ledger shows 27/27 SATISFIED. If any assertion were UNSATISFIED, the verdict would be FAIL and the work would go back to Build. The assertions are the mechanical definition of "done" — what the contract said, what Verify found.

## The findings

Each finding has a severity and a suggested action, rendered as a two-part tag:

<div style={{margin:"12px 0 16px",display:"flex",flexDirection:"column",gap:"8px"}}>
<div style={{fontSize:"13px",padding:"8px 12px",borderRadius:"var(--radius-sm)",background:"var(--bg-card)",border:"1px solid var(--border-soft)",color:"var(--ink-75)",display:"flex",alignItems:"center",gap:"8px"}}>
<span style={{padding:"2px 7px",borderRadius:"3px",fontWeight:500,letterSpacing:"0.06em",fontSize:"10px",fontFamily:"var(--font-mono)",textTransform:"uppercase",background:"var(--warn-bg)",color:"var(--warn)",whiteSpace:"nowrap",flexShrink:0}}>debt · scope</span>
<span>No dedicated integration tests for command entry point injection rejection</span>
</div>
<div style={{fontSize:"13px",padding:"8px 12px",borderRadius:"var(--radius-sm)",background:"var(--bg-card)",border:"1px solid var(--border-soft)",color:"var(--ink-75)",display:"flex",alignItems:"center",gap:"8px"}}>
<span style={{padding:"2px 7px",borderRadius:"3px",fontWeight:500,letterSpacing:"0.06em",fontSize:"10px",fontFamily:"var(--font-mono)",textTransform:"uppercase",background:"var(--info-bg)",color:"var(--info)",whiteSpace:"nowrap",flexShrink:0}}>obs · monitor</span>
<span>getCurrentBranch still uses execSync — not hardened by this phase</span>
</div>
</div>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}><strong>debt · scope</strong> means: the codebase is getting worse (debt) and this needs engineering work (scope). <strong>obs · monitor</strong> means: worth knowing (observation) but watch it, don't act now (monitor). Findings enter the proof chain and are triaged by [Learn](/docs/guides/using-ana-learn) between cycles.</p>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}>Security-hardening's findings focus on test coverage gaps. Other proofs surface different catches: `process.exit(1)` on a rebase conflict without running `git rebase --abort`, leaving dirty state. `JSON.parse` on CLI stdout with no try/catch — malformed response crashes. Path normalization that breaks on Windows backslashes. A race condition where a file deleted between filter and `readFileSync` crashes `completeWork`.</p>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}>To triage findings after shipping, run `ana run learn`. See [Using ana-learn](/docs/guides/using-ana-learn).</p>

## The integrity seal

SHA-256 hashes of every artifact — scope, spec, contract, both reports, both data files. If any artifact changes after shipping, the hashes won't match.

<div style={{background:"var(--bg-card)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",margin:"8px 0 18px",fontFamily:"var(--font-mono)",fontSize:"12.5px",lineHeight:1.65,overflow:"hidden"}}>
<div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 14px",borderBottom:"1px solid var(--hairline)",background:"var(--bg-elev)",fontSize:"11px",color:"var(--ink-60)"}}>
<span style={{color:"var(--ink-45)",textTransform:"uppercase",letterSpacing:"0.06em",fontSize:"10px"}}></span>
</div>
<pre style={{padding:"14px 16px",color:"var(--ink-75)",overflowX:"auto",whiteSpace:"pre",margin:0,background:"transparent",fontSize:"inherit",lineHeight:"inherit",fontFamily:"inherit"}}>
{"scope      sha256:13f7bad7930a...\ncontract   sha256:b9e52761c704...\nbuild-report  sha256:67bc172dade8...\nverify-report sha256:9f0dd78e9f3a...\n"}<span style={{color:"var(--ink-45)"}}>{"...4 more artifacts"}</span>
</pre>
</div>

<p style={{fontSize:"13px",color:"var(--ink-60)",margin:"0 0 16px"}}>These are the real hashes from the security-hardening proof.</p>

<NextCards cards={[
  {
    eyebrow: "Next guide",
    title: "Using ana-learn",
    href: "/docs/guides/using-ana-learn",
    description: "What to do with the findings your proofs accumulate."
  },
  {
    eyebrow: "Real proof",
    title: "security-hardening",
    href: "/docs/proof/security-hardening",
    description: "27 assertions, 10 findings. Read the real thing."
  }
]} />
