proof-aware-crypto-tooling-.../src/pacta/estateview.py

553 lines
40 KiB
Python
Raw Normal View History

"""estateview - the estate map as a cockpit view.
The same model as ESTATE.md (the canonical committed version), rendered
interactively for humans, with RUNTIME as a first-class dimension: every
entity dossier states whether anything is actually running, where, and
when it starts and stops. A sync test guards name-level drift between
this page and ESTATE.md.
"""
ESTATE_HTML = r'''<title>LTL estate map — repos, services, loops</title>
<style>
:root{
--ground:#f8f9fa; --panel:#ffffff; --ink:#1c2430; --ink2:#5a6675;
--line:#dde2e9; --src:#8a93a0; --sub:#1e7f4f; --mach:#3b4d8f;
--pub:#6d4a8f; --cons:#a86a10; --loop1:#c25e00; --loop2:#7a2ea0;
--held:#2b3442; --ok:#e2f2e9; --warn:#fdf0da;
}
*{box-sizing:border-box}
body{margin:0;background:var(--ground);color:var(--ink);
font:14px/1.45 system-ui,sans-serif}
code,.mono{font-family:ui-monospace,Menlo,Consolas,monospace}
header{padding:1.1rem 1.4rem .4rem}
h1{font-size:1.25rem;margin:0;letter-spacing:-.01em}
.sub{color:var(--ink2);font-size:.86rem;margin-top:.15rem}
.facts{display:flex;flex-wrap:wrap;gap:.45rem;padding:.6rem 1.4rem .2rem}
.fact{background:var(--panel);border:1px solid var(--line);border-radius:5px;
padding:.18rem .55rem;font-size:.78rem;color:var(--ink2)}
.fact b{color:var(--ink);font-weight:600}
.legend{display:flex;flex-wrap:wrap;gap:.9rem;padding:.45rem 1.4rem .6rem;
font-size:.76rem;color:var(--ink2);align-items:center}
.lg{display:flex;align-items:center;gap:.34rem}
.lg svg{display:block}
.wrap{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:0;
align-items:start}
@media(max-width:1080px){.wrap{grid-template-columns:1fr}}
.boardScroll{overflow-x:auto;padding:0 0 1.2rem 1.4rem}
.board{position:relative;width:1310px;padding-right:1rem}
.lanes{display:grid;grid-template-columns:170px 226px 300px 260px 226px;
gap:34px;position:relative;z-index:2}
.lane>.laneTitle{font-size:.68rem;letter-spacing:.09em;text-transform:uppercase;
font-weight:700;margin:0 0 .55rem;padding-bottom:.3rem;
border-bottom:2px solid var(--lc,var(--line))}
.lane{--lc:var(--line)}
.lane.src{--lc:var(--src)} .lane.sub{--lc:var(--sub)}
.lane.mach{--lc:var(--mach)} .lane.pub{--lc:var(--pub)}
.lane.cons{--lc:var(--cons)}
.laneTitle{color:var(--lc)}
.col{display:flex;flex-direction:column;gap:.55rem}
.node{background:var(--panel);border:1px solid var(--line);
border-left:3px solid var(--lc);border-radius:6px;
padding:.5rem .6rem;cursor:pointer;position:relative}
.node:hover,.node:focus-visible{border-color:var(--lc);outline:none;
box-shadow:0 1px 4px rgba(28,36,48,.12)}
.node.pinned{box-shadow:0 0 0 2px var(--lc)}
.node.dim{opacity:.28}
.node h3{margin:0;font-size:.8rem;font-weight:600}
.node h3.mono{font-size:.76rem}
.node .role{color:var(--ink2);font-size:.72rem;margin-top:.1rem}
.chips{display:flex;flex-wrap:wrap;gap:.25rem;margin-top:.3rem}
.chip{font-size:.62rem;font-weight:600;border-radius:8px;padding:.05rem .4rem}
.chip.ok{background:var(--ok);color:var(--sub)}
.chip.warn{background:var(--warn);color:var(--cons)}
.chip.gen{background:#efe9f5;color:var(--pub)}
.chip.frz{background:#e9edf3;color:#41506b}
.chip.l1{background:#fbe9dc;color:var(--loop1)}
.chip.l2{background:#f1e4f7;color:var(--loop2)}
.group{border:1px dashed var(--lc);border-radius:8px;padding:.55rem .55rem .6rem}
.group>.gTitle{font-size:.72rem;font-weight:700;margin:0 0 .45rem;
display:flex;align-items:baseline;gap:.4rem}
.group>.gTitle .mono{font-size:.7rem}
.group .col{gap:.4rem}
.group .node{border-left-width:2px;padding:.4rem .5rem}
.held{background:var(--held);border-color:var(--held)}
.held>.gTitle{color:#e8ecf2}
.held .node{background:#39445a;border-color:#4c5872;color:#e8ecf2}
.held .node .role{color:#aab4c6}
svg.edges{position:absolute;inset:0;z-index:1;pointer-events:none;
overflow:visible}
.e{fill:none;stroke:#b6bec9;stroke-width:1.3}
.e.attest{stroke:var(--sub)} .e.publish{stroke:var(--mach)}
.e.serve{stroke:var(--pub)} .e.consume{stroke:var(--cons)}
.e.tmpl{stroke:var(--mach);stroke-dasharray:5 4}
.e.sync,.e.pros{stroke-dasharray:5 4}
.e.pros{stroke:var(--cons)}
.e.loop1{stroke:var(--loop1);stroke-width:2.4}
.e.loop2{stroke:var(--loop2);stroke-width:2.4;stroke-dasharray:8 5}
.e.hot{stroke-width:3}
.e.faded{opacity:.12}
.eLabel{font-size:9.5px;fill:var(--ink2)}
.eLabel.loop1{fill:var(--loop1);font-weight:700}
.eLabel.loop2{fill:var(--loop2);font-weight:700}
aside{position:sticky;top:0;padding:1rem 1.4rem 1rem .4rem;max-height:100vh;
overflow-y:auto}
@media(max-width:1080px){aside{position:static;padding:0 1.4rem 2rem}}
.panel{background:var(--panel);border:1px solid var(--line);border-radius:8px;
padding:.9rem 1rem}
.panel h2{margin:0;font-size:.95rem}
.panel .laneTag{font-size:.65rem;letter-spacing:.08em;text-transform:uppercase;
font-weight:700;margin-bottom:.3rem}
.panel ul{margin:.55rem 0 0;padding-left:1.1rem}
.panel li{margin:.28rem 0;font-size:.82rem}
.panel .hint{color:var(--ink2);font-size:.8rem}
.mut{display:inline-block;margin-top:.55rem;font-size:.68rem;font-weight:700;
border-radius:8px;padding:.1rem .5rem}
.mut.free{background:var(--ok);color:var(--sub)}
.mut.frozen{background:#e9edf3;color:#41506b}
.mut.generated{background:#efe9f5;color:var(--pub)}
.mut.operator{background:#e8ddc9;color:#6b4d10}
.mut.external{background:var(--warn);color:var(--cons)}
footer{padding:.4rem 1.4rem 1.6rem;color:var(--ink2);font-size:.75rem;
max-width:62rem}
@media(prefers-reduced-motion:no-preference){
.node,.e{transition:opacity .15s,box-shadow .15s,stroke-width .15s}}
</style>
<header>
<h1>LTL estate map</h1>
<div class="sub">Every persisting entity of the Lean Transparency Log endeavour, arranged as five lanes of custody click any card for its dossier. The two colored routes are the loops that make this estate hard to hold in one head.</div>
</header>
<div class="facts">
<span class="fact">log <b>13 leaves</b></span>
<span class="fact">root <b class="mono">3488a2d0</b></span>
<span class="fact">key <b class="mono">874c8a00</b></span>
<span class="fact">paper <b>v0.9 · 23 pp · camera-ready</b></span>
<span class="fact">attested components <b>5</b></span>
estate: the SLH-DSA (FIPS 205) campaign enters the map — two new entities Two repos joined the estate on 2026-07-22; both renderings (ESTATE.md + cockpit /estate) gain their cards, with every fact recomputed from the repos themselves: - fips205-source (upstream lane): verbatim snapshot of integritychain/fips205 (pure-Rust FIPS 205 / SLH-DSA), upstream pin 30bac08, snapshot head 5dca0db — single deviation: upstream CI workflows stripped, documented in-commit. Aeneas-compat patches land there as transparent, individually-justified commits; nothing is proposed upstream. - fips205-slhdsa-verified (subject lane): SLH-DSA-SHA2-128s verify-path campaign, marked exactly as its own check.sh says — CAMPAIGN IN PROGRESS, zero certificates, non-green by design. NOT attested; the map does not imply otherwise. Also: - liveness board now probes fips205-slhdsa-verified (a sibling under the default repos root). fips205-source is deliberately NOT probed: the upstream-source shelf lives outside that root, like the five existing source clones (comment documents the decision). - drift tripwire (test_estate_view_and_estate_md_do_not_drift) extended with both new sentinel names. - stale fact chip refreshed in both renderings: pacta suite 135 → 144 green (the suite grew during the cockpit era; chip was never bumped). - estateview's pasta dossier no longer calls the curve layer "the one open verification task in the estate" — the campaign is a second. Suite 144 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 20:02:39 +00:00
<span class="fact">pacta suite <b>144 green</b></span>
<span class="fact">SLH-DSA campaign <b>open 0 certificates</b></span>
<span class="fact">state as of <b>2026-07-22</b></span>
</div>
<div class="facts" style="padding-top:.15rem">
<span class="fact" style="border-color:#1e7f4f"><b style="color:#1e7f4f">ALWAYS ON</b> droplet: caddy (TLS, static blog) &middot; LTL web service (read-only container) &middot; Forgejo (+ 03:00 mirror cron)</span>
<span class="fact" style="border-color:#3b4d8f"><b style="color:#3b4d8f">ON-DEMAND</b> operator machine: append/publish/sign ceremonies &middot; cockpit &middot; MCP &mdash; exist only while invoked</span>
<span class="fact" style="border-color:#a86a10"><b style="color:#a86a10">NOT RUNNING</b> warden: implemented prototype, no deployed instance, no funds watched</span>
<span class="fact"><b>everything else</b>: static files or external parties &mdash; no process at all</span>
</div>
<div class="legend" id="legend">
<span class="lg"><svg width="26" height="8"><line x1="0" y1="4" x2="26" y2="4" stroke="#b6bec9" stroke-width="1.3"/></svg>extract / feed</span>
<span class="lg"><svg width="26" height="8"><line x1="0" y1="4" x2="26" y2="4" stroke="#1e7f4f" stroke-width="1.3"/></svg>attest</span>
<span class="lg"><svg width="26" height="8"><line x1="0" y1="4" x2="26" y2="4" stroke="#3b4d8f" stroke-width="1.3"/></svg>append / publish</span>
<span class="lg"><svg width="26" height="8"><line x1="0" y1="4" x2="26" y2="4" stroke="#3b4d8f" stroke-width="1.3" stroke-dasharray="5 4"/></svg>template (CI-pinned)</span>
<span class="lg"><svg width="26" height="8"><line x1="0" y1="4" x2="26" y2="4" stroke="#6d4a8f" stroke-width="1.3"/></svg>serve / deploy</span>
<span class="lg"><svg width="26" height="8"><line x1="0" y1="4" x2="26" y2="4" stroke="#a86a10" stroke-width="1.3"/></svg>consume</span>
<span class="lg"><svg width="26" height="8"><line x1="0" y1="4" x2="26" y2="4" stroke="#c25e00" stroke-width="2.4"/></svg>Loop 1 dogfood signer</span>
<span class="lg"><svg width="26" height="8"><line x1="0" y1="4" x2="26" y2="4" stroke="#7a2ea0" stroke-width="2.4" stroke-dasharray="8 5"/></svg>Loop 2 self-attestation</span>
</div>
<div class="wrap">
<div class="boardScroll"><div class="board" id="board">
<svg class="edges" id="edgeSvg"></svg>
<div class="lanes">
<div class="lane src"><div class="laneTitle">Upstream inputs · frozen</div>
<div class="col">
<div class="node" id="srcDalek"><h3 class="mono">curve25519-dalek-source</h3><div class="role">upstream Rust, pinned clone</div></div>
<div class="node" id="srcAnza"><h3 class="mono">anza-cryptography-source</h3><div class="role">Solana fork, pinned clone</div></div>
<div class="node" id="srcRisc0"><h3 class="mono">risc0--dalek-source</h3><div class="role">RISC Zero fork, pinned clone</div></div>
<div class="node" id="srcBet"><h3 class="mono">betrusted--dalek-source</h3><div class="role">Betrusted fork (+ xous-core, litex-boards context)</div></div>
<div class="node" id="srcPasta"><h3 class="mono">pasta_curves-source</h3><div class="role">Pasta curves, pinned clone</div></div>
estate: the SLH-DSA (FIPS 205) campaign enters the map — two new entities Two repos joined the estate on 2026-07-22; both renderings (ESTATE.md + cockpit /estate) gain their cards, with every fact recomputed from the repos themselves: - fips205-source (upstream lane): verbatim snapshot of integritychain/fips205 (pure-Rust FIPS 205 / SLH-DSA), upstream pin 30bac08, snapshot head 5dca0db — single deviation: upstream CI workflows stripped, documented in-commit. Aeneas-compat patches land there as transparent, individually-justified commits; nothing is proposed upstream. - fips205-slhdsa-verified (subject lane): SLH-DSA-SHA2-128s verify-path campaign, marked exactly as its own check.sh says — CAMPAIGN IN PROGRESS, zero certificates, non-green by design. NOT attested; the map does not imply otherwise. Also: - liveness board now probes fips205-slhdsa-verified (a sibling under the default repos root). fips205-source is deliberately NOT probed: the upstream-source shelf lives outside that root, like the five existing source clones (comment documents the decision). - drift tripwire (test_estate_view_and_estate_md_do_not_drift) extended with both new sentinel names. - stale fact chip refreshed in both renderings: pacta suite 135 → 144 green (the suite grew during the cockpit era; chip was never bumped). - estateview's pasta dossier no longer calls the curve layer "the one open verification task in the estate" — the campaign is a second. Suite 144 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 20:02:39 +00:00
<div class="node" id="srcFips205"><h3 class="mono">fips205-source</h3><div class="role">integritychain FIPS 205 (SLH-DSA), pinned snapshot</div></div>
</div>
</div>
<div class="lane sub"><div class="laneTitle">Verified subjects</div>
<div class="col">
<div class="node" id="dalek"><h3 class="mono">dalek-ed25519-verified</h3><div class="role">16 certs · leaf 8 (gen 3)</div>
<div class="chips"><span class="chip ok">attested</span><span class="chip l1">signer source</span></div></div>
<div class="node" id="anza"><h3 class="mono">anza-ed25519-verified</h3><div class="role">16 certs · leaf 9</div>
<div class="chips"><span class="chip ok">attested</span></div></div>
<div class="node" id="risc0"><h3 class="mono">risc0-ed25519-verified</h3><div class="role">16 certs · leaf 10</div>
<div class="chips"><span class="chip ok">attested</span></div></div>
<div class="node" id="bet"><h3 class="mono">betrusted-ed25519-verified</h3><div class="role">16 certs · leaf 11</div>
<div class="chips"><span class="chip ok">attested</span></div></div>
<div class="node" id="pasta"><h3 class="mono">pasta-pallas-verified</h3><div class="role">field layer proven · curve layer pending</div>
<div class="chips"><span class="chip warn">not attested</span></div></div>
estate: the SLH-DSA (FIPS 205) campaign enters the map — two new entities Two repos joined the estate on 2026-07-22; both renderings (ESTATE.md + cockpit /estate) gain their cards, with every fact recomputed from the repos themselves: - fips205-source (upstream lane): verbatim snapshot of integritychain/fips205 (pure-Rust FIPS 205 / SLH-DSA), upstream pin 30bac08, snapshot head 5dca0db — single deviation: upstream CI workflows stripped, documented in-commit. Aeneas-compat patches land there as transparent, individually-justified commits; nothing is proposed upstream. - fips205-slhdsa-verified (subject lane): SLH-DSA-SHA2-128s verify-path campaign, marked exactly as its own check.sh says — CAMPAIGN IN PROGRESS, zero certificates, non-green by design. NOT attested; the map does not imply otherwise. Also: - liveness board now probes fips205-slhdsa-verified (a sibling under the default repos root). fips205-source is deliberately NOT probed: the upstream-source shelf lives outside that root, like the five existing source clones (comment documents the decision). - drift tripwire (test_estate_view_and_estate_md_do_not_drift) extended with both new sentinel names. - stale fact chip refreshed in both renderings: pacta suite 135 → 144 green (the suite grew during the cockpit era; chip was never bumped). - estateview's pasta dossier no longer calls the curve layer "the one open verification task in the estate" — the campaign is a second. Suite 144 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 20:02:39 +00:00
<div class="node" id="fips"><h3 class="mono">fips205-slhdsa-verified</h3><div class="role">SLH-DSA-SHA2-128s verify path · skeleton 0 certificates</div>
cockpit: the estate page now MEASURES instead of asserting The /estate page was hand-written prose inside estateview.py: 32 hard-coded fact arrays and zero places reading live data, last edited 2026-07-22. It cannot go stale by accident — it can only go stale, because nothing connected it to the repositories it describes. For eight days it told the operator: · SLH-DSA "campaign in progress", "check.sh exits non-green by design" — while it had 11 proven certificates, a green button, an 18-attack self-test and an outside reviewer's attest-with-conditions; · ed25519 "16 reviewed certificates" — while they had 31 bound certificates and 3022 inventoried constants; · nothing at all about five audit phases and five self-tests per repo, none of which existed on the day the page was last touched. Those four claims are corrected. More importantly the page now carries a MEASURED panel rendered from formal-verification-control's tools/estate-progress.py, which derives every figure from the repositories at generation time. The panel states three things a reader would otherwise have to assume: · WHEN it was measured, and by what; · WHETHER the repositories have moved since — the snapshot records the HEADs it was taken against, and the panel compares them live, naming any repo that has moved rather than quietly showing old numbers as current; · WHICH PART OF THE PAGE IS MEASURED AT ALL. Everything above the panel is labelled, in the page itself, as hand-written prose that can be out of date. That label is the honest part: the map is still prose, and a reader should know which half is which. If the snapshot is absent the panel says NOT MEASURED in words and prints the command to produce one. It never renders nothing, and never falls back to prose — a blank space and a confident-looking stale figure are the same failure, and the second is worse. Two numbers, never one, per PROGRESS-METRIC.md: a single figure is what let the old metric report 100% for work nobody had attacked. All three paths tested: current, moved-since, and absent. 145/145 tests pass, including the sync test guarding drift between this page and ESTATE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 16:24:31 +00:00
<div class="chips"><span class="chip warn">11 certs · reviewer attest-with-conditions</span><span class="chip warn">not attested</span></div></div>
<div class="node" id="corpus"><h3 class="mono">ltl-accumulator-verified</h3><div class="role">61 certs · proofs about the log's own accumulator model</div>
<div class="chips"><span class="chip ok">attested · entry 13</span><span class="chip frz">frozen 172a1d0</span><span class="chip l2">loop 2</span></div></div>
</div>
</div>
<div class="lane mach"><div class="laneTitle">Machinery &amp; operator-held</div>
<div class="col">
<div class="group"><div class="gTitle"><span class="mono">proof-aware-crypto-tooling-agent</span><span style="color:var(--ink2);font-weight:400">(pacta)</span></div>
<div class="col">
<div class="node" id="provider"><h3>Provider service</h3><div class="role">check append publish · site &amp; API code · publish templates</div>
<div class="chips"><span class="chip ok">templates CI-pinned</span></div></div>
<div class="node" id="signer"><h3>Dogfood signer</h3><div class="role">verified-dalek-serial binary signs every head</div>
<div class="chips"><span class="chip l1">loop 1</span></div></div>
<div class="node" id="conslib"><h3>Consumer library</h3><div class="role">verify · pin store · receipts · R0R5 risk model</div></div>
<div class="node" id="wardenCode"><h3>warden (code)</h3><div class="role">quorum-custody wallet · MCP · custody card</div></div>
<div class="node" id="paper"><h3>Paper</h3><div class="role">ltl.tex v0.9 camera-ready · archives v0.1 / v0.2</div></div>
<div class="node" id="course"><h3>Course + llms.txt</h3><div class="role">14 notebooks · agent-readable index</div></div>
</div>
</div>
<div class="group held"><div class="gTitle">Operator-held · never in git</div>
<div class="col">
<div class="node" id="key"><h3>Signing key</h3><div class="role">offline · sole copy + encrypted SD backup</div></div>
<div class="node" id="opstate"><h3>Operational log state</h3><div class="role">transparency-log-main the true accumulator</div></div>
<div class="node" id="sd"><h3>Evidence archive (offline)</h3><div class="role">review kits · stamped artifacts</div></div>
</div>
</div>
</div>
</div>
<div class="lane pub"><div class="laneTitle">Published faces</div>
<div class="col">
<div class="node" id="mirror"><h3 class="mono">lean-transparency-log</h3><div class="role">public mirror leaves, heads, receipts, fail-closed verify.py + selftest</div>
<div class="chips"><span class="chip gen">generated by publish</span></div></div>
<div class="node" id="site"><h3 class="mono">ltl.zkdefi.org</h3><div class="role">homepage from live leaves · /v1 API · /paper (+v0.2, v0.1) · key endpoint</div></div>
<div class="node" id="forgejo"><h3>Forgejo mirror</h3><div class="role">droplet · nightly 03:00 · full saymrwulf account</div>
<div class="chips"><span class="chip gen">disaster copy</span></div></div>
<div class="node" id="pcs"><h3>Infra as code (private)</h3><div class="role">droplet configuration in a private repo unnamed so this map stays shareable</div></div>
<div class="node" id="book"><h3 class="mono">verifying-crypto-with-lean</h3><div class="role">undergraduate book educational face, no LTL coupling</div></div>
</div>
</div>
<div class="lane cons"><div class="laneTitle">Consumers</div>
<div class="col">
<div class="node" id="cloner"><h3>Offline cloner</h3><div class="role">git clone verify.py --all (fails closed) own witness view</div></div>
<div class="node" id="wardenRun"><h3>warden (runtime)</h3><div class="role">internal consumer quorum of 4 attested fork verifiers</div></div>
<div class="node" id="agents"><h3>Agents</h3><div class="role">MCP tools · custody card with embedded inclusion proofs</div></div>
<div class="node" id="swiss"><h3 class="mono">swisspost-evoting-go-poc</h3><div class="role">prospective dalek family-level match only, no receipt code</div>
<div class="chips"><span class="chip warn">prospective</span></div></div>
<div class="node" id="reviewers"><h3>External reviewers</h3><div class="role">GPT-5.6 + Claude adversarial consumers of paper, corpus, log</div></div>
</div>
</div>
</div>
</div></div>
<aside><div class="panel" id="panel">
<div class="laneTag" style="color:var(--ink2)">Dossier</div>
<h2>Click any card</h2>
<p class="hint">Hovering highlights a card's edges; clicking pins its dossier here. The board scrolls sideways if your window is narrow.</p>
</div></aside>
</div>
<footer>
Canonical committed version: <span class="mono">ESTATE.md</span> in the pacta repo (prose + Mermaid + the What-is-running table). This page is its human-facing rendering, served read-only by the cockpit. Excluded by design: unrelated saymrwulf repos, and the operator-private detail beneath the three dark cards.
</footer>
<script>
const RUNTIME = {
srcDalek:"frozen clone — nothing runs", srcAnza:"frozen clone — nothing runs",
srcRisc0:"frozen clone — nothing runs", srcBet:"frozen clone — nothing runs",
srcPasta:"frozen clone — nothing runs",
estate: the SLH-DSA (FIPS 205) campaign enters the map — two new entities Two repos joined the estate on 2026-07-22; both renderings (ESTATE.md + cockpit /estate) gain their cards, with every fact recomputed from the repos themselves: - fips205-source (upstream lane): verbatim snapshot of integritychain/fips205 (pure-Rust FIPS 205 / SLH-DSA), upstream pin 30bac08, snapshot head 5dca0db — single deviation: upstream CI workflows stripped, documented in-commit. Aeneas-compat patches land there as transparent, individually-justified commits; nothing is proposed upstream. - fips205-slhdsa-verified (subject lane): SLH-DSA-SHA2-128s verify-path campaign, marked exactly as its own check.sh says — CAMPAIGN IN PROGRESS, zero certificates, non-green by design. NOT attested; the map does not imply otherwise. Also: - liveness board now probes fips205-slhdsa-verified (a sibling under the default repos root). fips205-source is deliberately NOT probed: the upstream-source shelf lives outside that root, like the five existing source clones (comment documents the decision). - drift tripwire (test_estate_view_and_estate_md_do_not_drift) extended with both new sentinel names. - stale fact chip refreshed in both renderings: pacta suite 135 → 144 green (the suite grew during the cockpit era; chip was never bumped). - estateview's pasta dossier no longer calls the curve layer "the one open verification task in the estate" — the campaign is a second. Suite 144 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 20:02:39 +00:00
srcFips205:"pinned snapshot — nothing runs; moves only for documented Aeneas-compat patches",
dalek:"static repo — proofs replay on demand", anza:"static repo — proofs replay on demand",
risc0:"static repo — proofs replay on demand", bet:"static repo — proofs replay on demand",
pasta:"static repo — open work, run manually", corpus:"frozen repo — replay on demand",
cockpit: the estate page now MEASURES instead of asserting The /estate page was hand-written prose inside estateview.py: 32 hard-coded fact arrays and zero places reading live data, last edited 2026-07-22. It cannot go stale by accident — it can only go stale, because nothing connected it to the repositories it describes. For eight days it told the operator: · SLH-DSA "campaign in progress", "check.sh exits non-green by design" — while it had 11 proven certificates, a green button, an 18-attack self-test and an outside reviewer's attest-with-conditions; · ed25519 "16 reviewed certificates" — while they had 31 bound certificates and 3022 inventoried constants; · nothing at all about five audit phases and five self-tests per repo, none of which existed on the day the page was last touched. Those four claims are corrected. More importantly the page now carries a MEASURED panel rendered from formal-verification-control's tools/estate-progress.py, which derives every figure from the repositories at generation time. The panel states three things a reader would otherwise have to assume: · WHEN it was measured, and by what; · WHETHER the repositories have moved since — the snapshot records the HEADs it was taken against, and the panel compares them live, naming any repo that has moved rather than quietly showing old numbers as current; · WHICH PART OF THE PAGE IS MEASURED AT ALL. Everything above the panel is labelled, in the page itself, as hand-written prose that can be out of date. That label is the honest part: the map is still prose, and a reader should know which half is which. If the snapshot is absent the panel says NOT MEASURED in words and prints the command to produce one. It never renders nothing, and never falls back to prose — a blank space and a confident-looking stale figure are the same failure, and the second is worse. Two numbers, never one, per PROGRESS-METRIC.md: a single figure is what let the old metric report 100% for work nobody had attacked. All three paths tested: current, moved-since, and absent. 145/145 tests pass, including the sync test guarding drift between this page and ESTATE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 16:24:31 +00:00
fips:"static repo — no process; campaign sessions are episodic operator-machine runs under lean-guard; check.sh GREEN with an 18-attack self-test",
provider:"SPLIT: the write side (check/append/publish) runs ON DEMAND on the operator machine, only during a ceremony; the read-only web face runs ALWAYS ON in the droplet container",
signer:"on demand — invoked only while signing during a ceremony; key offline otherwise",
conslib:"library — runs inside whichever consumer invokes it",
wardenCode:"NOT RUNNING — implemented prototype; no deployed instance",
paper:"static files, served by the always-on site",
course:"static; regenerated manually",
key:"OFFLINE — touched only during signing ceremonies, with per-command operator grant",
opstate:"dormant files between ceremonies — no process",
sd:"offline medium",
mirror:"static git repo — no process; consumers run verify.py themselves",
site:"ALWAYS ON — droplet container (pacta_provider serve), read-only mounts, read_only:true, no key material",
forgejo:"ALWAYS ON — droplet container; one cron: 03:00 mirror reconcile",
pcs:"config files — deployed by hand",
book:"static repo",
cloner:"external, episodic",
wardenRun:"NOT RUNNING — starts only when the operator or an agent launches MCP or the cockpit, stops with them",
agents:"external, episodic", swiss:"external, dormant since 2026-07-07",
reviewers:"external, per review round",
};
const DOSSIER = {
srcDalek:{lane:"Upstream inputs",mut:"frozen",facts:["Pinned clone of upstream curve25519-dalek + ed25519-dalek (one implementation: curve crate + signature crate).","Input to Aeneas/Charon extraction; never modified here.","Excluded from all maintenance passes by standing order."]},
srcAnza:{lane:"Upstream inputs",mut:"frozen",facts:["Pinned clone of the Solana/Anza cryptography fork.","Input to extraction; never modified."]},
srcRisc0:{lane:"Upstream inputs",mut:"frozen",facts:["Pinned clone of the RISC Zero dalek fork.","Input to extraction; never modified."]},
srcBet:{lane:"Upstream inputs",mut:"frozen",facts:["Pinned clone of the Betrusted dalek fork.","xous-core and litex-boards sit alongside as platform context.","Input to extraction; never modified."]},
srcPasta:{lane:"Upstream inputs",mut:"frozen",facts:["Pinned clone of the Pasta curves crate.","Feeds pasta-pallas-verified; never modified."]},
estate: the SLH-DSA (FIPS 205) campaign enters the map — two new entities Two repos joined the estate on 2026-07-22; both renderings (ESTATE.md + cockpit /estate) gain their cards, with every fact recomputed from the repos themselves: - fips205-source (upstream lane): verbatim snapshot of integritychain/fips205 (pure-Rust FIPS 205 / SLH-DSA), upstream pin 30bac08, snapshot head 5dca0db — single deviation: upstream CI workflows stripped, documented in-commit. Aeneas-compat patches land there as transparent, individually-justified commits; nothing is proposed upstream. - fips205-slhdsa-verified (subject lane): SLH-DSA-SHA2-128s verify-path campaign, marked exactly as its own check.sh says — CAMPAIGN IN PROGRESS, zero certificates, non-green by design. NOT attested; the map does not imply otherwise. Also: - liveness board now probes fips205-slhdsa-verified (a sibling under the default repos root). fips205-source is deliberately NOT probed: the upstream-source shelf lives outside that root, like the five existing source clones (comment documents the decision). - drift tripwire (test_estate_view_and_estate_md_do_not_drift) extended with both new sentinel names. - stale fact chip refreshed in both renderings: pacta suite 135 → 144 green (the suite grew during the cockpit era; chip was never bumped). - estateview's pasta dossier no longer calls the curve layer "the one open verification task in the estate" — the campaign is a second. Suite 144 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 20:02:39 +00:00
srcFips205:{lane:"Upstream inputs",mut:"frozen",facts:["Verbatim snapshot of integritychain/fips205 — pure-Rust FIPS 205 / SLH-DSA (zero unsafe, no_std, const-generic).","Pinned at upstream 30bac08 (2025-09-01); snapshot head 5dca0db — the single deviation from verbatim is stripping upstream CI workflows, documented in that commit.","Aeneas-compat patches land HERE as transparent, individually-justified commits; nothing is proposed upstream (no affiliation)."]},
cockpit: the estate page now MEASURES instead of asserting The /estate page was hand-written prose inside estateview.py: 32 hard-coded fact arrays and zero places reading live data, last edited 2026-07-22. It cannot go stale by accident — it can only go stale, because nothing connected it to the repositories it describes. For eight days it told the operator: · SLH-DSA "campaign in progress", "check.sh exits non-green by design" — while it had 11 proven certificates, a green button, an 18-attack self-test and an outside reviewer's attest-with-conditions; · ed25519 "16 reviewed certificates" — while they had 31 bound certificates and 3022 inventoried constants; · nothing at all about five audit phases and five self-tests per repo, none of which existed on the day the page was last touched. Those four claims are corrected. More importantly the page now carries a MEASURED panel rendered from formal-verification-control's tools/estate-progress.py, which derives every figure from the repositories at generation time. The panel states three things a reader would otherwise have to assume: · WHEN it was measured, and by what; · WHETHER the repositories have moved since — the snapshot records the HEADs it was taken against, and the panel compares them live, naming any repo that has moved rather than quietly showing old numbers as current; · WHICH PART OF THE PAGE IS MEASURED AT ALL. Everything above the panel is labelled, in the page itself, as hand-written prose that can be out of date. That label is the honest part: the map is still prose, and a reader should know which half is which. If the snapshot is absent the panel says NOT MEASURED in words and prints the command to produce one. It never renders nothing, and never falls back to prose — a blank space and a confident-looking stale figure are the same failure, and the second is worse. Two numbers, never one, per PROGRESS-METRIC.md: a single figure is what let the old metric report 100% for work nobody had attacked. All three paths tested: current, moved-since, and absent. 145/145 tests pass, including the sync test guarding drift between this page and ESTATE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 16:24:31 +00:00
dalek:{lane:"Verified subjects",mut:"frozen",facts:["31 bound certificates (field, group law, scalars, signature apex T1T4) and 3022 inventoried constants; 16 of the certificates are the curated attested subset in the log.","Attested in all three log generations; current leaf 8.","LOOP 1 anchor: the dogfood signer binary is built from this source — the log's heads are signed by code whose proofs are inside the log.","Attestation pins a commit; the branch only moves for docs."]},
anza:{lane:"Verified subjects",mut:"frozen",facts:["31 bound certificates, 3022 inventoried constants; attested subset is 16; current leaf 9.","Same proof pyramid as dalek, rebuilt for the fork's code structure."]},
risc0:{lane:"Verified subjects",mut:"frozen",facts:["31 bound certificates, 3022 inventoried constants; attested subset is 16; current leaf 10.","Differs from Betrusted's corpus by 27 changed proof lines (the paper's portability datum)."]},
bet:{lane:"Verified subjects",mut:"frozen",facts:["31 bound certificates, 3022 inventoried constants; attested subset is 16; current leaf 11."]},
estate: the SLH-DSA (FIPS 205) campaign enters the map — two new entities Two repos joined the estate on 2026-07-22; both renderings (ESTATE.md + cockpit /estate) gain their cards, with every fact recomputed from the repos themselves: - fips205-source (upstream lane): verbatim snapshot of integritychain/fips205 (pure-Rust FIPS 205 / SLH-DSA), upstream pin 30bac08, snapshot head 5dca0db — single deviation: upstream CI workflows stripped, documented in-commit. Aeneas-compat patches land there as transparent, individually-justified commits; nothing is proposed upstream. - fips205-slhdsa-verified (subject lane): SLH-DSA-SHA2-128s verify-path campaign, marked exactly as its own check.sh says — CAMPAIGN IN PROGRESS, zero certificates, non-green by design. NOT attested; the map does not imply otherwise. Also: - liveness board now probes fips205-slhdsa-verified (a sibling under the default repos root). fips205-source is deliberately NOT probed: the upstream-source shelf lives outside that root, like the five existing source clones (comment documents the decision). - drift tripwire (test_estate_view_and_estate_md_do_not_drift) extended with both new sentinel names. - stale fact chip refreshed in both renderings: pacta suite 135 → 144 green (the suite grew during the cockpit era; chip was never bumped). - estateview's pasta dossier no longer calls the curve layer "the one open verification task in the estate" — the campaign is a second. Suite 144 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 20:02:39 +00:00
pasta:{lane:"Verified subjects",mut:"free",facts:["Field layer proven from own extraction; curve layer (group law + scalar mul) remains open work.","NOT attested — the log carries only the four Ed25519 forks + the corpus."]},
fips:{lane:"Verified subjects",mut:"free",facts:["CAMPAIGN IN PROGRESS — ZERO certificates: verification/check.sh exits non-green and says so; that script is the only source of the word «proven» for this repo.","Scope: the FIPS 205 verify path only (slh_verify → fors / hypertree → xmss → wots → chain), parameter set SLH-DSA-SHA2-128s; keygen and signing are trusted base, exactly as ed25519 signing was.","The six SHA-2 hash oracles are opaque external models (TRUSTED-BASE.md), kept outside every future certificate's dependency cone.","Gate-0 (2026-07-22): Charon clean; Aeneas translated the whole cone with exactly one obstruction class (the Hashers fn-pointer struct) — campaign phase 1 is the compat patch in fips205-source.","NOT attested — the log carries nothing from this campaign yet."]},
corpus:{lane:"Verified subjects",mut:"frozen",facts:["61 certificates over one boundary axiom (LTLAcc.sha256); 222-constant environment inventory; 15-gap honest ledger.","Mechanizes the archived report's §6: extractors, consistency binding, per-step pin safety.","LOOP 2 anchor: attested INTO the log as entry 13 — the log carries kernel-checked proofs about its own accumulator model.","Frozen at 172a1d0 (the attested commit); doc-only commits may move the branch.","Docs carry numbering notes: paper references are v0.2 numbering."]},
provider:{lane:"pacta · machinery",mut:"free",facts:["pacta_provider: attestation check → log-append → log-publish; webdocs homepage + /v1 API code.","Holds the publish TEMPLATES for the mirror's verify.py / selftest / README — since 2026-07-19 pinned by CI (test_published_assets) after the audit caught a stale fail-open template.","Deploys to the droplet as the ltl container."]},
signer:{lane:"pacta · machinery",mut:"free",facts:["verified-dalek-serial: the Ed25519 binary built from the attested dalek source.","Signs every tree head; before signing, the provider re-checks inclusion of the signer's own leaf.","LOOP 1: signature vouches for the tree; the tree contains the attestation of the signer's source (leaf 8). Execution provenance is reported, not proven — stated in the paper."]},
conslib:{lane:"pacta · machinery",mut:"free",facts:["src/pacta: receipt verification, pin store (rollback rejection, fork evidence), R0R5 risk model, claim cards.","The deployed iterative verifiers the paper differential-tests against the recursive model live here."]},
wardenCode:{lane:"pacta · machinery",mut:"free",facts:["WALLET.md: custody capsule, hash-chained ledger, inbound quorum boundary, outbound signing firewall.","Inbound: accepts log-derived statements only when independently attested verifier backends agree.","Agent surfaces: MCP over stdio, custody card, posture challenge, refusal receipts."]},
paper:{lane:"pacta · machinery",mut:"free",facts:["paper/ltl.tex — v0.9 camera-ready, 23 pages: trust decomposition, accountability games with explicit reductions, deployed evaluation.","Archives: v0.1 (4 pp) and v0.2 (19 pp, the corpus's numbering reference) kept and served.","Submission package + webform field set staged on the SD archive."]},
course:{lane:"pacta · machinery",mut:"free",facts:["14 Jupyter notebooks generated from scripts/build_curriculum_notebooks.py (fix the generator, then the notebook).","llms.txt: the agent-readable index of the whole endeavour."]},
key:{lane:"Operator-held",mut:"operator",facts:["Ed25519 signing key, fingerprint 874c8a00… — the log's identity.","Offline; never on the server; the agent never touches it without an explicit per-command grant.","Public half published at two independent locations (site + mirror) for TOFU comparison."]},
opstate:{lane:"Operator-held",mut:"operator",facts:["provider/state/transparency-log-main: the true accumulator — appends happen HERE, the mirror is its projection.","Lesson learned in rehearsal: rebuild the tree from operational state, never from published projections."]},
sd:{lane:"Operator-held",mut:"operator",facts:["Review kits (rounds 115), stamped artifacts (_timestamp_hash8 convention), and execution evidence records.","Kept offline; never in any git repo."]},
mirror:{lane:"Published faces",mut:"generated",facts:["The git-published log: 13 leaves, 6 signed heads (sizes 813), receipts, provider key, fail-closed verify.py + 11-case selftest.","GENERATED by log-publish from operational state + pacta templates — direct commits here must be mirrored back into the templates (that is the defect the 2026-07-19 audit caught).","Cloning it makes anyone a witness: verify.py --all re-verifies everything offline."]},
site:{lane:"Published faces",mut:"generated",facts:["Droplet: caddy → docker (cloud-ltl-1). Homepage rendered live from real leaves — the counts on the page ARE the accumulator.","/v1/sth, /v1/attestation, /v1/proof, /log-public-key; /paper serves v0.9, /paper/v0.2 and /paper/v0.1 the archives.","Read-only; no key material on the server."]},
forgejo:{lane:"Published faces",mut:"generated",facts:["cloud-forgejo-1 on the droplet: nightly (03:00) mirror of the ENTIRE saymrwulf GitHub account — disaster-recovery copy, not a curated set."]},
pcs:{lane:"Published faces",mut:"free",facts:["The droplet's deployment configuration (compose stack, reverse proxy, reconstruct step), maintained in a private repository.","Deliberately unnamed here: the public estate lists only entities whose existence must be public for trust.","Captured under version control after an audit found the deployment was not."]},
book:{lane:"Published faces",mut:"free",facts:["The undergraduate book (twelve chapters + solutions): from 1+1=2 to reading the estate's real proofs.","Audited 2026-07-19: zero coupling to log/paper state — safely independent."]},
cloner:{lane:"Consumers",mut:"external",facts:["Anyone: git clone the mirror, run verify.py --all (stdlib + openssl; FAILS CLOSED without signature capability).","Retention makes them a witness: their clone can later expose an equivocating head."]},
wardenRun:{lane:"Consumers",mut:"free",facts:["The estate's own dogfood consumer: signs nothing inbound unless a quorum of independently attested verifier backends agrees.","Code lives in pacta (left lane); shown here in its consuming role. The paper calls it the implemented internal prototype."]},
agents:{lane:"Consumers",mut:"external",facts:["MCP tools (wallet_status, verify_inbound, request_signature, …) and the self-proving custody card: embedded inclusion proofs a counterparty recomputes rather than trusts."]},
swiss:{lane:"Consumers",mut:"external",facts:["The operator's Go PoC of the Swiss Post e-voting system.","Its vendored dalek dependency matches an attested subject at FAMILY level, not the attested version — the paper's version-exactness negative (kept anonymous there).","No receipt code yet; strictly prospective."]},
reviewers:{lane:"Consumers",mut:"external",facts:["GPT-5.6 + a Claude reviewer: fifteen adversarial rounds over corpus, log, site, and paper.","Fed via SD kits; findings drove every hardening round; both re-derived the log's cryptography independently."]},
};
const EDGES = [
["srcDalek","dalek","","extract"],["srcAnza","anza","","extract"],
["srcRisc0","risc0","","extract"],["srcBet","bet","","extract"],
["srcPasta","pasta","","extract"],
estate: the SLH-DSA (FIPS 205) campaign enters the map — two new entities Two repos joined the estate on 2026-07-22; both renderings (ESTATE.md + cockpit /estate) gain their cards, with every fact recomputed from the repos themselves: - fips205-source (upstream lane): verbatim snapshot of integritychain/fips205 (pure-Rust FIPS 205 / SLH-DSA), upstream pin 30bac08, snapshot head 5dca0db — single deviation: upstream CI workflows stripped, documented in-commit. Aeneas-compat patches land there as transparent, individually-justified commits; nothing is proposed upstream. - fips205-slhdsa-verified (subject lane): SLH-DSA-SHA2-128s verify-path campaign, marked exactly as its own check.sh says — CAMPAIGN IN PROGRESS, zero certificates, non-green by design. NOT attested; the map does not imply otherwise. Also: - liveness board now probes fips205-slhdsa-verified (a sibling under the default repos root). fips205-source is deliberately NOT probed: the upstream-source shelf lives outside that root, like the five existing source clones (comment documents the decision). - drift tripwire (test_estate_view_and_estate_md_do_not_drift) extended with both new sentinel names. - stale fact chip refreshed in both renderings: pacta suite 135 → 144 green (the suite grew during the cockpit era; chip was never bumped). - estateview's pasta dossier no longer calls the curve layer "the one open verification task in the estate" — the campaign is a second. Suite 144 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 20:02:39 +00:00
["srcFips205","fips","","extract"],
["dalek","provider","","attest"],["anza","provider","","attest"],
["risc0","provider","","attest"],["bet","provider","","attest"],
["provider","opstate","append","publish"],
["key","opstate","signs heads","publish"],
["opstate","mirror","publish","publish"],
["provider","mirror","templates","tmpl"],
["provider","site","app code","serve"],
["mirror","site","published copy","serve"],
["paper","site","/paper","serve"],
["pcs","site","infra","serve"],
["mirror","forgejo","nightly","sync"],
["mirror","cloner","clone + verify","consume"],
["site","agents","API · custody card","consume"],
["mirror","wardenRun","receipts · quorum","consume"],
["site","swiss","prospective","pros"],
["sd","reviewers","kits","consume"],
["dalek","signer","built from","loop1"],
["signer","opstate","signs the log","loop1"],
["mirror","dalek","contains the signer's own attestation (leaf 8)","loop1"],
["corpus","provider","attested (entry 13)","loop2"],
["mirror","corpus","carries proofs about its own accumulator","loop2"],
];
const board=document.getElementById("board"),svg=document.getElementById("edgeSvg");
const NS="http://www.w3.org/2000/svg";
function anchors(id){const el=document.getElementById(id),b=board.getBoundingClientRect(),r=el.getBoundingClientRect();
return {L:{x:r.left-b.left,y:r.top-b.top+r.height/2},R:{x:r.right-b.left,y:r.top-b.top+r.height/2}};}
let edgeEls=[];
function draw(){
svg.innerHTML="";svg.setAttribute("width",board.scrollWidth);
svg.setAttribute("height",board.scrollHeight);edgeEls=[];
const defs=document.createElementNS(NS,"defs");
[["#b6bec9","m0"],["#1e7f4f","m1"],["#3b4d8f","m2"],["#6d4a8f","m3"],
["#a86a10","m4"],["#c25e00","m5"],["#7a2ea0","m6"]].forEach(([c,id])=>{
const m=document.createElementNS(NS,"marker");
m.setAttribute("id",id);m.setAttribute("viewBox","0 0 8 8");
m.setAttribute("refX","7");m.setAttribute("refY","4");
m.setAttribute("markerWidth","5.5");m.setAttribute("markerHeight","5.5");
m.setAttribute("orient","auto");
const p=document.createElementNS(NS,"path");
p.setAttribute("d","M0 0 L8 4 L0 8 z");p.setAttribute("fill",c);
m.appendChild(p);defs.appendChild(m);});
svg.appendChild(defs);
const mk={extract:"m0",attest:"m1",publish:"m2",tmpl:"m2",serve:"m3",
sync:"m3",consume:"m4",pros:"m4",loop1:"m5",loop2:"m6"};
EDGES.forEach(([f,t,label,type])=>{
const A=anchors(f),B=anchors(t);
const back=B.L.x<A.R.x-20;
let s,e,d;
if(!back){s=A.R;e=B.L;
const dx=Math.max(36,(e.x-s.x)*.42);
d=`M${s.x} ${s.y} C ${s.x+dx} ${s.y}, ${e.x-dx} ${e.y}, ${e.x-6} ${e.y}`;}
else{s=A.L;e=B.R; // return edge (loops): swing beneath the lanes
const drop=Math.max(s.y,e.y)+70+(type==="loop2"?36:0);
d=`M${s.x} ${s.y} C ${s.x-70} ${s.y+30}, ${s.x-70} ${drop}, ${(s.x+e.x)/2} ${drop}
S ${e.x+70} ${e.y+30}, ${e.x+6} ${e.y}`;}
const p=document.createElementNS(NS,"path");
p.setAttribute("d",d);p.setAttribute("class","e "+type);
p.setAttribute("marker-end",`url(#${mk[type]})`);
p.dataset.f=f;p.dataset.t=t;svg.appendChild(p);edgeEls.push(p);
if(label){const tx=document.createElementNS(NS,"text");
tx.setAttribute("class","eLabel "+(type.startsWith("loop")?type:""));
const midx=back?(s.x+e.x)/2:(s.x+e.x)/2, midy=back?Math.max(s.y,e.y)+66+(type==="loop2"?36:0):(s.y+e.y)/2-5;
tx.setAttribute("x",midx);tx.setAttribute("y",midy);
tx.setAttribute("text-anchor","middle");tx.textContent=label;
tx.dataset.f=f;tx.dataset.t=t;svg.appendChild(tx);}});
}
function related(id){const s=new Set([id]);
EDGES.forEach(([f,t])=>{if(f===id)s.add(t);if(t===id)s.add(f);});return s;}
let pinned=null;
function highlight(id){
const rel=id?related(id):null;
document.querySelectorAll(".node").forEach(n=>{
n.classList.toggle("dim",!!rel&&!rel.has(n.id));
n.classList.toggle("pinned",n.id===pinned);});
edgeEls.forEach(p=>{const on=!rel||(p.dataset.f===id||p.dataset.t===id);
p.classList.toggle("faded",!!rel&&!on);
p.classList.toggle("hot",!!rel&&on);});
}
function showPanel(id){
const d=DOSSIER[id];if(!d)return;
const el=document.getElementById(id);
const title=el.querySelector("h3").textContent;
const chips=[...el.querySelectorAll(".chip")].map(c=>c.outerHTML).join(" ");
const mutText={free:"changes freely",frozen:"frozen / pinned",
generated:"generated — fix the source, not this",
operator:"operator-only",external:"external party"}[d.mut];
const rt = RUNTIME[id] || "";
document.getElementById("panel").innerHTML=
`<div class="laneTag">${d.lane}</div><h2>${title}</h2>
<div class="chips" style="margin-top:.4rem">${chips}</div>
${rt ? `<p style="font-size:.78rem;margin:.5rem 0 0"><b>Runtime:</b> ${rt}</p>` : ""}
<ul>${d.facts.map(f=>`<li>${f}</li>`).join("")}</ul>
<span class="mut ${d.mut}">${mutText}</span>`;
}
document.querySelectorAll(".node").forEach(n=>{
n.tabIndex=0;
n.addEventListener("mouseenter",()=>{if(!pinned)highlight(n.id);});
n.addEventListener("mouseleave",()=>{if(!pinned)highlight(null);});
n.addEventListener("click",e=>{e.stopPropagation();
pinned=(pinned===n.id)?null:n.id;
highlight(pinned);showPanel(n.id);});
n.addEventListener("keydown",e=>{if(e.key==="Enter"||e.key===" "){
e.preventDefault();n.click();}});
});
document.body.addEventListener("click",e=>{
if(!e.target.closest(".node")&&pinned){pinned=null;highlight(null);}});
window.addEventListener("resize",()=>requestAnimationFrame(draw));
requestAnimationFrame(draw);setTimeout(draw,150);
</script>
'''
cockpit: the estate page now MEASURES instead of asserting The /estate page was hand-written prose inside estateview.py: 32 hard-coded fact arrays and zero places reading live data, last edited 2026-07-22. It cannot go stale by accident — it can only go stale, because nothing connected it to the repositories it describes. For eight days it told the operator: · SLH-DSA "campaign in progress", "check.sh exits non-green by design" — while it had 11 proven certificates, a green button, an 18-attack self-test and an outside reviewer's attest-with-conditions; · ed25519 "16 reviewed certificates" — while they had 31 bound certificates and 3022 inventoried constants; · nothing at all about five audit phases and five self-tests per repo, none of which existed on the day the page was last touched. Those four claims are corrected. More importantly the page now carries a MEASURED panel rendered from formal-verification-control's tools/estate-progress.py, which derives every figure from the repositories at generation time. The panel states three things a reader would otherwise have to assume: · WHEN it was measured, and by what; · WHETHER the repositories have moved since — the snapshot records the HEADs it was taken against, and the panel compares them live, naming any repo that has moved rather than quietly showing old numbers as current; · WHICH PART OF THE PAGE IS MEASURED AT ALL. Everything above the panel is labelled, in the page itself, as hand-written prose that can be out of date. That label is the honest part: the map is still prose, and a reader should know which half is which. If the snapshot is absent the panel says NOT MEASURED in words and prints the command to produce one. It never renders nothing, and never falls back to prose — a blank space and a confident-looking stale figure are the same failure, and the second is worse. Two numbers, never one, per PROGRESS-METRIC.md: a single figure is what let the old metric report 100% for work nobody had attacked. All three paths tested: current, moved-since, and absent. 145/145 tests pass, including the sync test guarding drift between this page and ESTATE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 16:24:31 +00:00
# ─────────────────────────────────────────────────────────────────────────────
# MEASURED PROGRESS PANEL
#
# Everything above this line is hand-written prose. That is why, between
# 2026-07-22 and 2026-07-30, this page told the operator that the SLH-DSA
# campaign was "in progress" with a button "non-green by design" while it had
# eleven proven certificates and a green button, and that the ed25519 forks had
# "16 reviewed certificates" while they had 31 bound and 3022 inventoried. A
# page that asserts cannot notice it has gone out of date; only a page that
# measures can.
#
# So this panel renders ONLY what formal-verification-control's
# tools/estate-progress.py derived from the repositories, and it states three
# things a reader would otherwise have to assume: when it was measured, whether
# the repositories have moved since, and which parts of this page are measured
# at all. If there is no snapshot it renders that fact loudly rather than
# quietly rendering nothing.
# ─────────────────────────────────────────────────────────────────────────────
import json as _json
import os as _os
import subprocess as _sp
PROGRESS_JSON = _os.environ.get(
"PACTA_PROGRESS_JSON",
"/home/oho/GitClone/FormalVerification/formal-verification-control/ESTATE-PROGRESS.json")
ESTATE_ROOT = _os.environ.get(
"ESTATE_ROOT", "/home/oho/GitClone/Claude/FormalVerification")
def _live_head(repo: str):
try:
r = _sp.run(["git", "-C", _os.path.join(ESTATE_ROOT, repo),
"rev-parse", "--short", "HEAD"],
capture_output=True, text=True, timeout=5)
return r.stdout.strip() or None
except Exception:
return None
def _panel(cls: str, title: str, body: str) -> str:
return (f'<section class="mprog {cls}"><h2>{title}</h2>{body}</section>')
def progress_panel() -> str:
"""The measured half of this page. Never falls back to prose."""
style = """
<style>
.mprog{max-width:62rem;margin:1.2rem 1.4rem;padding:1rem 1.2rem;
border:1px solid var(--line);border-radius:8px;background:var(--panel)}
.mprog h2{margin:.1rem 0 .5rem;font-size:1rem}
.mprog.warn{background:var(--warn);border-color:#e0b877}
.mprog.bad{background:#fdecea;border-color:#e3a7a0}
.mprog table{border-collapse:collapse;width:100%;font-size:.86rem}
.mprog th,.mprog td{text-align:left;padding:.28rem .5rem;border-bottom:1px solid var(--line)}
.mprog .num{text-align:right;font-variant-numeric:tabular-nums}
.mprog .note{color:var(--ink2);font-size:.78rem;margin-top:.6rem}
.bar{height:.5rem;background:#eef1f5;border-radius:3px;overflow:hidden;min-width:7rem}
.bar>i{display:block;height:100%;background:var(--sub)}
</style>"""
if not _os.path.exists(PROGRESS_JSON):
return style + _panel("bad", "Progress: NOT MEASURED", f"""
<p>No snapshot at <code>{PROGRESS_JSON}</code>, so this page is showing
you <em>nothing</em> rather than something stale. That is deliberate:
the previous version of this page displayed hand-typed claims that were
eight days out of date, and looked exactly as confident as this one.</p>
<p>To populate it:
<code>formal-verification-control/tools/estate-progress.py --json</code></p>""")
try:
d = _json.load(open(PROGRESS_JSON))
except Exception as e:
return style + _panel("bad", "Progress: SNAPSHOT UNREADABLE", f"<p>{e}</p>")
moved = []
for repo, recorded in (d.get("repo_heads") or {}).items():
live = _live_head(repo)
if live and recorded and live != recorded:
moved.append((repo, recorded, live))
rows = []
for c in d["campaigns"]:
ax = c["axes"]
for axis, label in (("proof", "act one · proof"), ("attestation", "act two · attestation")):
if axis not in ax:
continue
a = ax[axis]
unm = (f' <span title="only a human or an outside party can establish these">'
f'+{a["unmeasurable"]} unmeasurable</span>' if a["unmeasurable"] else "")
rows.append(
f'<tr><td>{c["title"]}</td><td>{label}</td>'
f'<td class="num">{a["earned"]} / {a["identified"]}</td>'
f'<td><div class="bar"><i style="width:{a["pct"]:.0f}%"></i></div></td>'
f'<td class="num">{a["pct"]}%{unm}</td>'
f'<td>{c["reproduction_note"]}</td></tr>')
t = d["totals"]
head = (f'<p><strong>act one — proof {t["proof"]["pct"]}%</strong> · '
f'<strong>act two — attestation {t["attestation"]["pct"]}%</strong> '
f'<span class="note">(two numbers, never one: a single figure is what let the '
f'old metric report 100% for work nobody had attacked)</span></p>')
table = ('<table><tr><th>campaign</th><th>axis</th><th class="num">band-points</th>'
'<th></th><th class="num">verified</th><th>reproduction</th></tr>'
+ "".join(rows) + "</table>")
contra = ""
if d.get("contradictions"):
items = "".join(f"<li><code>{c['id']}</code>: {c['detail']}</li>"
for c in d["contradictions"])
contra = (f'<p><strong>The ledger contradicts the repositories.</strong> '
f'These numbers are not trustworthy until this list is empty:</p><ul>{items}</ul>')
note = (f'<p class="note">Measured {d["generated_at"]} by <code>{d["generator"]}</code>, '
f'from the repositories as they were at that moment. Nothing here is cached or '
f'carried forward. <strong>Everything on this page ABOVE this panel is '
f'hand-written prose</strong> and can be out of date; only this panel is derived.</p>')
if moved:
rowsm = "".join(f"<li><code>{r}</code>: measured at <code>{a}</code>, "
f"now <code>{b}</code></li>" for r, a, b in moved)
return style + _panel(
"warn", "Progress: MEASURED, BUT THE REPOSITORIES HAVE MOVED SINCE",
f'<p>{len(moved)} repository(ies) changed after this snapshot, so the figures '
f'below describe an earlier state:</p><ul>{rowsm}</ul>{head}{table}{contra}{note}'
f'<p class="note">Re-run <code>tools/estate-progress.py --json</code> to refresh.</p>')
return style + _panel("", "Progress — measured, not asserted",
head + table + contra + note)