Skip to content

Reports

scripts/dashboard/reports.js builds one bob-reports/1 document: every report the fleet produced in the last 14 days, newest first (#2073). Reports are a view, not a scroll through GitHub. Nothing is stored. Every build reads each source again.

Terminal window
node scripts/dashboard/reports.js # one block per report, then each source's status
node scripts/dashboard/reports.js --json # the bob-reports/1 document
{
"schema": "bob-reports/1",
"generated_at": "2026-09-13T22:00:00.000Z",
"refresh_s": null,
"machine": "macbook-air",
"window_days": 14,
"since": "2026-08-30T22:00:00.000Z",
"sources": {
"tick-digest": {
"status": "ok", "reason": null, "count": 1,
"machines": [
{ "id": "macbook-air", "source": "local", "as_of": "2026-09-13T22:00:00.000Z", "stale": false, "count": 0, "reason": null },
{ "id": "farm-01", "source": "snapshot", "as_of": "2026-09-13T21:30:00Z", "stale": false, "count": 1, "reason": null }
]
},
"session-report": { "status": "unavailable", "reason": "rate-limited" },
"status-report": { "status": "ok", "reason": null, "count": 0, "truncated": false }
},
"reports": [
{
"kind": "tick-digest", "title": "bob tick 2026-09-13", "at": "2026-09-13T03:12:00Z",
"project": "bigbrain", "machine": "farm-01",
"ref": "paulirv/bigbrain#2311", "url": "https://github.com/paulirv/bigbrain/issues/2311",
"verdict": "ok — 2 merged", "exit": 0,
"markdown": "## bob tick — 2026-09-13 (live) on farm-01\n…", "stale": false
}
]
}
Key Meaning
kind tick-digest, session-report or status-report.
title The issue title. For a digest, bob tick <date>, with the mode in brackets when it was not live.
at When the report was made: a digest’s finished_at (else started_at, else its date), an issue’s createdAt.
project The projects.json name. A digest’s project is matched by its directory, then by basename (a remote machine’s path does not resolve here), else it is the basename.
machine The machine a digest ran on. null for issues, which live on the forge.
ref, url owner/repo#N and its link. A digest links the plan issue the tick ran, which carries the digest comment. Both are null for a digest with no plan; url is null when the plan’s repo is unknown.
verdict, exit A digest’s verdict line and exit code. null for issues.
markdown A digest’s rendered .md, as bob tick wrote it. null for issues, and for a digest whose .md is missing.
stale true for a digest read from a snapshot older than BOB_FLEET_STALE_SECONDS (default 24 h).
state An issue’s open or closed. Issues only.

Reports are ordered newest at first. Anything older than since (generated_at minus window_days) is left out.

Source Read from
tick-digest This machine: every tick-digest/1 in $BOB_HOME/fleet/ticks/ in the window, with its .md. Every other registry machine: its newest snapshot’s last_tick (Fleet Snapshot Timer), since bob tick writes a digest only where it ran (#2054). A remote machine therefore contributes its newest digest, and a new one within one snapshot interval.
session-report gh search issues --label session-report --created >=<since> over the registry’s owners, newest first, filtered to repos a projects.json entry on this machine has as its origin.
status-report The same search for status-report. An issue carrying both labels is listed once, as a session-report.

Every source reports a status:

status Meaning
ok Read. count is how many reports it produced. truncated: true means a search returned a full page of 100, so older reports may be missing.
unavailable The read failed. reason is typed: for gh, the #1968 names (gh-missing, unauthenticated, rate-limited, and, from the dashboard server, server-cannot-run-gh and gh-failing), else unavailable. The digests still list.
not-measured There is nothing to read: no project on this machine has a GitHub origin.

tick-digest.machines says, per machine, where its digests came from: local, snapshot (with as_of and stale), or null with a reason. A machine that published no snapshot, or whose snapshot predates last_tick, is named there, so a missing digest is never mistaken for a machine that ran no tick.

  • gh goes through the shim. Both searches run on PATH, where the gh shim caches search issues reads (the forge cache, #1749). When the forge is down, a recent cached read is served instead of a failure.
  • Two searches. A build costs two search API calls.
  • Local reads for digests. This machine’s tick directory and the snapshot directory. No network call.

bob dash serve (the one dashboard server, scripts/dashboard/server.js) serves the document at /reports.json. bob viz renders it as the Reports pane on /bob.

Behaviour Detail
Refresh Rebuilt at most once every refresh_s seconds (DASH_REPORTS_REFRESH_S, default 120), however many tabs poll it: a build runs two issue searches. A request that arrives during a build waits for that build instead of starting another. A digest published in a snapshot is on the page within one snapshot interval plus one rebuild and one poll.
Page /bob re-reads /reports.json every refresh_s and repaints only when the pane changed, so a digest folded or opened by hand stays that way. Each entry shows its kind, machine and project, its date, and its title linked to its issue. A tick digest also shows its verdict and its markdown; the newest digest is open and the rest fold.
gh The issue searches use the server’s own gh runner, so they count toward its gh liveness tracker (#1968). An unreadable session-report or status-report carries the server’s reason, which can also be server-cannot-run-gh or gh-failing, and the document gains the same gh evidence block as the /warp panes. The pane prints each reason with what to do about it, and still lists the digests.
Render scripts/dashboard/bob-reports.js, served as /bob/reports.js, is a pure function of the document. It renders the markdown bob tick writes (headings, bold, code spans, pipe tables, - lists) from escaped text, so nothing inside a digest can inject markup. tests/test-reports-pane.js snapshots its output (tests/fixtures/bob-viz/reports.html).
Failure If the document cannot be built at all, the response has reports: [] and an error, and the pane shows the error. “no reports in the last 14 days” appears only when every source was read.
  • Notices: the bob-notices/1 inbox built the same way
  • Fleet Snapshot Timer: last_tick, and what keeps it fresh
  • bob viz: the page these reports are for
  • tests/test-reports-pane.js: ordering, the 14-day window, gh unavailable