|
| 1 | +<!doctype html> |
| 2 | +<html lang="en"> |
| 3 | +<head> |
| 4 | + <meta charset="utf-8"> |
| 5 | + <title>Implementation Plan: Issue #166 Readiness Serving/Freshness Contract</title> |
| 6 | + <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 7 | + <style> |
| 8 | + body { margin: 0; font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #f6f7f9; color: #1f2937; line-height: 1.5; } |
| 9 | + main { max-width: 1100px; margin: 0 auto; padding: 32px; } |
| 10 | + section { background: #fff; border: 1px solid #e5e7eb; border-radius: 8px; padding: 20px; margin: 16px 0; } |
| 11 | + h1, h2 { line-height: 1.2; margin-top: 0; } |
| 12 | + code { background: #f3f4f6; padding: 2px 5px; border-radius: 4px; } |
| 13 | + .badge { display: inline-block; padding: 4px 10px; border-radius: 999px; background: #fee2e2; color: #991b1b; font-size: 12px; font-weight: 700; } |
| 14 | + .note { border-left: 4px solid #2563eb; } |
| 15 | + .risk { border-left: 4px solid #dc2626; } |
| 16 | + .approval { border-left: 4px solid #d97706; } |
| 17 | + </style> |
| 18 | +</head> |
| 19 | +<body> |
| 20 | +<main> |
| 21 | + <h1>Implementation Plan: Issue #166 Readiness Serving/Freshness Contract</h1> |
| 22 | + <p class="badge">Approved and implemented</p> |
| 23 | + |
| 24 | + <section> |
| 25 | + <h2>Task Summary</h2> |
| 26 | + <p> |
| 27 | + Define and implement the stable readiness freshness/confidence contract that |
| 28 | + dashboard, iOS, MCP, and later confidence UI can consume without duplicating |
| 29 | + backend logic. This issue is broader than the already-executed |
| 30 | + <code>2026-05-28-readiness-serving-freshness-closure.html</code> plan: that |
| 31 | + plan closed bounded restamp/backfill wiring, while this one should formalize |
| 32 | + the API shape and consumer semantics. |
| 33 | + </p> |
| 34 | + </section> |
| 35 | + |
| 36 | + <section> |
| 37 | + <h2>Current Behavior</h2> |
| 38 | + <ul> |
| 39 | + <li><code>internal/health/types.go</code> already exposes <code>readiness_confidence</code>, <code>readiness_cap_reason</code>, <code>readiness_components</code>, and per-component <code>freshness</code>, <code>confidence</code>, <code>sample_count</code>, and <code>missing_reason</code> on <code>BriefingResponse</code>.</li> |
| 40 | + <li><code>internal/storage/briefing.go</code> builds date-aligned readiness evidence from daily cache plus same-day raw metric fallback, including missing and stale states.</li> |
| 41 | + <li><code>/api/health-briefing</code> returns the full <code>BriefingResponse</code>; <code>/api/readiness-history</code> returns score and band only.</li> |
| 42 | + <li><code>internal/mcpserver/tools.go</code> has <code>get_health_briefing</code> and <code>get_readiness_history</code>, but tool descriptions still describe the older readiness formula and do not call out freshness/confidence metadata.</li> |
| 43 | + <li>Dashboard page rendering currently reads confidence and cap reason into the page data, but confidence UI is intentionally not the goal of this issue.</li> |
| 44 | + </ul> |
| 45 | + </section> |
| 46 | + |
| 47 | + <section> |
| 48 | + <h2>Desired Behavior</h2> |
| 49 | + <ul> |
| 50 | + <li>One documented server-owned readiness state vocabulary: fresh, stale, missing, data-accruing, low-coverage, and capped/provisional states.</li> |
| 51 | + <li>API consumers can decide display state from response fields only; no client should infer freshness from dates or recompute coverage.</li> |
| 52 | + <li>Existing score values remain behavior-compatible unless tests expose a mismatch between score and metadata.</li> |
| 53 | + <li>Dashboard and MCP continue to work, with richer metadata available and documented for future confidence UI.</li> |
| 54 | + </ul> |
| 55 | + </section> |
| 56 | + |
| 57 | + <section> |
| 58 | + <h2>Assumptions And Unknowns</h2> |
| 59 | + <ul> |
| 60 | + <li>Assumption: the primary contract should be attached to <code>/api/health-briefing</code> first because it already owns <code>BriefingResponse</code>.</li> |
| 61 | + <li>Assumption: <code>/api/readiness-history</code> should stay lightweight unless the confidence UI needs historical confidence states.</li> |
| 62 | + <li>Unknown: whether <code>data_accruing</code> should be represented as a new readiness freshness enum or mapped through <code>confidence=provisional</code> plus reason.</li> |
| 63 | + <li>Unknown: whether MCP needs a separate concise readiness contract tool or simply better descriptions for existing tools.</li> |
| 64 | + </ul> |
| 65 | + </section> |
| 66 | + |
| 67 | + <section> |
| 68 | + <h2>Files Likely To Change</h2> |
| 69 | + <ul> |
| 70 | + <li><code>internal/health/types.go</code> - add or tighten response structs/enums only if the current fields cannot express the contract cleanly.</li> |
| 71 | + <li><code>internal/storage/briefing.go</code> - normalize evidence mapping and reasons if stale/missing/low-coverage cases are inconsistent.</li> |
| 72 | + <li><code>internal/storage/readiness_evidence_test.go</code> or related tests - cover fresh, stale, missing, low-coverage, and data-accruing/provisional cases.</li> |
| 73 | + <li><code>internal/ui/handler.go</code> and UI tests - only if response wrapping or dashboard API shape needs explicit metadata preservation.</li> |
| 74 | + <li><code>internal/mcpserver/tools.go</code> - update readiness tool descriptions and, if approved, expose concise contract metadata.</li> |
| 75 | + <li><code>README.md</code>, <code>docs/ARCHITECTURE.md</code>, or a small new API doc - document the contract for dashboard and MCP/debug consumers.</li> |
| 76 | + </ul> |
| 77 | + </section> |
| 78 | + |
| 79 | + <section> |
| 80 | + <h2>Implementation Steps</h2> |
| 81 | + <ol> |
| 82 | + <li>Write a short contract table before code edits: fields, allowed values, producer, and intended consumer behavior.</li> |
| 83 | + <li>Audit current readiness evidence outputs against that table for fresh, stale, missing same-day value, low HRV sample count, missing sleep-stage details, and illness/stress cap scenarios.</li> |
| 84 | + <li>Add focused tests for the current mapping. Prefer tests around pure or near-pure evidence builders before touching handlers.</li> |
| 85 | + <li>If the current fields cannot express <code>data_accruing</code> cleanly, add a small explicit reason/status field rather than changing existing score semantics.</li> |
| 86 | + <li>Update MCP descriptions and docs so the contract is discoverable.</li> |
| 87 | + <li>Run focused tests first, then full Go test/vet before PR.</li> |
| 88 | + </ol> |
| 89 | + </section> |
| 90 | + |
| 91 | + <section> |
| 92 | + <h2>Impact</h2> |
| 93 | + <ul> |
| 94 | + <li><strong>API:</strong> additive metadata only; no removal or rename of existing JSON fields.</li> |
| 95 | + <li><strong>Data/migration:</strong> no schema migration expected.</li> |
| 96 | + <li><strong>Auth/permissions:</strong> no change.</li> |
| 97 | + <li><strong>UX:</strong> no new confidence UI in this issue; it prepares that work.</li> |
| 98 | + <li><strong>Deployment:</strong> normal app deploy after tests if code changes are needed.</li> |
| 99 | + </ul> |
| 100 | + </section> |
| 101 | + |
| 102 | + <section> |
| 103 | + <h2>Test Plan</h2> |
| 104 | + <ul> |
| 105 | + <li><code>go test ./internal/health ./internal/storage -run "Test.*Readiness.*Evidence|Test.*Readiness.*Confidence" -count=1</code></li> |
| 106 | + <li><code>go test ./internal/ui ./internal/mcpserver -count=1</code> if handlers or MCP descriptions are touched.</li> |
| 107 | + <li><code>go test ./...</code></li> |
| 108 | + <li><code>go vet ./...</code></li> |
| 109 | + <li>Optional direct DB smoke with <code>~/.health-db</code>: inspect one current <code>/api/health-briefing</code>-equivalent row and confirm metadata matches actual same-day availability.</li> |
| 110 | + </ul> |
| 111 | + </section> |
| 112 | + |
| 113 | + <section class="risk"> |
| 114 | + <h2>Risks And Edge Cases</h2> |
| 115 | + <ul> |
| 116 | + <li>Changing numeric readiness behavior under a metadata issue would blur scope; keep score changes out unless a contract test reveals a bug.</li> |
| 117 | + <li>Adding too many enums could make client logic harder; prefer a small stable vocabulary plus reason strings.</li> |
| 118 | + <li>Historical readiness points may not have enough evidence to expose detailed metadata without extra queries.</li> |
| 119 | + </ul> |
| 120 | + </section> |
| 121 | + |
| 122 | + <section> |
| 123 | + <h2>Rollback Plan</h2> |
| 124 | + <p>Revert additive metadata and documentation changes. No database rollback should be required. Existing consumers should continue to work throughout because the plan avoids removing current fields.</p> |
| 125 | + </section> |
| 126 | + |
| 127 | + <section> |
| 128 | + <h2>Open Questions</h2> |
| 129 | + <ul> |
| 130 | + <li>Should <code>/api/readiness-history</code> gain historical confidence metadata now, or should that wait for the confidence UI issue?</li> |
| 131 | + <li>Should <code>data_accruing</code> be a freshness enum, a cap reason, or a separate serving state?</li> |
| 132 | + <li>Which doc should be canonical for API consumers: README, architecture doc, or a dedicated API contract section?</li> |
| 133 | + </ul> |
| 134 | + </section> |
| 135 | + |
| 136 | + <section> |
| 137 | + <h2>Implementation Result</h2> |
| 138 | + <p> |
| 139 | + Implemented on 2026-06-06. The change is additive: existing |
| 140 | + <code>readiness_confidence</code>, <code>readiness_cap_reason</code>, and |
| 141 | + <code>readiness_components</code> fields remain in place, and clients can |
| 142 | + now prefer the grouped <code>readiness_serving</code> object. |
| 143 | + </p> |
| 144 | + <ul> |
| 145 | + <li>Added <code>ReadinessServingState</code> with <code>status</code>, <code>confidence</code>, <code>reason</code>, and component evidence.</li> |
| 146 | + <li>Added serving status values: <code>fresh</code>, <code>missing</code>, <code>stale</code>, <code>data_accruing</code>, <code>low_coverage</code>, and <code>capped</code>.</li> |
| 147 | + <li>Kept readiness score behavior unchanged; the new object summarizes existing evidence/cap metadata for consumers.</li> |
| 148 | + <li>Kept serving state synchronized when coherence or illness safety caps update readiness metadata after initial scoring.</li> |
| 149 | + <li>Updated MCP descriptions and README documentation so consumers know to use <code>readiness_serving</code> instead of guessing.</li> |
| 150 | + <li>Added tests for missing evidence priority, sparse-HRV data-accruing status, illness cap status, low-coverage status, and <code>ComputeBriefing</code> response exposure.</li> |
| 151 | + </ul> |
| 152 | + </section> |
| 153 | + |
| 154 | + <section> |
| 155 | + <h2>Verification Run</h2> |
| 156 | + <ul> |
| 157 | + <li><code>go test ./internal/health ./internal/storage -run "Test.*Readiness.*Evidence|Test.*Readiness.*Serving|TestComputeBriefing_ExposesReadinessServingContract" -count=1</code> passed.</li> |
| 158 | + <li><code>go test ./internal/ui ./internal/mcpserver -count=1</code> passed; <code>internal/mcpserver</code> has no test files but compiled.</li> |
| 159 | + <li><code>go test ./internal/health ./internal/storage -count=1</code> passed.</li> |
| 160 | + <li><code>go test ./...</code> passed.</li> |
| 161 | + <li><code>go vet ./...</code> passed.</li> |
| 162 | + </ul> |
| 163 | + </section> |
| 164 | + |
| 165 | + <section> |
| 166 | + <h2>Known Limitations After Implementation</h2> |
| 167 | + <ul> |
| 168 | + <li><code>/api/readiness-history</code> still returns lightweight score and band data only; historical confidence metadata remains a future confidence UI decision.</li> |
| 169 | + <li>No database migration or historical backfill was added; this is a response-contract change over current evidence.</li> |
| 170 | + <li>No new visual confidence UI was added in this issue.</li> |
| 171 | + </ul> |
| 172 | + </section> |
| 173 | + |
| 174 | + <section class="approval"> |
| 175 | + <h2>Approval Gate</h2> |
| 176 | + <p>Approved and implemented. Further confidence UI or historical readiness metadata should use a separate follow-up plan.</p> |
| 177 | + </section> |
| 178 | +</main> |
| 179 | +</body> |
| 180 | +</html> |
0 commit comments