-
Timmy review build 2026-11-02 — privacy-safe operator health counters (#19)
Pre-ReleaseQuality gates / quality (push) Waiting to runreleased this
2026-11-02 13:29:24 +00:00 | 0 commits to main since this releasePrerelease for review — tag
daily-2026-11-02on commit664a9099571fbbf185ab1e94c45d11502458f490(America/New_York release date 2026-11-02, built 2026-11-02T13:19Z).Delta: privacy-safe operator health counters — disclosed on the privacy screen, and readable as an operator report from the command line. This is a real source change, not a rebuild:
mainmoved from9067ce5(whatdaily-2026-11-01shipped) to664a909.What changed, and what the recording proves
1. The privacy screen now discloses the counters (user-visible). A fourth row,
[data-health-disclosure], sits with the other privacy facts and says what is counted, what is never counted (notes, photos, image fingerprints, identity), and that the counters reset when the server restarts. The recording scrolls that card into frame and reads the app's own sentence first; the scene fails if the copy changes.2.
GET /api/metricsis an operator surface, not a public one. WithTIMMY_METRICS_TOKENunset the route returns 404 (absent, not guarded); with it set, a missing or wrong bearer gets 403 with no counters in the body; a match returns the snapshot. Token comparison is a SHA-256 digest compare (timingSafeEqual), so a wrong-length guess does not leak a prefix.3.
scripts/model_metrics_report.mjsreads that snapshot withoutjq. The recording runs the real CLI against its own server (loopback only, demo token set by the build) and prints what came back — the card on screen is that output, not a fixture:SECTION APP uptime 9m 49s · requests 2 analyzed · 2 refused before the model SECTION QUEUE in flight 0 / 4 · accepted 0 · at capacity no SECTION MODEL readiness disabled · outcomes suggestion 0 · abstained 0 · failure 2 abstention no answers yet · latency mean n/a · max 0ms · samples 0 failures ingress_refused 2, every other class 0 wrong token refused · exit 1 · no countersThose two
ingress_refusedfailures are the hostile-bytes requests this recording made earlier in the same take (device-guard refusal, then the same bytes posted straight at the running server). The scene asserts the count is ≥ 1 before it draws the card, so a zero would fail the recording rather than be captioned as evidence.The privacy property is structural: the formatter imports the three frozen vocabularies and prints only those, so a failure class outside the enum is not printed rather than echoed. No note text, image hash, base64, or caller identity has a path to the terminal — asserted by test, not by convention.
Completed ticket / PR
- PR #92 merged —
feat(metrics): read the privacy-safe health snapshot without jq (#19), merge commit48979bf, Closes #19 (auto-closed 2026-11-02T12:07Z). Reviewed before merge: focused 18-file diff, no secrets, no model weights, no medical imagery;npm test298/298,npm run test:metrics-report8/8,check:syntax,check:diff, andtest:uiin real Chromium all green on the branch in a clean worktree before the merge. - Two corrections on top of the merge, both stated because they were caught by running the thing:
Correction 1 —
ef83ad9. Writing the on-camera scene meant running the new CLI. Its first real output printedfailure ingress_refused0: the longest failure label exactly filled the 22-character column, so label and count rendered as one broken token.LABEL_WIDTHis now 30 and a format test fails if any row loses the gap between its label and its value. (The disclosure-only demo in the PR would never have exercised this — it never ran the CLI.)Correction 2 —
664a909. The first recording was made and inspected at full resolution before publishing, and the card was wrong in a different way:ANALYZE REQUESTSand all eightFAILURE …labels wrapped onto two lines, detaching each label from its count on a 390 px viewport. The card now uses short keys with detail folded into values (one wrappedfailuresline), and was geometry-probed at the recording's own phone viewport before the rebuild: 706 px of content in a 706 px panel, no clipped key. The rebuild was recorded from scratch; no frame from the discarded take is shipped.Gates — 30/30 passed
npm test299/299 (298 merged + the new label-gap regression); mobile green path; photo-first acceptance; sleek Hermes chat; manual fallback + draft recovery; provisional suggestion state; hard-stool follow-up; vision corpus refusal; abstention quality gate; worker container receipts; worker post-load readiness; longitudinal pattern summary; grounded chat citations; training contribution consent; corpus manifest provenance; reviewer adjudication blind; dataset card; calibration harness; operator backup restore; production runbook commands; portable backup restore; image ingress refusal; privacy-safe health metrics; dependency audit (0 high); syntax (node/bash/python); secret scan; forbidden artifacts; demo H.264 720×1280 probe; complete MP4 decode; release delta verified painted on camera (103/103 captions, delta caption on screen, top 14 px, 73 px band, padBottom 14 px).Post-build, independently of the builder:
sha256sum -c SHA256SUMS→ bothOK;ffprobe→ H.264 720×1280 yuv420p, 25 fps, 12,889 frames, 515.56 s, video-only (no audio track, by design);ffmpeg -f null -full decode → exit 0, no errors.The build refused to start while anything held
127.0.0.1:4173, and hash-compares two served files against the clone under test before the first gate — the demo cannot be recorded against a different tree.Artifacts
- source archive
timmy-talking-turd-2026-11-02-664a9099571f.tar.gz— 388,064 bytes — sha256038e2340380541e8f6707d438c1cb988c42271645bd3f06322f212462bb15e8a - demo video
timmy-talking-turd-2026-11-02-664a9099571f-demo.mp4— 31,718,265 bytes — H.264 720×1280 yuv420p, 25 fps, 515.56 s — sha25614aa6a89d6d6ef858b6afd33e98df11814c4ab19edef8cff66bba82f8f87e1dc
Model / profile
Built and recorded by Hermes (profile
default, modeldeepseek-flash). The demo runs the real app from the built commit withTIMMY_VISION_ENABLED=false; the configured vision profile remains self-hostedSmolVLM2-2.2B-Instruct(pinned GGUF) with the hosted profile as fallback. The health report card is a real CLI run against a real server, but that server is in its disabled-AI state, so the report showsreadiness disabledand only the failure classes that state can produce. No live inference appears in the video. No model weights,.env, provider logs, raw corpora, or real medical images are packaged; every log, note, and photo placeholder on screen is synthetic.Operational note
timmy.alexanderwhitestone.comroutes to127.0.0.1:4173. Nothing was listening on that port when this run started, so the public URL had no backend before the build began (this release did not take it down; the gate only requires the port be free while it runs). It is running again from664a909and the public URL answers 200 (/api/healthztoo). The next release build will refuse to start while it runs — that is the gate working as intended, so stop the listener before the build and restart it after.Verified on this run, both auth branches: token unset →
404 {"error":"Not found"}(route absent); token set + wrong bearer →403; token set + match →200snapshot.Review focus
Watch from the privacy screen onward (~7:00–7:30): the disclosure sentence, then the report card. The thing to check is the honesty of the card, specifically two rows —
REQUESTS: 2 analyzed · 2 refused before the modelshould match the two hostile uploads the video showed earlier, andREADINESS: disabledshould make it obvious that this snapshot is from a server with AI switched off, not a claim about model health. If that reads as a health dashboard for a live model, it over-claims and needs rewording.Known accuracy limitation
Unchanged by this release, and not made better by it. Bristol accuracy is not clinically validated; the calibration receipt still reports
BLOCKEDbecause no candidate model clears every gate.queue.inFlightis the app's own admission depth forPOST /api/analyze, not the full bounded queue with cancellation and overload fallback — that is #17, still unmerged (PR #64). User confirmation remains mandatory everywhere: photo analysis may suggest visible Bristol form, broad color, and image quality only, and never symptoms or a diagnosis. Visible color is not blood.Downloads
- PR #92 merged —