diff --git a/CLAUDE.md b/CLAUDE.md
index 6b535e1..bf91e9a 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -29,5 +29,7 @@ reference app (`samples/corpay`, proven nightly against the published packages).
 phase is active (`docs/rfc/goldpath-console.md`: U1–U3 met — all five module
 panels are proven nightly by the console smoke against one real app; U4 next). Live status ledgers —
 keep them updated in the same PR that changes reality: `docs/strategy/ai-sdlc-status.md`
-(AI-assisted SDLC vs reality) and `docs/strategy/coverage-matrix.md` (capability × sample).
+(AI-assisted SDLC vs reality), `docs/strategy/coverage-matrix.md` (capability × sample),
+and `docs/strategy/open-threads.md` (deferred work with its TRIGGER and the proof that
+must run before the thread closes — nothing is postponed without landing there).
 Roadmap gates: `docs/strategy/foundation.md` §12.
diff --git a/docs/rfc/goldpath-console.md b/docs/rfc/goldpath-console.md
index a220e11..45f7b20 100644
--- a/docs/rfc/goldpath-console.md
+++ b/docs/rfc/goldpath-console.md
@@ -85,7 +85,8 @@ custom-develop ON, with the same kit, the same way they add features to the back
 | U1 | `ui/kit`: tokens + primitives + composites | component tests green; kit gallery page |
 | U2 | Run console over the registry (single-app path) | **MET** (2026-07-26): `scripts/console-smoke.sh` drives the real console against a real Goldpath app (Postgres + Quartz + the frozen surface) — capability discovery, confirm gate, run reaching terminal, repair queue replayed; runs nightly |
 | U3 | Module panels (bulk/campaign/notification/archival), capability-lit | **MET** (2026-07-27): all four panels ship, and the console smoke drives every module's real verbs against one app — bulk's four-eyes gate (including the engine's refusal on invalid rows), the campaign governor over a real broker (release, throttle, pause, resume, abort), the notification evidence in all three kinds (sent, failed, suppressed, recipients masked), and archival's chain verification, keyed retrieval, legal hold, the hold's refusal of an erasure, and the erasure itself — after which the chain still verifies |
-| U4 | Cross-service registry + triage home + auth story + `MapGoldpathConsole()` + GmConsole in nightly | the full D3 bar; CorPay screenshots into the README |
+| U4 | Cross-service registry + triage home + auth story + `MapGoldpathConsole()` + GmConsole in nightly | the full D3 bar; the console driven against CorPay and its screenshots into the README (open-threads T1) |
+| U5 | The styling pass — one sweep over spacing, density, filter layout, panel rhythm | deliberately LAST (open-threads T2): cosmetics before the flows settle get done twice. The axe and smoke gates must stay green through it, and the tokens change in `ui-standard-v1`, not per panel |
 
 ## 6. Non-goals
 
diff --git a/docs/strategy/open-threads.md b/docs/strategy/open-threads.md
new file mode 100644
index 0000000..248d126
--- /dev/null
+++ b/docs/strategy/open-threads.md
@@ -0,0 +1,33 @@
+# Open threads — deferred work, with its trigger and its proof
+
+Every entry here is work we CHOSE to postpone, not work we forgot. The rule that makes
+this file worth keeping: a thread leaves the table only when the **proof** column has
+actually run — not when the code lands.
+
+Keep it honest in the same PR that changes reality (same discipline as
+[ai-sdlc-status.md](ai-sdlc-status.md) and [coverage-matrix.md](coverage-matrix.md)). A
+thread that turns out to be unnecessary is DELETED with a line saying why, never left
+pending forever.
+
+| # | Thread | Why it waits | Trigger — when it comes up | What must be PROVEN then |
+|---|---|---|---|---|
+| T1 | The console driven against **CorPay** (the real sample), and CorPay screenshots in the README | The gate drives a purpose-built host that composes all five modules; CorPay is the adopter-shaped proof, and it needs U4's cross-service registry to be worth wiring | U4 | `scripts/console-smoke.sh` (or its CorPay twin) drives CorPay's own admin surface end to end; the README screenshots come from that run, not from a mock |
+| T2 | **The UI styling pass** — one sweep over spacing, density, filter layout and the panel rhythm | Cosmetics before the flows are settled means doing them twice; the owner's call is to change them TOGETHER, once the flows are done | after U4 (all flows complete) | the axe gate stays green (contrast is part of the style), the console smoke stays green (no locator is a style accident), and the tokens change in `ui-standard-v1` — one place, not per panel |
+| T3 | **Mutation testing for the TypeScript side** | .NET has Stryker; the UI has none. Today's answer is the coverage floor (kit 95/90, console 97/85) plus an adversarial e2e that drives real services | a UI regression that BOTH the coverage floor and the console smoke miss | whatever we adopt must catch that specific regression, replayed |
+| T4 | The **review agent as a CI step** (it is a manual script today) | It needs an agent-in-CI story; the same one the LLM-half evals wait on | agent-in-CI exists | the agent's findings gate a PR the way the hooks gate a turn |
+| T5 | **LLM-half skill evals** — running the skills themselves per fixture | Deterministic acceptance runs nightly; running the skills needs agent-in-CI | agent-in-CI exists | a skill that fails its evals cannot be released ([ai-sdlc-status.md](ai-sdlc-status.md) §2) |
+| T6 | **CLI-as-MCP** and **plugin packaging** | Both are distribution shapes with no adopter asking yet | CLI-as-MCP: the Insurance sample's first run · packaging: the first brownfield adopter | the shape is exercised by that adopter's own flow, not by a demo we write for it |
+| T7 | **`Goldpath.Ai`** (runtime AI as an opt-in module, ADR-0011) | The console phase owns the calendar; the RFC is written and the ADR is accepted | after the UI phase | the module composes in and out cleanly (a manifest without it has NO AI code), and its evals run in the same lane as the rest |
+| T8 | Bulk's **`?definition=` filter** on `/batches` ([#72](https://github.com/omercelikdev/goldpath/issues/72)) | The console refuses to fake it client-side: narrowing one take-bounded page would read as "no batches" while more exist | the next bulk surface change | the panel filters by definition through the SERVER, and the smoke walks a definition with more batches than one page |
+
+## Closed threads
+
+Kept short on purpose — the point of the list is what is still open.
+
+- **The console's refusal paths** (auth floor, tenant scoping, mid-session death) — closed
+  2026-07-27 by the three-app smoke; found and fixed a discovery bug that reported a
+  composed app as having no admin surface at all.
+- **UI coverage gaps** — closed 2026-07-27 by a measured sweep and a CI floor; found and
+  fixed a deadline verdict that called an overrunning run "on track".
+- **Accessibility** — closed 2026-07-27 by the axe gate; found and fixed the secondary
+  text's contrast and a confirm dialog Escape could not close.
