Skip to content

fix: a deployment that records nothing stops reporting zeros - #188

Merged
danjamk merged 2 commits into
mainfrom
fix/185-analytics-off
Aug 9, 2026
Merged

fix: a deployment that records nothing stops reporting zeros#188
danjamk merged 2 commits into
mainfrom
fix/185-analytics-off

Conversation

@danjamk

@danjamk danjamk commented Aug 8, 2026

Copy link
Copy Markdown
Owner

fix: a deployment that records nothing stops reporting zeros

Closes: #185

Overview

Production ran the whole observability chain this morning with no Analytics Engine binding, and
every signal said healthy:

Surface Said Was true
read_document / list_documents views: 0 on 20 documents nothing is recorded
sync-views succeeded, "0 documents" there was nothing to find
viewsRisk (#165) ok, 0 days at risk there is no history and never will be
Slack heartbeat green

Every surface agreed with every other, which is what made it convincing.

statsFor already refuses to collapse three answers — no sync yet, published since the sync,
measured and never opened — because a 0 that means "not measured" reads as fact at the moment it
is not one. It was missing the fourth: this deployment cannot measure. So the exact failure that
function exists to prevent walked in through a door nobody guarded.

The staleness alarm made it worse rather than catching it: coverage is trivially current when there
is nothing to capture, so the thing built to detect silent data loss reported ok on a deployment
structurally incapable of collecting data.

Summary of Changes

Asked of the binding, never inferred from an empty summary. analyticsEnabled(env) is the same
condition recordView already branches on, so there is one source of truth rather than a second
inferred one — "recorded nothing" and "cannot record" produce identical data and mean opposite
things.

statsFor gains its fourth answer. A document with no history on a non-recording deployment
returns null, not zeros.

syncRisk gains an off state that outranks every other, including losing. Reporting ok
with zero days at risk is technically true and completely misleading.

health says it out loud. Previously the only place this appeared was one line of a deploy log:

! View tracking is OFF on this deployment — nothing is being recorded.
  Documents report no view counts because none exist, not because nobody opened them.
  Enable Analytics Engine on the account, then redeploy with ANALYTICS=on.
  Existing history through 2026-08-08 is intact — it simply stops accruing.

Stored history survives. Turning tracking off does not make what was already measured untrue —
it stops it accruing. Dropping it would destroy real data to fix a display bug.

The parameter is required, not defaulted. A default of true would reintroduce this exact bug
the next time someone adds a reader. The compiler found all six existing call sites in one pass,
which is the point.

Testing

make check      ✓  646 worker tests (8 new), typecheck, guards
node --test     ✓  186 CLI + script tests
make check-docs ✓

Verified against a live deployment with the binding removed — the production shape, not a mock.
I deployed test with analytics: false, confirmed the fix, and restored it:

Check Before After
health silent names it, and names the fix
Never-viewed document views: 0 absent — claims nothing
Document with real history views: 3 views: 3 — unchanged, it was measured

That middle row is the incident in one line.

Not covered: nothing asserts the deploy path sets the binding correctly — that is #187.

Files Changed

  • worker/src/env.tsanalyticsEnabled()
  • worker/src/views.ts — the fourth answer, the off state
  • worker/src/api.ts · worker/src/mcp.ts — six call sites
  • cli/lib/ops/health.mjs · worker/test/views.test.ts · CHANGELOG.md

Deployment Instructions

Deploy and upgrade. No state change — this is a read-path fix.

It does not turn view tracking on anywhere. It makes the "off" state visible instead of
disguising it as zeros. Turning production on is the manual work in #187.

Next Steps

danjamk added 2 commits August 8, 2026 15:13
Production ran the whole observability chain with no Analytics Engine
binding and every signal said healthy. Twenty documents at views: 0, a
successful sync of nothing, zero days of history at risk, a green
heartbeat. Every surface agreed with every other, which is what made it
convincing.

statsFor already refused to collapse three answers — no sync yet,
published since the sync, measured and never opened — because a 0 that
means "not measured" reads as fact at the moment it is not one. It was
missing the fourth: this deployment cannot measure. So the case the
function exists to prevent walked in through a door nobody guarded.

The staleness alarm made it worse rather than catching it. Coverage is
trivially current when there is nothing to capture, so the thing built to
detect silent data loss reported ok on a deployment structurally incapable
of collecting data.

Asked of the binding, never inferred from an empty summary: "recorded
nothing" and "cannot record" produce identical data and mean opposite
things. It is the same condition recordView already branches on, so there
is one source of truth rather than a second inferred one.

Stored history survives. Turning tracking off does not make what was
already measured untrue — it stops it accruing — and dropping it would
destroy real data to fix a display bug.

The parameter is required rather than defaulted. A default of true would
reintroduce this exact bug the next time someone adds a reader, and the
compiler found all six existing call sites in one pass.

Verified against a live deployment with the binding removed, which is the
production shape: health says tracking is off and names the fix, a
never-viewed document reports nothing where it used to report 0, and a
document with real history still reports it.
@danjamk
danjamk merged commit 0be58b5 into main Aug 9, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A deployment that records nothing looks exactly like one nobody visited

1 participant