# Dashboard navigation and child pages

The Dashboard (`dash.md`, alias Dashboard) is the calm place to choose work, review its health, and open supporting collection and task pages. Its navigation sits immediately after `# Dash`, above `## Tasks`, as three labeled rows in exact reading and keyboard order: Review, Work, Browse.

| Group | Badges, left to right | Purpose |
| --- | --- | --- |
| Review | NEW · ROTTEN · CROWDED | Intake, aging work, crowded notes |
| Work | TODAY · PENDING · NEXT · READY | Today's plan and the actionable lanes |
| Browse | PROJECTS · REFERENCES · BLOCKED · STATS ↗ | Open supporting collection and task pages |

Grouping is navigation only. It never changes the freshness walk, lane semantics, caps, or review sequence, and the Projects collection badge is not the freshness PROJECTS tier.

## Work badge colors

TODAY, PENDING, NEXT, and READY use the same count-to-limit colors in daily `bob-plan` blocks and on `dash.md`. Counts and limits use exact integer comparisons, never rounded displayed percentages. For an available nonnegative integer count `n` and positive integer limit `L`, the colors are:

| Condition | Color |
| --- | --- |
| `n === 0` | grey |
| `0 < n < 2 * L / 5` | blue |
| `2 * L / 5 <= n < 3 * L / 5` | green |
| `3 * L / 5 <= n < 4 * L / 5` | yellow |
| `4 * L / 5 <= n < L` | orange |
| `n === L` | magenta |
| `n > L` | red |

Check zero, strict excess, and exact equality before descending through 80%, 60%, and 40%. Small caps skip bands: cap 1 goes grey → magenta → red, and cap 3 goes blue → yellow → magenta. Orange first appears at cap 5 (`4/5`). A NEXT section at `15/15` is magenta even when a larger whole lane makes it over the whole-lane cap; that condition remains informational and does not make the section over.

TODAY uses `budget.links` for its count and limit. Themes over their cap still override TODAY to red; themes exactly at cap leave the link-based color intact. A missing ledger or invalid count remains unavailable (`–`). Orange (80% up to the cap) and magenta (exactly at the cap) are presentation states, not lints or `over` conditions. Magenta marks a lane that is exactly full, and no other Bob chip uses that hue.

Daily `bob-plan` PENDING/NEXT/READY badges use the same live section counts and colors, including on older daily notes; older notes retain their own TODAY ledger but use current live PENDING/NEXT/READY counts. CLI warnings and navigation notices continue to check the whole lane, including TODAY, while daily `bob-plan` cap lint lines follow the displayed section counts. An unavailable count remains `–` with neutral styling and unavailable accessibility text; it is never converted into numeric zero. Missing ledger data or a missing Pomodoros section remains unavailable, rather than a synthetic `0/limit`.

NEW, ROTTEN, and CROWDED share one Review count rule: muted grey with `0 ✓` when the count is zero, red for every positive count, and `–` when unavailable. ROTTEN follows its displayed count even below the escalation threshold or after the upkeep budget is met.

BLOCKED is informational and has no cap. Its count stays available for navigation and uses the same informational accent as PROJECTS and REFERENCES regardless of its size.

## Child pages

Root-level notes with hierarchy from frontmatter `parent: "[[dash]]"`:

- `dash_projects.md` (alias Dashboard Projects): `# Projects`, `[[dash|← Dashboard]]`, one short active/waiting description, and `![[projects.base#🚀 Active & Waiting]]`.
- `dash_references.md` (alias Dashboard References): `# References`, `[[dash|← Dashboard]]`, one short reading-queue description, one empty ```` ```bob-reading-board ```` fence, and `![[refs.base#🔖 Reading Queue]]`. The board is a read-only kanban (Reading, Next, Ready, Snoozed) drawn from `bob ref list` JSON; the table follows it. The REFERENCES badge still counts the Reading Queue Base view, not the board. The board's fence, lanes, and keys are in [ref.md](<https://bobs-org.github.io/ref/#reading-board-in-obsidian>). The **Open Reading Board** command opens this page, as **Open Stats** opens `dash_stats`.
- `dash_stats.md` (aliases Stats, Dashboard Stats): `# Stats`, `[[dash|← Dashboard]]`, one short derived-metrics description, and one empty ```` ```bob-stats ```` fence. The Browse row ends with a label-only `STATS ↗` chip (no count) with the same chip chrome, hover preview, and click/Enter/Ctrl-click behavior as the other Browse chips. The block draws the schema-1 report from `bob stats`; metric meanings, the review journal, and CLI options live in [stats.md](<https://bobs-org.github.io/stats/index.md>). The daily-note counterpart is the [Day strip](<https://bobs-org.github.io/stats/#day-strip>).

Neither child carries `type: [[project]]`, and no project or reference note moves. The two `.base` files keep all views, filters, columns, formulas, grouping, and sorting. The badge always describes the child's default view, even if a visit switches the embedded table elsewhere.

## Count scopes

- PROJECTS links to `dash_projects`: project notes in the Active &amp; Waiting view, counted once per path. Tooltip: `N projects in Active & Waiting. Open Projects.`
- REFERENCES links to `dash_references`: Markdown reference notes in the Reading Queue, counted once per path. Tooltip: `N references in Reading Queue (next, wip, ready). Open References.`

A successfully evaluated empty view is `0`. Incomplete metadata, a failed source read, or an unrecognized view contract is `–` with a short reason in the tooltip and accessibility label. One unavailable collection never hides the other collection or any task badge. Collection size is informational and never turns red.

## Source and view contract guard

`api.dashboardCollections` (namespace v1, top-level api stays v3) mirrors the two default views without a general Bases interpreter. Project type must resolve through Obsidian's link resolver to `project.md`; a list type never counts. Project status follows Bases `containsAny` (scalar substring, list exact elements). References use exact case-sensitive status equality, the exact `ref/` prefix, and the Markdown extension. No task-only Today, hide, freshness, schedule, or dependency filters apply to either collection.

The plugin parses both `.base` files with the existing Obsidian `parseYaml` dependency and validates only membership-affecting structure, including any result limit, tolerating presentation-only changes. A changed filter or renamed view marks that collection unavailable instead of advertising a stale count. Predicate and contract support must be extended together for a future filter change. Base definitions load asynchronously outside the synchronous `snapshot()`; metadata and vault events refresh open badges after a short debounce, stale async completions are discarded, and widgets are keyed by owning component and kind with cleanup on unload. There is no per-badge polling, and `eval`, table DOM scraping, and private Bases query APIs are never used.
