Files
wehub-resource-sync 070959e133
landing-page-staging / Deploy landing page to staging (push) Has been skipped
landing-page-ci / Validate landing page (push) Failing after 4s
visual-baseline / Capture visual baselines (push) Has been cancelled
bake-plugin-previews / Bake plugin previews (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:00:47 +08:00

409 lines
27 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Turn an Incident Retro into a Learning Deck like a Platform VP - Product management</title>
<style>/* html-ppt :: shared webfonts (trimmed to faces actually in use) */
@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;700;800;900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&display=swap');
</style>
<style>/* html-ppt :: base.css — reset + shared tokens + layout primitives */
/* Default tokens. Themes in assets/themes/*.css override the :root block. */
:root {
--bg: #ffffff;
--bg-soft: #f7f7f8;
--surface: #ffffff;
--surface-2: #f2f2f4;
--border: rgba(0,0,0,.08);
--border-strong: rgba(0,0,0,.16);
--text-1: #111216;
--text-2: #55596a;
--text-3: #8a8f9e;
--accent: #B5392A;
--good: #1aaf6c;
--warn: #f5a524;
--bad: #e0445a;
--radius: 2px;
--radius-sm: 2px;
--radius-lg: 3px;
--shadow: none;
--shadow-lg: none;
--font-sans: 'Archivo',-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;
--font-serif: 'Archivo',Georgia,serif;
--font-mono: 'IBM Plex Mono',SFMono-Regular,Menlo,monospace;
--font-display: var(--font-sans);
--letter-tight: -.03em;
--letter-normal: -.01em;
--ease: cubic-bezier(.16,1,.3,1);
}
*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;padding:0;background:var(--bg);color:var(--text-1);
font-family:var(--font-sans);font-weight:400;line-height:1.6;
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
letter-spacing:var(--letter-normal)}
img,svg,video{max-width:100%;display:block}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}
code,kbd,pre,samp{font-family:var(--font-mono)}
/* ================= SLIDE SYSTEM ================= */
.deck{position:relative;width:100vw;height:100vh;overflow:hidden;background:var(--bg)}
.slide{
position:absolute;inset:0;
display:flex;flex-direction:column;justify-content:center;
padding:72px 96px;
box-sizing:border-box;
opacity:0;pointer-events:none;
transition:opacity .5s var(--ease), transform .5s var(--ease);
transform:translateX(30px);
overflow:hidden;
}
.slide.is-active{opacity:1;pointer-events:auto;transform:translateX(0);z-index:2}
.slide.is-prev{transform:translateX(-30px)}
/* single-page standalone (used when a layout file is opened directly) */
body.single .slide{position:relative;width:100vw;height:100vh;opacity:1;transform:none;pointer-events:auto}
/* ================= TYPOGRAPHY ================= */
.eyebrow{font-size:13px;font-weight:500;letter-spacing:.16em;text-transform:uppercase;color:var(--text-3)}
.kicker{font-size:14px;font-weight:600;color:var(--accent);letter-spacing:.08em;text-transform:uppercase}
h1.title,.h1{font-family:var(--font-display);font-size:72px;line-height:1.05;font-weight:800;letter-spacing:var(--letter-tight);margin:0 0 18px;color:var(--text-1)}
h2.title,.h2{font-family:var(--font-display);font-size:54px;line-height:1.1;font-weight:700;letter-spacing:var(--letter-tight);margin:0 0 14px}
h3,.h3{font-size:32px;line-height:1.2;font-weight:600;letter-spacing:var(--letter-normal);margin:0 0 10px}
h4,.h4{font-size:22px;line-height:1.3;font-weight:600;margin:0 0 8px}
.lede{font-size:22px;line-height:1.55;color:var(--text-2);font-weight:300;max-width:62ch}
.dim{color:var(--text-2)}
.dim2{color:var(--text-3)}
.mono{font-family:var(--font-mono)}
.serif{font-family:var(--font-serif)}
.gradient-text{color:var(--accent)} /* gradient text retired: single-accent discipline */
/* ================= LAYOUT PRIMITIVES ================= */
.stack>*+*{margin-top:14px}
.row{display:flex;gap:24px;align-items:center}
.row.wrap{flex-wrap:wrap}
.grid{display:grid;gap:24px}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}
.center{display:flex;align-items:center;justify-content:center;text-align:center}
.fill{flex:1}
.sp-t{padding-top:24px}.sp-b{padding-bottom:24px}
.mt-s{margin-top:8px}.mt-m{margin-top:18px}.mt-l{margin-top:32px}
.mb-s{margin-bottom:8px}.mb-m{margin-bottom:18px}.mb-l{margin-bottom:32px}
/* ================= CARDS ================= */
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
padding:26px 28px;box-shadow:var(--shadow);position:relative;overflow:hidden}
.card-soft{background:var(--surface-2);border:1px solid var(--border)}
.card-outline{background:transparent;border:1.5px solid var(--border-strong);box-shadow:none}
.card-accent{background:var(--surface);border-top:3px solid var(--accent)}
.card-hover{transition:transform .3s var(--ease),box-shadow .3s var(--ease)}
.card-hover:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg)}
.pill{display:inline-block;padding:4px 12px;border-radius:999px;font-size:12px;font-weight:500;
background:var(--surface-2);color:var(--text-2);border:1px solid var(--border)}
.pill-accent{background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent);border-color:color-mix(in srgb,var(--accent) 28%,transparent)}
/* ================= BARS / DIVIDERS ================= */
.divider{height:1px;background:var(--border);width:100%}
.divider-accent{height:3px;width:72px;background:var(--accent);border-radius:2px}
/* ================= CHROME (header/footer/progress) ================= */
.deck-header{position:absolute;top:24px;left:40px;right:40px;display:flex;align-items:center;justify-content:space-between;
font-size:12px;color:var(--text-3);letter-spacing:.12em;text-transform:uppercase;z-index:10;pointer-events:none}
.deck-footer{position:absolute;bottom:24px;left:40px;right:40px;display:flex;align-items:center;justify-content:space-between;
font-size:12px;color:var(--text-3);z-index:10;pointer-events:none}
.slide-number::before{content:attr(data-current)}
.slide-number::after{content:" / " attr(data-total)}
.progress-bar{position:fixed;left:0;right:0;bottom:0;height:3px;background:transparent;z-index:20}
.progress-bar > span{display:block;height:100%;width:0;background:var(--accent);transition:width .3s var(--ease)}
/* ================= PRESENTER / OVERVIEW ================= */
.notes{display:none!important}
.notes-overlay{position:fixed;inset:auto 0 0 0;max-height:42vh;background:rgba(20,22,30,.95);color:#e8ebf4;
padding:20px 32px;font-size:16px;line-height:1.6;border-top:1px solid rgba(255,255,255,.1);transform:translateY(100%);
transition:transform .3s var(--ease);z-index:40;overflow:auto;font-family:var(--font-sans)}
.notes-overlay.open{transform:translateY(0)}
.overview{position:fixed;inset:0;background:rgba(10,12,18,.92);backdrop-filter:blur(12px);z-index:50;
display:none;padding:40px;overflow:auto}
.overview.open{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;align-content:start}
.overview .thumb{background:var(--surface);border:1px solid var(--border);border-radius:12px;
aspect-ratio:16/9;overflow:hidden;cursor:pointer;position:relative;color:var(--text-1);padding:16px;
font-size:11px;transition:transform .2s var(--ease)}
.overview .thumb:hover{transform:scale(1.04)}
.overview .thumb .n{position:absolute;top:8px;left:10px;font-weight:700;font-size:14px;color:var(--text-3)}
.overview .thumb .t{position:absolute;bottom:10px;left:14px;right:14px;font-weight:600;color:var(--text-1)}
/* ================= PRESENTER VIEW ================= */
/* Presenter view opens in a separate popup window (S key).
* All presenter styles are self-contained in the popup HTML generated by runtime.js.
* The audience window (this file) is NOT affected — it stays as normal deck view.
* Only the .notes class below is needed to hide speaker notes from audience. */
/* ================= UTILITY ================= */
.hidden{display:none!important}
.nowrap{white-space:nowrap}
.tr{text-align:right}.tc{text-align:center}.tl{text-align:left}
.uppercase{text-transform:uppercase;letter-spacing:.12em}
/* ================= PRINT ================= */
@media print{
.slide{position:relative;opacity:1!important;transform:none!important;page-break-after:always;height:100vh}
.deck-header,.deck-footer,.progress-bar,.notes-overlay,.overview{display:none!important}
}
</style>
<style>/* knowledge-arch-blueprint — cream paper + architectural blueprint style
family signatures kept: cream paper, drafting grid, rust ink, 2px ruled borders.
polish pass: Archivo drafting grotesque (Inter retired), sharp corners, shadows
removed (drawings are flat), contrast fixes, staggered entrance on transform+opacity. */
.tpl-knowledge-arch-blueprint{
--kb-bg:#F0EAE0;
--kb-ink:#1a1a1a;
--kb-ink2:#4f4b44;
--kb-ink3:#6f6a5f; /* was #8a8479: lifted to ~4.7:1 on cream for AA meta text */
--kb-rust:#B5392A;
--kb-rust-soft:rgba(181,57,42,.08);
--kb-line:#cec8be;
background:var(--kb-bg);
color:var(--kb-ink);
font-family:'Archivo',-apple-system,sans-serif;
}
.tpl-knowledge-arch-blueprint .slide{background:var(--kb-bg);color:var(--kb-ink);padding:64px 80px}
.tpl-knowledge-arch-blueprint .kb-grid-bg{position:absolute;inset:0;pointer-events:none;opacity:.35;background-image:linear-gradient(rgba(26,26,26,.06) 1px,transparent 1px),linear-gradient(90deg,rgba(26,26,26,.06) 1px,transparent 1px);background-size:48px 48px;mask-image:radial-gradient(ellipse at center,black 40%,transparent 85%)}
.tpl-knowledge-arch-blueprint .slide > *{position:relative;z-index:2}
.tpl-knowledge-arch-blueprint .kb-kicker{font-family:'IBM Plex Mono',monospace;font-size:12px;font-weight:600;letter-spacing:.28em;text-transform:uppercase;color:var(--kb-rust);margin-bottom:14px}
.tpl-knowledge-arch-blueprint .kb-h1{font-size:66px;font-weight:800;line-height:1.04;color:#111;margin:0 0 14px;letter-spacing:-.025em;text-wrap:balance}
.tpl-knowledge-arch-blueprint .kb-h1 span.rust{color:var(--kb-rust)}
.tpl-knowledge-arch-blueprint .kb-sub{font-size:19px;color:var(--kb-ink2);line-height:1.6;max-width:62ch}
.tpl-knowledge-arch-blueprint .kb-sub b{white-space:nowrap} /* keep URLs and bold runs from breaking mid-word */
.tpl-knowledge-arch-blueprint .kb-insight{display:inline-block;background:var(--kb-rust);color:#fff;border-radius:2px;padding:18px 22px;font-size:14px;font-weight:600;line-height:1.55;max-width:340px;border-left:6px double rgba(255,255,255,.55)}
.tpl-knowledge-arch-blueprint .kb-insight .kk{font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.22em;opacity:.75;display:block;margin-bottom:8px;font-weight:600}
.tpl-knowledge-arch-blueprint .kb-section-label{font-family:'IBM Plex Mono',monospace;font-size:11px;font-weight:600;letter-spacing:.3em;text-transform:uppercase;color:var(--kb-ink3);margin:30px 0 12px;display:flex;align-items:center;gap:14px}
.tpl-knowledge-arch-blueprint .kb-section-label::after{content:'';flex:1;height:1px;background:var(--kb-line)}
.tpl-knowledge-arch-blueprint .kb-pipeline{display:flex;align-items:stretch;gap:14px;margin-top:24px}
.tpl-knowledge-arch-blueprint .kb-step{flex:1;border:2px solid #1a1a1a;border-radius:2px;padding:20px 18px;background:#FBF8F2;position:relative;min-height:178px;display:flex;flex-direction:column}
.tpl-knowledge-arch-blueprint .kb-step.hero{background:var(--kb-rust);border-color:#1a1a1a;color:#fff;flex:1.25;transform:translateY(-8px)}
.tpl-knowledge-arch-blueprint .kb-step-num{font-family:'IBM Plex Mono',monospace;font-size:10px;font-weight:600;letter-spacing:.22em;color:var(--kb-ink3);margin-bottom:8px;text-transform:uppercase}
.tpl-knowledge-arch-blueprint .kb-step.hero .kb-step-num{color:rgba(255,255,255,.72)}
.tpl-knowledge-arch-blueprint .kb-step-title{font-size:22px;font-weight:800;line-height:1.15;letter-spacing:-.01em;color:#111;margin-bottom:8px}
.tpl-knowledge-arch-blueprint .kb-step.hero .kb-step-title{color:#fff}
.tpl-knowledge-arch-blueprint .kb-step-body{font-size:13px;line-height:1.55;color:var(--kb-ink2);margin-top:auto}
.tpl-knowledge-arch-blueprint .kb-step.hero .kb-step-body{color:rgba(255,255,255,.9)}
.tpl-knowledge-arch-blueprint .kb-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:24px}
.tpl-knowledge-arch-blueprint .kb-card{background:#FBF8F2;border:2px solid #1a1a1a;border-radius:2px;padding:22px 24px}
.tpl-knowledge-arch-blueprint .kb-card h4{font-size:20px;font-weight:800;letter-spacing:-.01em;margin-bottom:6px}
.tpl-knowledge-arch-blueprint .kb-card p{font-size:14px;color:var(--kb-ink2);line-height:1.55}
.tpl-knowledge-arch-blueprint .kb-legend{display:flex;gap:18px;flex-wrap:wrap;margin-top:22px;font-family:'IBM Plex Mono',monospace;font-size:12px;color:var(--kb-ink2)}
.tpl-knowledge-arch-blueprint .kb-legend .d{display:flex;align-items:center;gap:8px}
.tpl-knowledge-arch-blueprint .kb-legend .b{width:14px;height:14px;border:2px solid #1a1a1a;border-radius:1px}
.tpl-knowledge-arch-blueprint .kb-legend .b.rust{background:var(--kb-rust);border-color:#1a1a1a}
.tpl-knowledge-arch-blueprint .kb-footer{position:absolute;left:80px;right:80px;bottom:36px;display:flex;justify-content:space-between;font-family:'IBM Plex Mono',monospace;font-size:11px;color:var(--kb-ink3);letter-spacing:.18em;text-transform:uppercase;border-top:1px solid var(--kb-line);padding-top:16px}
.tpl-knowledge-arch-blueprint .kb-mono{font-family:'IBM Plex Mono',monospace}
.tpl-knowledge-arch-blueprint .kb-codebox{background:#1a1a1a;color:#f0eae0;border-radius:2px;padding:22px 26px;font-family:'IBM Plex Mono',monospace;font-size:14px;line-height:1.8;margin-top:20px;border:2px solid #1a1a1a}
.tpl-knowledge-arch-blueprint .kb-codebox .cm{color:#aaa496} /* comment tone lifted for AA on #1a1a1a */
.tpl-knowledge-arch-blueprint .kb-codebox .kw{color:#e8a87c}
.tpl-knowledge-arch-blueprint .kb-codebox .st{color:#b3d1bc}
.tpl-knowledge-arch-blueprint .kb-codebox .hl{color:#f3a99e;background:rgba(255,255,255,.08);padding:0 4px;border-radius:2px}
.tpl-knowledge-arch-blueprint .kb-big-num{font-family:'Archivo',sans-serif;font-size:188px;font-weight:900;line-height:.9;color:var(--kb-rust);letter-spacing:-.05em}
/* entrance: staggered rise, transform+opacity only */
@keyframes kb-rise{from{opacity:0;transform:translateY(22px)}to{opacity:1;transform:none}}
.tpl-knowledge-arch-blueprint .slide.is-active > *:not(.kb-grid-bg):not(.kb-footer){animation:kb-rise .6s var(--ease) both}
.tpl-knowledge-arch-blueprint .slide.is-active > *:nth-child(3){animation-delay:.06s}
.tpl-knowledge-arch-blueprint .slide.is-active > *:nth-child(4){animation-delay:.12s}
.tpl-knowledge-arch-blueprint .slide.is-active > *:nth-child(5){animation-delay:.18s}
@media (prefers-reduced-motion:reduce){
.tpl-knowledge-arch-blueprint .slide.is-active > *{animation:none!important}
}
</style>
<style>
/* Static-preview fallback (runtime.js is absent — keep every slide visible) */
.deck{height:auto;min-height:100vh;overflow:visible}
.slide{position:relative;inset:auto;opacity:1;pointer-events:auto;transform:none;height:100vh;page-break-after:always}
.deck-header,.deck-footer,.slide-number,.progress-bar,.notes-overlay,.overview{pointer-events:none}
.notes{display:none!important}
</style></head>
<body class="tpl-knowledge-arch-blueprint">
<div class="deck">
<!-- 1. COVER -->
<section class="slide is-active">
<div class="kb-grid-bg"></div>
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:40px;margin-bottom:44px">
<div>
<div class="kb-kicker">Product Management · Incident Retro Deck</div>
<h1 class="kb-h1" style="font-size:54px">Turn an incident retro into<br>a <span class="rust">learning deck</span>, like a Platform VP</h1>
<p class="kb-sub">The daemon-restart data bug: what broke, why, the fix on the table, and the one decision engineering, SRE, and leadership need to co-sign this week.</p>
</div>
<div class="kb-insight"><span class="kk">DECISION NEEDED</span>Ship the data-root guardrail before the next namespace migration — not another point patch.</div>
</div>
<div class="kb-section-label">Retro Arc · Decision → Measure</div>
<div class="kb-pipeline">
<div class="kb-step"><div class="kb-step-num">STEP 01</div><div class="kb-step-title">Decision needed</div><div class="kb-step-body">Which fix ships this sprint: patch the call sites, or remove the fallback entirely</div></div>
<div class="kb-step"><div class="kb-step-num">STEP 02</div><div class="kb-step-title">User pain</div><div class="kb-step-body">41 projects looked "deleted" for 12 minutes after a routine restart</div></div>
<div class="kb-step hero"><div class="kb-step-num">STEP 03 · CORE</div><div class="kb-step-title">Options &amp; recommendation</div><div class="kb-step-body">Compare the narrow patch against the guardrail that closes the whole class</div></div>
<div class="kb-step"><div class="kb-step-num">STEP 04</div><div class="kb-step-title">Measure</div><div class="kb-step-body">MTTR, recurrence count, and CI catch-rate we'll track post-ship</div></div>
</div>
<div class="kb-footer"><span>Open Design · Platform Incident Retro</span><span>01 / 08</span></div>
</section>
<!-- 2. SECTION DIVIDER -->
<section class="slide">
<div class="kb-grid-bg"></div>
<div style="margin:auto 0">
<div class="kb-kicker">Chapter One · Decision Needed</div>
<h1 class="kb-h1" style="font-size:92px">Ship the guardrail —<br><span class="rust">before</span> the next restart</h1>
<p class="kb-sub" style="font-size:24px;margin-top:20px">On June 14, a routine daemon restart under a stale namespace let 41 projects' SQLite files resolve against a cwd-relative fallback instead of the daemon's actual data root.<br>The only question left this sprint is <b>which fix we ship</b> — a patch, or a guardrail.</p>
</div>
<div class="kb-footer"><span>Section · Chapter 1</span><span>02 / 08</span></div>
</section>
<!-- 3. CONTENT 2-col -->
<section class="slide">
<div class="kb-grid-bg"></div>
<div class="kb-kicker">User Pain · Options</div>
<h1 class="kb-h1" style="font-size:44px">12 minutes of "my projects vanished" × 41 teams</h1>
<div class="kb-grid-2">
<div class="kb-card">
<div class="kb-kicker" style="color:#6f6a5f">Option A</div>
<h4>Patch the call sites</h4>
<p>Fix the 9 known <span class="kb-mono">openDatabase(projectRoot)</span> calls to pass the resolved data root explicitly. Ships in two days — but the next engineer who adds a call site can reintroduce the same escape.</p>
</div>
<div class="kb-card" style="background:var(--kb-rust-soft);border-color:var(--kb-rust)">
<div class="kb-kicker">Option B · Recommended</div>
<h4>Remove the fallback entirely</h4>
<p>Delete the cwd-relative default from <span class="kb-mono">openDatabase</span> itself, so a missing data root fails loudly at startup instead of silently writing elsewhere. One migration, closes the whole bug class.</p>
</div>
</div>
<div class="kb-legend">
<div class="d"><span class="b"></span>Fast, narrow coverage · Option A</div>
<div class="d"><span class="b rust"></span>Slower, closes the class · Option B</div>
<div class="d">—— data path &nbsp;&nbsp; ┈┈ silent fallback (the bug)</div>
</div>
<div class="kb-footer"><span>Content · Options</span><span>03 / 08</span></div>
</section>
<!-- 4. CODE -->
<section class="slide">
<div class="kb-grid-bg"></div>
<div class="kb-kicker">Tradeoffs · The Fix</div>
<h1 class="kb-h1" style="font-size:44px">Why "patch the sites" loses to "kill the fallback"</h1>
<p class="kb-sub">A per-site patch depends on every future engineer remembering the rule. Removing the fallback makes the rule impossible to violate — the daemon simply refuses to start with an unresolved data root.</p>
<pre class="kb-codebox"><span class="cm"># apps/daemon/src/db.ts — before vs after</span>
<span class="kw">function</span> openDatabase(projectRoot<span class="hl">?</span>) {
<span class="kw">const</span> root = projectRoot ?? <span class="st">cwd-relative default</span> <span class="cm">// silent escape</span>
<span class="kw">return</span> sqlite.open(root)
}
<span class="cm"># after: fallback deleted, root is required</span>
<span class="kw">function</span> openDatabase(root<span class="hl"> = RUNTIME_DATA_DIR</span>) {
<span class="kw">if</span> (!root) <span class="kw">throw</span> <span class="st">"missing data root — refuse to start"</span>
<span class="kw">return</span> sqlite.open(root)
}</pre>
<div class="kb-footer"><span>Content · Tradeoffs</span><span>04 / 08</span></div>
</section>
<!-- 5. DIAGRAM - SVG feedback loop -->
<section class="slide">
<div class="kb-grid-bg"></div>
<div class="kb-kicker">Recommendation · System Diagram</div>
<h1 class="kb-h1" style="font-size:40px">One resolved root, three enforced checks</h1>
<svg viewBox="0 0 1200 520" style="width:100%;max-width:1200px;margin-top:20px" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
<path d="M0,0 L10,5 L0,10 z" fill="#1a1a1a"/>
</marker>
<marker id="arrow-r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
<path d="M0,0 L10,5 L0,10 z" fill="#B5392A"/>
</marker>
</defs>
<g font-family="Archivo, sans-serif" font-size="16" font-weight="700">
<!-- boxes -->
<rect x="40" y="180" width="200" height="120" rx="2" fill="#FBF8F2" stroke="#1a1a1a" stroke-width="2"/>
<text x="140" y="220" text-anchor="middle">Daemon start</text>
<text x="140" y="250" text-anchor="middle" font-size="12" font-weight="400" fill="#4f4b44">OD_DATA_DIR env in</text>
<rect x="300" y="180" width="200" height="120" rx="2" fill="#FBF8F2" stroke="#1a1a1a" stroke-width="2"/>
<text x="400" y="220" text-anchor="middle">Resolve root</text>
<text x="400" y="250" text-anchor="middle" font-size="12" font-weight="400" fill="#4f4b44">no cwd fallback allowed</text>
<rect x="560" y="160" width="220" height="160" rx="2" fill="#B5392A" stroke="#1a1a1a" stroke-width="2"/>
<text x="670" y="210" text-anchor="middle" fill="#fff" font-size="20">RUNTIME_DATA_DIR</text>
<text x="670" y="240" text-anchor="middle" font-size="12" font-weight="400" fill="rgba(255,255,255,.8)">single source of truth</text>
<text x="670" y="262" text-anchor="middle" font-size="12" font-weight="400" fill="rgba(255,255,255,.8)">SQLite · artifacts · plugins</text>
<rect x="840" y="180" width="200" height="120" rx="2" fill="#FBF8F2" stroke="#1a1a1a" stroke-width="2"/>
<text x="940" y="220" text-anchor="middle">Every caller</text>
<text x="940" y="250" text-anchor="middle" font-size="12" font-weight="400" fill="#4f4b44">openDatabase, artifacts, MCP</text>
<!-- forward arrows -->
<line x1="245" y1="240" x2="295" y2="240" stroke="#1a1a1a" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="505" y1="240" x2="555" y2="240" stroke="#1a1a1a" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="785" y1="240" x2="835" y2="240" stroke="#1a1a1a" stroke-width="2" marker-end="url(#arrow)"/>
<!-- feedback dashed -->
<path d="M 940 180 Q 940 80, 670 80 Q 400 80, 400 180" fill="none" stroke="#B5392A" stroke-width="2" stroke-dasharray="6 6" marker-end="url(#arrow-r)"/>
<rect x="580" y="58" width="180" height="30" rx="2" fill="#F0EAE0" stroke="#B5392A" stroke-width="1"/>
<text x="670" y="78" text-anchor="middle" fill="#B5392A" font-size="12">CI CHECK · blocks new fallbacks</text>
<!-- bottom feedback to sources -->
<path d="M 940 300 Q 940 420, 670 420 Q 140 420, 140 300" fill="none" stroke="#B5392A" stroke-width="2" stroke-dasharray="6 6" marker-end="url(#arrow-r)"/>
<rect x="560" y="400" width="220" height="30" rx="2" fill="#F0EAE0" stroke="#B5392A" stroke-width="1"/>
<text x="670" y="420" text-anchor="middle" fill="#B5392A" font-size="12">RESTART DRILL · every release, both namespaces</text>
</g>
</svg>
<div class="kb-footer"><span>Diagram · Recommendation</span><span>05 / 08</span></div>
</section>
<!-- 6. STATS -->
<section class="slide">
<div class="kb-grid-bg"></div>
<div class="kb-kicker">Measure</div>
<h1 class="kb-h1" style="font-size:44px">What we track <span class="rust">after ship</span></h1>
<div style="display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:24px;margin-top:28px;align-items:center">
<div style="text-align:center"><div class="kb-big-num">0</div><p style="font-family:'IBM Plex Mono',monospace;font-size:13px;color:#4f4b44;margin-top:6px;letter-spacing:.14em;text-transform:uppercase">Recurrences targeted across next 2 restart drills</p></div>
<div class="kb-card"><h4 style="color:var(--kb-rust)">-92%</h4><p>MTTR for data-path incidents once the CI guardrail lands (14m → 70s)</p></div>
<div class="kb-card"><h4 style="color:var(--kb-rust)">9 → 0</h4><p>Legacy fallback call sites remaining after the migration</p></div>
</div>
<div class="kb-grid-2" style="margin-top:18px">
<div class="kb-card"><h4>3 signals we watch</h4><p>Restart-drill pass rate, CI guardrail catches on PRs, and support tickets tagged "missing project."</p></div>
<div class="kb-card"><h4>Sign-off owners</h4><p>Platform infra and SRE co-sign the guardrail PR; engineering leadership signs off on the quarterly restart-drill cadence.</p></div>
</div>
<div class="kb-footer"><span>Content · Measure</span><span>06 / 08</span></div>
</section>
<!-- 7. CTA -->
<section class="slide">
<div class="kb-grid-bg"></div>
<div class="kb-kicker">Next Step · The Ask</div>
<h1 class="kb-h1" style="font-size:52px">Approve the <span class="rust">guardrail PR</span> this week</h1>
<p class="kb-sub">One irreversible step: merge the fallback removal plus the CI check before the next namespace migration ships.</p>
<div class="kb-pipeline">
<div class="kb-step"><div class="kb-step-num">TODAY</div><div class="kb-step-title">Merge the guardrail PR</div><div class="kb-step-body">Removes the cwd-relative fallback from openDatabase</div></div>
<div class="kb-step"><div class="kb-step-num">THIS WEEK</div><div class="kb-step-title">Run the restart drill</div><div class="kb-step-body">Two concurrent namespaces, verify no silent fallback writes</div></div>
<div class="kb-step hero"><div class="kb-step-num">NEXT RELEASE · CORE</div><div class="kb-step-title">Ship the CI check</div><div class="kb-step-body">Blocks any new call site that recomputes a data root instead of receiving one</div></div>
<div class="kb-step"><div class="kb-step-num">ONGOING</div><div class="kb-step-title">Quarterly drill review</div><div class="kb-step-body">SRE reports pass rate to leadership every release cycle</div></div>
</div>
<div class="kb-footer"><span>CTA</span><span>07 / 08</span></div>
</section>
<!-- 8. THANKS -->
<section class="slide">
<div class="kb-grid-bg"></div>
<div style="margin:auto 0;text-align:center">
<div class="kb-kicker">Engineering · SRE · Leadership</div>
<h1 class="kb-h1" style="font-size:104px;margin-top:24px">sign <span class="rust">·</span> off</h1>
<p class="kb-sub" style="margin:0 auto;font-size:22px">Cross-functional agreement closes this retro: Platform, SRE, and Leadership all back <b class="nowrap">the guardrail</b>, not just the patch.</p>
</div>
<div class="kb-footer"><span>End of deck</span><span>08 / 08</span></div>
</section>
</div>
</body>
</html>