Skip to content

Notices

scripts/dashboard/notices.js builds one bob-notices/1 document: BoB’s inbox (#2071). Each notice is something only Paul can act on, and each carries the one command or link that acts on it. Nothing is stored. Every build reads each source again, so a notice is gone on the first build after its source clears.

One notice is a hint rather than a wait: did-you-know (#2077) names one tool provisioned in the project in view that has never been invoked there, taken from bob tour. It is never counted as needing Paul.

Terminal window
node scripts/dashboard/notices.js # one block per notice, then each source's status
node scripts/dashboard/notices.js --json # the bob-notices/1 document
node scripts/dashboard/notices.js --project <dir> # the did-you-know for <dir> (default: the current directory)
{
"schema": "bob-notices/1",
"generated_at": "2026-09-13T22:00:00.000Z",
"refresh_s": null,
"machine": "farm-01",
"sources": {
"todo": { "status": "ok", "reason": null, "count": 1, "truncated": false },
"blocked": { "status": "ok", "reason": null, "count": 1, "not_measured_machines": ["macbook-air"] },
"decision": { "status": "unavailable", "reason": "rate-limited" },
"bridge-question": { "status": "not-measured", "reason": "pending bridge questions live in the remote-decision-bridge worker, …" },
"release": { "status": "ok", "reason": null, "count": 0, "deployed": "1.273.0", "newest": "v1.273.0" },
"did-you-know": { "status": "ok", "reason": null, "count": 1, "project": "bigbrain", "unknown": 32 }
},
"notices": [
{
"kind": "blocked", "project": "bigbrain", "machine": "farm-01",
"title": "warp run blocked: preflight failed (host)", "ref": "paulirv/bigbrain#2400",
"since": "2026-09-13T20:00:00Z", "stale": false,
"action": { "command": "bob update", "url": "https://github.com/paulirv/bigbrain/issues/2400" }
},
{
"kind": "did-you-know", "project": "bigbrain", "machine": "farm-01",
"title": "bob-mirror: Reconcile and publish to each repo's declared second git host (mirrors.json): …",
"ref": "bob-mirror", "since": null, "stale": false,
"action": { "command": "bob mirror --help", "dismiss": "bob tour --park bob-mirror" }
}
]
}
Key Meaning
kind todo, blocked, decision, release or did-you-know (see below).
priority todo and decision: p1 … p4, from the source issue’s priority label (p1-critical … p4-low, #2477). null means not measured: the issue has no priority label. /bob pins a p1 notice, like every blocked notice, above the Notices fold (#2922), and filters the column by it. Other kinds carry no priority.
project The projects.json name the notice belongs to. For did-you-know, the project directory’s name as bob tour reports it.
machine The machine id for blocked, release and did-you-know. null for todo and decision, which live on the forge, not on a machine.
title One line: the issue title, the failed checks, the release, or the item and when to reach for it.
ref owner/repo#N for an issue, the tag for a release, the item name for a hint, null when there is none.
since When the wait began: the issue’s creation, the decision comment, the failed preflight, the tag. null when not measured, and always null for did-you-know, which is not a wait.
handoff On a todo or blocked notice that has a handoff record (#3058): {kind, what, why, command, text, todo, plan}, the engine’s own words, taken from the fleet feed’s handoffs and matched by todo (owner/repo#N) or, for a blocked run, by machine and project. Absent when there is no record. The needs-you banner renders it.
age_s Seconds from since to generated_at, measured on the document’s clock so a renderer never reads one. null when since is null.
stale true for a blocked notice read from a snapshot older than the fleet feed’s stale_after_s.
action {command}, {url}, or both. A command runs on machine, in the project. did-you-know adds dismiss, the command that parks the item.

Notices are ordered oldest since first, so the longest wait leads. Undated notices come last, and did-you-know after every other kind.

Kind Source Action Clears when
todo Open issues labelled todo without completed in any registered project’s repo: one gh search issues --label todo --state open over the registry’s owners, filtered to repos a projects.json entry on this machine has as its origin. url: the todo. command: gh issue edit N --repo R --add-label completed, the done-signal, once the action is done. completed is added, or the todo is closed.
blocked A project whose warp phase is blocked on any machine in the fleet feed, with the feed’s preflight. command: the failed checks’ fixes, de-duplicated and joined with &&. bob preflight when no fix was recorded (it re-grades and prints them). url: the todo the gate filed. The run leaves blocked. A remote machine’s notice clears with its next snapshot.
decision Open issues whose latest comment is a ## Decision Needed. Candidates come from gh search issues "Decision Needed" --match comments, then each one’s comments are read (at most 20 per build). url: the decision comment. Any later comment, answer or status update, since the question has moved on. The issue closing clears it too.
release The newest vX.Y.Z tag in BOB_SOURCE (as last fetched) is newer than the version in this machine’s BOB_HOME/.bob-version (#2046). command: bob update. The machine is updated to that version.
did-you-know One unknown item from bob tour --json --no-backfill for the project in view: never invoked in that project’s session ledger, and neither tried nor parked. The unknown items, in name order, are indexed by the UTC day number of generated_at, so every build in a day shows the same item and the next day shows the next. A parked or in-use item is never shown. The project in view is the dashboard server’s project, or --project (default: the current directory) on the command line. command: the item’s try-it command from the tour. dismiss: bob tour --park <item>, run in the project, which records the item as parked in <project>/.claude/.tour.json, the state file bob tour owns. The next day, when the rotation moves on. A dismissed item is never shown again, and the next build shows another.

Every source reports a status next to the notices it produced. An empty notices list with every source ok means nothing needs Paul. A source that could not be read is never shown as an empty list.

status Meaning
ok Read. count is how many notices it produced. truncated: true means a search returned a full page of 100, so there may be more.
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. decision with partial: true read some issues and kept their notices.
not-measured There is nothing to read. bridge-question is always this: pending bridge questions live in the remote-decision-bridge worker, which has no read endpoint yet, and .claude/.decisions.jsonl records only answered decisions (decision log). release is this when .bob-version is absent or has no version, or there is no stable tag. todo and decision are this when no project on this machine has a GitHub origin. did-you-know is this when the project’s session ledger holds no events: a cold ledger grades everything unknown, so run bob tour in the project once to backfill it from transcripts. A notices build never backfills.

did-you-know is unavailable when bob tour fails, with its message as the reason. When it is ok, the source also carries project and unknown, the size of the rotation pool.

blocked also lists not_measured_machines: registry machines that published no snapshot, so their runs were never looked at.

  • gh goes through the shim. Every gh call runs on PATH, where the gh shim records its outcome and caches search issues and issue view reads (the forge cache, #1749). When the forge is down, a recent cached read is served instead of a failure.
  • Two searches, then up to 20 views. A build costs two search API calls plus one gh issue view per registered decision candidate.
  • Local reads only for the rest. blocked comes from the fleet feed, release from git for-each-ref and .bob-version, and did-you-know from one scripts/tour/tour.js run (the ledger, the registry and .claude/.tour.json, written by nothing but --tried and --park). None of them makes a network call.

bob dash serve (the one dashboard server, scripts/dashboard/server.js) serves the document at /notices.json. bob viz renders it as the Notices column on /bob.

Behaviour Detail
Refresh Rebuilt at most once every refresh_s seconds (DASH_NOTICES_REFRESH_S, default 60), however many tabs poll it. A request that arrives during a build waits for that build instead of starting another.
Page /bob re-reads /notices.json every 10 s, or every refresh_s when that is shorter. A notice is gone from the page within one rebuild and one poll after its source clears.
gh The forge reads use the server’s own gh runner, so they count toward its gh liveness tracker (#1968). An unreadable todo or decision source carries the server’s reason, which can also be server-cannot-run-gh or gh-failing. The document then gains the same gh evidence block as the /warp panes.
Render scripts/dashboard/bob-notices.js, served as /bob/notices.js, is a pure function of the document. tests/test-notices.js snapshots its output (tests/fixtures/bob-viz/notices.html).
Failure If the document cannot be built at all, the response has notices: [] and an error, and the column shows the error.
Did you know Drawn from the server’s own project (the directory bob dash serve was started for). The column shows it below the list and leaves it out of the “need you” count, with its try-it command and its dismiss command.
  • Fleet Feed: the preflight a blocked run carries
  • bob viz: the page these notices are for
  • Todo format contract: what a todo issue holds
  • tests/test-notices.js: each kind, clear-on-source-change, typed reasons