CodeIssuesPull RequestsActionsSecurityInsights
✨ AI
More
Settings

fix(zero-noise): precision publication is an owner decision, not a side effect #5525

Merged⚡ AI-generatedXSccantynz wants to mergefix/precision-publication-gatemainopened 9d ago
4 changed files+62−8
Modified.env.example+5−0View fileUnifiedSplit
348348# transition alerting + paging webhook as every other check. Unset = off.
349349# Production: https://vapron.ai/
350350PEER_WATCH_URL=
351
352# Zero-Noise pillar 4 publication gate: 1 renders the public /status
353# "Signal precision" section. Verdicts collect regardless; site admins
354# always see the section. Flip after verified-before-shown ships.
355SIGNAL_PRECISION_PUBLIC=
Modifiedsrc/__tests__/copy-honesty.test.ts+25−3View fileUnifiedSplit
101101 });
102102
103103 it("/status: signal precision is computed-not-claimed — honest empty state, rate never without sample size", async () => {
104 const body = await page("/status");
105 // The section renders in every state (no-DB, under-sample, published)
106 // and always carries the provenance sentence.
104 // Publication gate (owner, 2026-08-24): anonymous /status shows NO
105 // precision section until SIGNAL_PRECISION_PUBLIC=1 — the platform
106 // proves itself correct before posting live results. Rendering nothing
107 // is honest; advertising a scoreboard before its pipeline is hardened
108 // is not. Site admins see it in place regardless (not exercised here —
109 // this suite renders anonymously).
110 const prev = process.env.SIGNAL_PRECISION_PUBLIC;
111 delete process.env.SIGNAL_PRECISION_PUBLIC;
112 try {
113 const hidden = await page("/status");
114 expect(hidden).not.toContain("Signal precision");
115 } finally {
116 if (prev !== undefined) process.env.SIGNAL_PRECISION_PUBLIC = prev;
117 }
118
119 process.env.SIGNAL_PRECISION_PUBLIC = "1";
120 let body: string;
121 try {
122 body = await page("/status");
123 } finally {
124 if (prev === undefined) delete process.env.SIGNAL_PRECISION_PUBLIC;
125 else process.env.SIGNAL_PRECISION_PUBLIC = prev;
126 }
127 // Once published, the section renders in every state (no-DB,
128 // under-sample, published) and always carries the provenance sentence.
107129 expect(body).toContain("Signal precision");
108130 expect(body).toContain(
109131 "Computed from developer verdicts on AI review findings, not claimed."
Modifiedsrc/lib/config.ts+10−0View fileUnifiedSplit
124124 get sshHostKey() {
125125 return process.env.SSH_HOST_KEY || "";
126126 },
127 /**
128 * Zero-Noise pillar 4 publication gate. Verdicts on AI review findings
129 * collect regardless; the public /status "Signal precision" section
130 * renders only when this is 1 (site admins always see it in place).
131 * Owner directive 2026-08-24: the platform proves itself correct before
132 * posting live results — flip after verified-before-shown ships.
133 */
134 get signalPrecisionPublic() {
135 return process.env.SIGNAL_PRECISION_PUBLIC === "1";
136 },
127137 /**
128138 * Where the auto-generated SSH host key persists when SSH_HOST_KEY is not
129139 * set. Defaults under GIT_REPOS_PATH so it rides the git-repos volume and
Modifiedsrc/routes/status.tsx+22−5View fileUnifiedSplit
2727import { recentRedChecks } from "../lib/synthetic-monitor";
2828import { sendEmail, reportEmailFailure } from "../lib/email";
2929import { config } from "../lib/config";
30import { isSiteAdmin } from "../lib/admin";
3031import {
3132 computeSignalPrecision,
3233 MIN_SAMPLE,
553554 // - precision null → fewer than MIN_SAMPLE judgments in the window;
554555 // show the real judged/total counts instead.
555556 // - a number → the rate, always beside its sample size.
557 // Publication gate (owner directive 2026-08-24: "our platform needs to be
558 // functioning correctly before we are posting live results"). Verdicts
559 // COLLECT regardless; the public figure renders only when the owner flips
560 // SIGNAL_PRECISION_PUBLIC=1 — after the verified-before-shown pipeline
561 // (Zero-Noise build-map item 2) has hardened what the number measures.
562 // Site admins always see the section in place, so the owner watches the
563 // real figure exactly where the public eventually will.
564 const viewerIsAdmin = user ? await isSiteAdmin(user.id).catch(() => false) : false;
565 const showSignalPrecision = config.signalPrecisionPublic || viewerIsAdmin;
556566 let signalPrecision: SignalPrecision | null = null;
557 try {
558 signalPrecision = await computeSignalPrecision(SIGNAL_WINDOW_DAYS);
559 } catch {
560 signalPrecision = null;
567 if (showSignalPrecision) {
568 try {
569 signalPrecision = await computeSignalPrecision(SIGNAL_WINDOW_DAYS);
570 } catch {
571 signalPrecision = null;
572 }
561573 }
562574
563575 return c.html(
669681 </div>
670682 )}
671683
672 {/* ─── Signal precision (Zero Noise pillar 4) ─── */}
684 {/* ─── Signal precision (Zero Noise pillar 4) ───
685 Gated: admin-only until SIGNAL_PRECISION_PUBLIC=1. Rendering
686 nothing publicly is honest — advertising a scoreboard before its
687 pipeline is hardened is not. */}
688 {showSignalPrecision && (
673689 <section class="status-section" aria-labelledby="status-sig-h">
674690 <header class="status-section-head">
675691 <div>
762778 </p>
763779 </div>
764780 </section>
781 )}
765782
766783 {/* ─── Service uptime badges ─── */}
767784 <section class="status-section" aria-labelledby="status-comp-h">
768785
c comment · e edit title · m merge · a approve · r request changes · ? shortcuts