JSON view returns populated-list / zeroed-stats during warmup with no staleness signal #54

Open
opened 2026-05-23 20:55:27 +00:00 by coilysiren · 0 comments
Owner

Originally filed by @coilysiren on 2026-05-09T05:12:54Z - https://github.com/coilysiren/repo-recall/issues/70

🤖 Filed by Claude Code on Kai's behalf.

The JSON view at /?format=json can return a "populated repo list, zeroed stats" state during dashboard warmup, with no field signaling that the per-repo / per-session subsystem hasn't finished hydrating. An agent that polls this endpoint will read the response as authoritative ("nothing dirty, no uncommitted, no CI failures") and skip real action items.

Reproducer

Curl /?format=json immediately after starting the binary (or after a scan refresh trigger). On a cold/warming dashboard the payload looks like:

{
  "counts": {"repos": 22, "sessions": 0, "links": 0, "commits": 0},
  "uncommitted_groups": [],
  "action_required": [],
  "ci_failures": [],
  "repos": [{"name": "...", "session_count": 0, "commits_30d": 0, "untracked_files": 0, "modified_files": 0, ...}, ...]
}

But the HTML view at / (rendered from the same request handler, presumably) is already showing populated session counts, commit counts, and uncommitted pills. ~5 seconds later, refetching the same JSON URL returns fully-populated stats.

Why this matters

generated_at and last_scan were both fresh (1778302344 / 1778302211) so a freshness check would have falsely passed. There is no populated: false, no warming: true, no HTTP 503, nothing to tell a programmatic consumer "this snapshot is incomplete, retry."

Options

  • Block until populated - hold the JSON request until the underlying caches are hot. Simple; couples request latency to scan latency.
  • Signal staleness in payload - add a populated: bool or state: "warming" | "ready" top-level field. Agents check it. HTML view ignores it.
  • 503 during warmup - cleanest from a polling standpoint. Agents retry, humans hitting the URL get a clear error.
  • Discrepancy alarm - if the HTML render path can render but the JSON serializer returns zeros, the JSON serializer is reading from a different store. Worth understanding why before patching the symptom.

The fourth one is the meta-improvement: figure out why the two render paths diverge during warmup at all.

Concrete trigger

This was caught when an agent (Claude) hit the dashboard right after a session start and reported "no uncommitted changes anywhere" while the user's browser was simultaneously showing 19 dirty repos.

🤖 Filed by Claude Code on Kai's behalf.

_Originally filed by @coilysiren on 2026-05-09T05:12:54Z - [https://github.com/coilysiren/repo-recall/issues/70](https://github.com/coilysiren/repo-recall/issues/70)_ > 🤖 Filed by Claude Code on Kai's behalf. The JSON view at `/?format=json` can return a "populated repo list, zeroed stats" state during dashboard warmup, with no field signaling that the per-repo / per-session subsystem hasn't finished hydrating. An agent that polls this endpoint will read the response as authoritative ("nothing dirty, no uncommitted, no CI failures") and skip real action items. ## Reproducer Curl `/?format=json` immediately after starting the binary (or after a scan refresh trigger). On a cold/warming dashboard the payload looks like: ```json { "counts": {"repos": 22, "sessions": 0, "links": 0, "commits": 0}, "uncommitted_groups": [], "action_required": [], "ci_failures": [], "repos": [{"name": "...", "session_count": 0, "commits_30d": 0, "untracked_files": 0, "modified_files": 0, ...}, ...] } ``` But the HTML view at `/` (rendered from the same request handler, presumably) is already showing populated session counts, commit counts, and uncommitted pills. ~5 seconds later, refetching the same JSON URL returns fully-populated stats. ## Why this matters `generated_at` and `last_scan` were both fresh (`1778302344` / `1778302211`) so a freshness check would have falsely passed. There is no `populated: false`, no `warming: true`, no HTTP 503, nothing to tell a programmatic consumer "this snapshot is incomplete, retry." ## Options - **Block until populated** - hold the JSON request until the underlying caches are hot. Simple; couples request latency to scan latency. - **Signal staleness in payload** - add a `populated: bool` or `state: "warming" | "ready"` top-level field. Agents check it. HTML view ignores it. - **503 during warmup** - cleanest from a polling standpoint. Agents retry, humans hitting the URL get a clear error. - **Discrepancy alarm** - if the HTML render path can render but the JSON serializer returns zeros, the JSON serializer is reading from a different store. Worth understanding why before patching the symptom. The fourth one is the meta-improvement: figure out why the two render paths diverge during warmup at all. ## Concrete trigger This was caught when an agent (Claude) hit the dashboard right after a session start and reported "no uncommitted changes anywhere" while the user's browser was simultaneously showing 19 dirty repos. > 🤖 Filed by Claude Code on Kai's behalf.
coilysiren added
P3
and removed
P2
labels 2026-05-31 07:01:12 +00:00
Sign in to join this conversation.
No labels
P0
P1
P2
P3
P4
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/repo-recall#54
No description provided.