Every card below renders what `bob capture --dry-run --no-clip --format json` returns for the current draft, in `bob`'s own order. The explicit Preview button and Capture resolve the clipboard and mirror the full block; continuous live preview passes `--no-clip`. Insertion behavior for the rows is in [Task pickers](<https://bobs-org.github.io/reference/mac-capture/task-pickers/index.md>) and [Relationship pickers](<https://bobs-org.github.io/reference/mac-capture/relationship-pickers/index.md>).

Synthetic CI render. Open the image for full-size text.

## Start overrides

A `=` override restart or swap previews on the same start card with an orange warning banner as the first row, reworded titles, status, badges, footer action, and notifications, built only from Bob's additive `pomodoro_start.override` object (`action` restart/swap, leftover `"start"` as a plain start, `ledger` kept/fresh, `previous` including `overdue`, `demoted`, `close_first`). An older Bob that omits the object decodes as a plain `=` start with no behavior change, and an unknown override action degrades to a plain start; the app never computes ledger ranges itself. The footer's primary Return tints orange whenever the on-screen preview contains an override. An override commits only after its warning was on screen: every real submit passes hidden `--refuse-override` unless that preview belongs to this exact draft, analysis generation, and bob client and shows the override. A `pomodoro_override_refused` answer keeps the draft, re-previews, and asks for Return again. An older bob that rejects the flag is retried without it and that answer is remembered for that executable.

## Templates

A Bob `template` candidate for `@@te` or `@@` is shown as the `@@template:` directive with Bob's label beneath it; accepting inserts Bob's replacement verbatim. The `+` shortcut does not accept this header candidate. When the route list includes a template candidate at bare `@@`, its header shows that typing `@` again starts a template.

Template fields decode tolerantly: an older Bob omits them and keeps ordinary drafts working. A new Bob with an older app exposes unknown template span kinds as neutral text. An older Bob refuses `@@template:` before writing anything, so upgrade Bob before submitting a template draft.

Template drafts live in the [Saved templates](<https://bobs-org.github.io/reference/mac-capture/saved-templates/index.md>) shelf.

## Live preview

Live preview calls `bob capture --dry-run --no-clip --format json -- <draft>` through a dedicated process-client API that asserts `--no-clip`. Bob's admitted URL `%` listen marker remains a reference request in continuous preview; ordinary clipboard spans stay literal until the separate explicit clipboard-resolving preview. Template previews show a `Template · N rows` capsule beside the capture count. When Bob reports the `template_row` need, the panel keeps the preview calm and shows Bob's `template_missing_rows` message. Non-info template diagnostics underline the matching typed text in the editor.

## Batch drafts and authored children

The additive `sub_bullets` field on `capture` output is the exact rendered authored child lines, including Bob's target-selected indentation, and is omitted entirely when a draft has no authored bullets. `capture-parse` keeps `sub_bullets` as normalized bodies and adds aligned `sub_bullet_depths` values (`1` or `2`); missing depths from an older `bob` decode as depth `1`, and mismatched depths are ignored safely. `capture-parse` also decodes Bob's additive `items` array for batch drafts, preserving item index, source range, physical line range, route, section, needs, and authored-child depths. Its additive `global_destination` object is decoded tolerantly; absent metadata means the connected `bob` binary predates global destination declarations. Template parsing adds a nullable header/range/field/row object and per-row items with UTF-8 source ranges. Template rows never open pickers; a row-incomplete need keeps the dry-run preview idle until a row is added. Capture responses add a template summary and per-capture row numbers, including the legacy one-result response shape.

## Capture results

`bob capture --format json` keeps the legacy top-level first result for a single capture or compatibility fallback, and may add an ordered `captures` array for a batch. The app normalizes both shapes to one collection before updating preview, status, VoiceOver announcements, and notification content; it forwards the batch-level `open_notes` array unchanged for Control-Return instead of re-deriving destinations. It keeps the additive top-level `global_destination` summary alongside that normalized collection and never splits a draft into multiple mutating `bob` subprocesses. When live preview reports exactly one `task_toggle`, the footer's primary action changes from **Capture** to **Set Next**, **Set Open**, or **Ensure Next** according to Bob's returned behavior metadata; when it reports exactly one `pomodoro_link`, the action becomes **Start** if the link starts a session and **Link** otherwise; a single close — whole-item `x`, link `=x`, or new-task `=x` — becomes **Close**; a single whole-item `=`/`=<X>` start becomes **Start**, a `=` restart of the running session becomes **Restart**, and a `=#name` swap becomes **Swap**; a single whole-item `!note:block-id` completion becomes **Complete**; batches keep **Capture** because Return will submit more than the toggle. Ensure Next preview, VoiceOver, and notifications present status and relocation independently ("Ready → Next" vs "Next unchanged", "Moved LATER → CURRENT" vs "Already in CURRENT; no Pomodoro changes") and never show the two-way "adds link" or "removed later links" rows. Committed notification titles summarize the actual result (combined, status-only, move-only, or already-Next no-op); Open Note/Open Notes includes the daily note only when `pomodoro_link_action` is `moved`. Pomodoro-link captures notify as `Started NAME`, `Linked to NAME`, `Moved to NAME`, or `Already in NAME`, batch lines use the link transition text under a `Link` kind, and Open Note/Open Notes includes the daily note whenever the link inserted, moved, or started a session. A Pomodoro close notifies as `Closed NAME` with a session-and-timing line, a tasks-and-Work-Log line (with a completed count when nonzero), and the next-session line; link and new-task closes use the same title and body, batch lines append `(closed NAME)` under a `Close` kind, and Open Note targets the day file, which a close always writes. A project note that links tasks previews a link section ("Links 2 tasks into ADMIN (new)", one row per task with its text and `^id`), notifies "Linked 2 tasks into ADMIN", and includes the daily note in Open Note(s) whenever `task_links` is non-empty.

## Preview stack

Preview shows every block Bob will write, in Bob's own order: each item's parent

`task_line`, authored children, then `clip.lines` and `schedule_log.lines` when the response carries them. Task-toggle items instead show the route/block destination, the status transition, the daily-note destination, and the `+` or `−` Pomodoro-link line Bob planned. Pomodoro-link items show the route/block destination, the status transition (`[ ] → [*]`, `[*] already Next`, `[/] stays In Progress`), the daily-note destination, and the ledger outcome Bob planned (`Linked under BUGS`, `Moved Task Link BUGS → FOCUS (created FOCUS)`, or `Task Link already in BUGS; no ledger change.`), plus the atomic-start session row when the link starts one. Every item with a `pomodoro_link_destination` also shows a destination row above it (`→ GOALS · next up`, `→ running GOALS 0945–1015`, `→ new Pomodoro BOB`, with a `timer` symbol) from the destination `role`, and a batch that changed today's Pomodoros section shows one plan-budget meter row above the items (`Themes 3/3`, `Links 8/10` capsules — green within the cap, red over — a `+1 BOB` delta chip whenever the themes meter grew, and orange warning captions). Both rows join the VoiceOver summary.

### Close card

A Pomodoro close instead shows its own card whenever `pomodoro_close` is present: a `stop.circle.fill` header with the `Close NAME` title and the monospaced session range (the shortened half tinted with the Pomodoro-session colour), the day-file destination plus a timing chip that is orange when early, green when on time, and secondary when over, a `link` via row for link closes (`Linked bob.md · ^ready into CAPTURE`, `Moved from SASE`) or a `plus.circle` row for new-task closes, up to six task rows with per-role glyphs, transitions (`[*] → [/]`, `[*] deferred`, `[x] closed`, `[x]`), text with strikethrough on struck rows, trailing locators, and Work Log previews — badges, transitions, and tags never wrap or shrink, and at narrow widths the locator truncates first, then the one-line task title; row titles show wikilink display text (`[[path|Alias]]` reads `Alias`), like the pickers — each row shows its `typed_work_log` entries first, all of them, with the date stripped, a `square.and.pencil` glyph in the cyan log tint, and primary text, each followed by its `typed_work_log_details` lines in secondary callout text, indented to the entry text with no glyph and never capped, followed by the remaining `work_log` entries in secondary text capped at two — then a notes row (`1 note stays`), a next-session footer row, and an empty state (`No Task Links — the session simply closes`) when there are no task rows. Numbered rows start with a fixed-width badge — a filled `N.circle.fill` when the row is listed, an open `N.circle` otherwise (monospaced digits in a capsule past 50), tinted orange for in progress, green for complete, and secondary for deferred, with unlisted rows dimmed so chosen rows stand out; unnumbered rows keep a clear spacer so text stays aligned, and with no numbered rows the card looks exactly like today's. Completed rows keep the embedded glyph tinted green with struck text and a `[*] → [x]` transition when the status changed. One caption row under the task rows teaches the syntax before a selection is typed (`x1,2 keeps only these in progress · … · x 2   wrote the tests logs work to 2`, tinted like the editor spans, with the `2` in the cyan log tint) and shows the outcome summary after (`In progress 1, 3   · Complete 2 · Deferred 4`, or `In progress none` for `x0`); numbered rows never hide under `+N more`. The accessibility label includes the typed entries with their details after each entry. The footer's primary action becomes **Close**, the live-preview, preview, and submit status read `Would close …` / `Closed …` with started, completed (only when nonzero), and Work Log counts, and a failed dry run clears the card so no stale preview sits beside the error. The error callout shows Bob's message unchanged; a strict plan-budget refusal (`code == plan_theme_cap_exceeded`) adds the hint line `Queue it with ^ or   defer with $<N>.` While a list dangles on `,`/`!`/`~`, the card previews the trimmed draft dimmed with a `Type a task number after ,` row, **Close** is disabled, and Return cannot submit; while a Work Log bullet dangles (`x` plus `- 1`), the card previews the rest dimmed with a `Type the Work Log entry for task 1` row, **Close** stays disabled, and Return cannot submit; a valid draft restores the normal card. While a start list dangles on `~`/`,`, the start card previews the trimmed draft dimmed the same way with **Start** disabled instead.

### Start card

A whole-item `=`/`=<X>` start instead shows its own card whenever `kind` is `pomodoro_start`: a `play.circle.fill` header with the `Start NAME` title and the monospaced session range, the day-file destination, then one caption row — the teaching hint before a drop is typed, the drop summary after (`Dropped 2, 4`, plus `· nothing left queued` when nothing stays queued), or the pending notice while a list dangles — followed by the queued-task rows merged with dropped rows in lineup order. A restart or swap puts an orange warning banner first on the card (`Overrides the running CAPTURE`, with the session range, a detail line, and a monospaced `x =` chip to close it first) and tints the footer's primary Return orange. A `=` restart keeps the start pink but swaps the header glyph for `arrow.clockwise.circle.fill`, retitles to `Restart NAME` / `Restarted NAME`, reads `Would restart CAPTURE 0920-0945 → 0935-1000 (15m) at line 5` in the status, and adds a dim `was 0920–0945` caption under the destination. A `=#name` swap instead uses `arrow.left.arrow.right.circle.fill`, retitles to `Swap in NAME` / `Swapped in NAME`, reads `Would swap in BUGS 0920-0945 (takes over CAPTURE) at line 5` for a kept ledger (or the fresh session range otherwise), adds a `Takes over` capsule next to the title when the swap keeps the running ledger, and adds an `arrow.uturn.down` demoted row (`CAPTURE → first future · keeps 2 Task Links`, plus `and its notes`). Each numbered row gets the close card's number badge (`n.circle`, filled for dropped rows, capsule above 50) with status glyphs (`circle` Ready, `circle.inset.filled` Next, `circle.lefthalf.filled` In Progress, `questionmark.circle` other, `minus.circle` dropped, `exclamationmark.triangle` unresolved with the warning as help text), task text (wikilink display text, like the pickers) with a truncating `note ^id` locator; dropped rows render struck and dimmed with a caption joining `stays <status>` and `with N nested line(s)`. Numbered rows never hide under `+N more`; rows without numbers (older Bob) render exactly like today's card. A created session shows a small pink **New** capsule next to the title on a dry run (**Created** once committed, and the notification reads `Started NAME` with `0905–0930 (25m)   · New session`); with no drop typed and a non-empty lineup, a bare `=`/`=<X>` start teaches `Type ~2 to drop task 2 · #name to start a specific Pomodoro` (`Type ~1 to drop it · …` for one row), with `~N` tinted like the drop span and `#name` like the editor's name span, while a named start teaches only the drop half. An empty lineup keeps the quiet `Type #name to start a specific Pomodoro` caption, and named starts with an empty lineup show no hint. Dropped rows read "Task 2, …, drops from today" and queued rows "Task 1, …, queued" for VoiceOver. A `=` that overrides the running session shows the orange banner on the start card instead of a still-running error, and an override commits only after its warning was on screen. The footer's primary action becomes **Start** (**Restart** for a restart, **Swap** for a swap), the live-preview, preview, and submit status read `Would start …` / `Started …` with the session and line (plus `· drops 2` / `· dropped 2` once a drop is typed), `Would restart …` / `Restarted …` with the before → after range for a restart, and `Would swap in …` / `Swapped in …` with the takeover or fresh range for a swap, and the notification reads `Started NAME` with the session and queued-task count (counting `tasks` only, plus `· dropped 2`), `Restarted NAME` with the en-dash session, queued count, and `· was 0920–0945`, or `Swapped in NAME` with the taken range and the demoted session back to first future. One item stays compact; a batch renders an ordered stack with item count, destination/kind metadata, dividers, and exact `previewBlockLines` or toggle transition rows. When Bob reports a global destination, preview and the destination detail show one compact shared-scope line (`All items → foo.md` or `All items → foo.md · under ^a-id`) and mark item-level deviations as local overrides instead of repeating the shared target on every item. The outer auxiliary detail region owns scrolling, so preview itself never nests another scroll view. The preview card always takes its natural height: the window grows to show it in full up to the screen limit before the auxiliary region scrolls, and the card keeps its last rendered height while a live preview reloads. Continuous live preview passes `--no-clip`, so it has no `clip` to show; the explicit **Preview** button and **Capture** resolve the clipboard and therefore mirror the full block.

### Pomodoro and task blocks

Whenever Bob reports batch-level `pomodoro_blocks`, every Pomodoro the capture touches, creates, or reports renders once below the item stack as a full block view: a status caption (`Running · line 27` with a `play.circle.fill` glyph, `Completed` with `checkmark.circle.fill`, `Queued` with `circle.dashed`) plus a pink **New** capsule on a dry run (**Created** once committed), then a card with a status rail, a diff gutter (`+` green for added lines, `•` accent for changed lines with the old text on hover, `−` red for removed lines), indent guides per depth, and the verbatim lines Bob will write — tinted like the editor (pink time range, wikilink colors, checkbox colors) with no truncation. An added line Bob marks as a surviving successor link carries a trailing `lock.open.fill` badge (`Unblocked successor` on hover and to VoiceOver). Standard items whose verbatim lines the blocks already cover omit the duplicated stack, and the blocks dim to 0.6 together with the close card while a close-list selection dangles. An older Bob that omits `pomodoro_blocks` previews exactly as before. `PomodoroBlockDesignTests` renders the adjust, close, link-move, created-named-start, and chain fixtures to PNG (light/dark, 760/620 pt, scale 2) when `BOB_MAC_CAPTURE_RENDER_DIR` is set. Whenever Bob reports batch-level `task_blocks`, every parent task a sub-bullet capture wrote under renders once below the item stack as a full task card, before the Pomodoro blocks: a picker-status caption (`In Progress · sase.md · line 1` with the `@+` chooser glyph and color) plus a pink **New** capsule on a dry run (**Created** once committed), then the shared diff card with task tinting (tertiary list markers, checkbox colors, secondary `#tags` and `[key:: value]` fields, indigo trailing `^block-id`, wikilink colors, semibold task-line prose) and no truncation. Covered sub-bullet items switch to a compact `↳ Sub-bullet under ^id` header (with `› SECTION` when Bob reports one) and drop the verbatim stack and trailing note line; uncovered items render exactly as before. Blocks above 24 rows fold quiet runs of 4 or more unchanged rows into `⋯ N unchanged lines` rows that expand on click (with a **Show all lines** action); smaller blocks never fold. A single sub-bullet names its parent in the status and summary (`Preview → sase.md › ^id`), and an older Bob without `task_blocks` previews exactly as before. `TaskBlockDesignTests` renders

## Deterministic scheduling

The preview path assigns a fixed `BOB_PRIORITY_ROLL_SEED` for the draft lifecycle so randomized `$<N>` scheduled dates can be reused by submission. Bob derives item-specific rolls from that seed for batch drafts, and the seed resets only after a successful capture or discard.

## Completing tasks with `!`

## Completing tasks with `!`

A capture item that is exactly `!note:block-id` completes that existing open task without closing a Pomodoro: the task line closes exactly as `x!N` would write it, its Task Links retire in today's ledger the way `bob task reconcile` would retire them, and Blocked dependents recover the way Ctrl+Enter recovers them. Bulk works one `!` item per blank-line-separated block; any failure rolls the whole batch back.

The completion preview card shows the struck task (`[*] → [x]` with Bob's clean task text struck and dimmed), one row per closed embedded subtask, one row per descendant left open, the ledger effect named per entry (`Strikes/Struck its Task Link in CAPTURE`, with `(completed)` for completed entries, `Moves/Moved its Task Link SASE → CAPTURE, struck`, `Task Link already in PLAN; drops/dropped the SASE copy`, `removes/removed empty SASE`), and one row per unblocked dependent — with `list.bullet.indent`, `timer`, and `lock.open.fill`/`lock.fill` fact rows under a green `checkmark.circle.fill` seal (`Already done — nothing to change` in gray for the idempotent no-op). A dependent Bob linked into the predecessor's slot renders with the Next tint, a trailing destination capsule (`→ FIX`, `→ new BOB · next up`), an `added ^id` caption when Bob minted its block ID, and an `inbox` capsule when it lives in an inbox file; a recovered dependent renders secondary with a reason caption (`Ready · not planned today`); a dependent that stays blocked renders muted with `lock.fill` and a `stays Blocked · …` caption. An older Bob without `text`, `struck_in`, or `dropped` keeps the count-based ledger wording and the local task-line text. The footer action is **Complete** and every fact joins the VoiceOver summary. Notifications read `Completed: <task>` (`Completed N tasks` for an all-completion batch) with `sase.md · unblocked <name>` bodies, plus one extra line when anything was linked (`🔓 Next in FIX: <task>`, `🔓 3 linked → FIX: …`, `🔓 3 linked · FIX, SASE`) or the breaker fired. Open Note(s) includes the daily note whenever the ledger changed or any successor was linked. An older Bob without `task_complete` decodes as no completion preview and keeps the standard card; upgrade Bob before using `!`.

## Saving links to your reading queue

## Saving links to your reading queue

A capture item that is exactly one bare link (alone, one per line in a pasted URL list, or mixed with ordinary tasks in a blank-line-separated batch) queues that link for the reading queue instead of becoming an inbox task. Bob classifies the URL, checks the library without touching the network, and reports one of `not_found`, `in_library`, `in_intake`, `clipping`, `duplicate`, `legacy`, or `unknown`; a real run stages a durable ref job that a background worker clips, while a dry run previews the same card without staging anything.

The reference preview card shows the display URL (or the library path when the link is already known), Bob's own detail line (`new to your library · clips in the background` for a new link, `Captured Post · queued` for a library hit, `waiting for bob ref scan` for an intake hit), an `Article`/`PDF`/`arXiv` chip (or the reading-state chip in the library), and — on queued items — the inbox fallback hint naming where the task goes if clipping fails. The footer action is **Queue** for a queued single link and **Done** for an already-known one; batches keep **Capture**. The editor underlines the whole link in the link color via the `ref_url` span. Notifications read `Queued for reading: <link>` (or `Already in your library: <title>`), and Control-Return opens the note or intake PDF only for `in_library` and `in_intake`, using Bob's landing data; a queued link opens nothing, because Bob reports no target for it. Command-Return is the editor alias. An older Bob without the `ref` object keeps capturing the link as an ordinary task with the standard card; upgrade Bob before queueing links. Queueing can be turned off per draft with `bob capture -R/--no-ref`.

Queueing can be turned off per draft with `bob capture -R/--no-ref`. The queued job itself is filed by `bob` in the background; the app never touches the network.

## Successor offers

When a current Bob preview reports successor offers for `!` completion or `x` close, Return opens a grouped choice card before the capture is written. Nothing is marked initially, including a single offer. Return is Pull In: it chooses marked offers or, when none are marked, the highlighted offer. Up/Down or Control-N/Control-P moves the highlight, including from the filter. Space marks or unmarks the highlighted offer whenever the filter is empty or unfocused, including immediately after the card opens. The filter takes spaces only once it holds text. Command-A marks every offer, Shift-Return is Skip: it commits with no offers, and Escape returns to the unchanged draft without writing. Control-Return confirms with Return's selection rule, captures, and opens Bob's reported notes. The card shows Bob's global offer numbers, destinations, project folds, blocked residents, and a projected plan-link count when Bob supplied the budget. It is a full-width card like the task picker, with a context line naming what unblocked the offers, destination capsules that turn green on the offers Return will pull in, a live Links projection when Bob supplied the budget, and footer hints with Skip and Pull In N buttons that also work by pointer, plus a lowest-priority `⌃↩ Pull In & Open` hint. When the card already carries an open intent (Control-Return from a picker, or Control-Return on the card itself), that hint is omitted and both buttons show a trailing `arrow.up.forward` glyph. The success notification reports what was pulled in.

## Inbox routing

When a matching Bob preview reports that a capture will change the status of an existing inbox task, the preview adds an `Inbox · … · ↩ choose where it goes` row. Return opens the route card before writing, after the successor choice when both choices are needed. The card shows each changed task and Bob's available areas and open projects, with the destination path, parent, project status, and Blocked mark. Filter the list locally, then use Return to move the task or Shift-Return to keep it in its inbox. Control-Return moves it and opens the capture notes. With multiple tasks, answer them one at a time; the previous destination is highlighted when it remains available.

Escape goes back one task. From the first task it returns to the earlier successor card, when present, or to the unchanged draft. If Bob refuses a move, the card reopens on that task with Bob's reason. If the task changed since the preview, the card closes and Return asks Bob for a fresh choice. The success notice says which destination was used or that the task stayed in its inbox.

## Relationship rows

Preview shows one `⛓ depends on · Buy shoes · foo.md ^bar · Ready → In Progress` or `🧱 blocks · Do cleanup tasks · job.md ^cleanup · Next → Blocked` row per relationship, in Bob's `dependency_updates[]` order. Already-present rows say `already depends on` or `already blocks`; project-resident counts remain on the block row. Managed Depends-On/Blocks Markdown is omitted from task cards while these rows are present. A `task_dependency` item uses an owner header with its text, note and block ID, and resulting status; the owner task card appears before related task cards, and its repeated task line is omitted when the card covers it. Success notifications name the owner and relationship, use the route label as their subtitle, and include consumed-link detail when Bob reports one. Consumed links use Bob's session name, time, state, action, and removal flag; deleted sessions render red, and removed Pomodoro lines keep the red diff style. A dependency-only action is never labeled "Create task". The `&` and `*` editor spans are supplied by Bob; Swift never scans either sigil to parse capture grammar. Older Bob payloads without resolved relationship details keep their legacy preview and notification copy.

## Relation rows (`~` / `~~`)

Preview shows one `🪢 links to "Design a retry policy" · see   sase.md ^retry-design` or `🪢 "Ship the sase blog" now links here · next step   sase_blog.md ^prj` row per edge, in Bob's `relation_updates[]` order. Relabeled rows say `🪢 relabeled "Retry design" · next`; already-linked rows say `🪢 already linked "Retry design"`. An archived target appends the muted `· archived: LINKED FROM shows live only` suffix because the courtesy mirror is skipped. Managed `**LINKS:**` / `**LINKED FROM:**` Markdown is omitted from task cards while relation rows are present. Relation rows never render red, consumption, or status arrows. A `||` dry run that would hide a visible label renders Bob's `hides_existing_relation_label` message as an amber row; the commit appends `· hid "label" from relation suggestions` to the notification. Success notifications count relations separately: a single `~` reads `🪢 owner now links to "target"`, a single `~~` reads `🪢 "source" now links here`, and larger or mixed batches read `owner · depends on D · links R`. New relation IDs render as `🪢 New relation ID · path ^id (source|target)` captions. The `~` editor spans are supplied by Bob; Swift never scans the sigil to parse capture grammar. When the draft contains `~` but the parse response lacks `relation_grammar`, the panel shows the calm `This bob predates ~ links; ~ text would be captured literally · update bob` warning: the first ⌘↩ only shows the warning, the second ⌘↩ submits.

## Similar tasks

When a capture draft will create a new task, the preview card may grow a **Similar tasks** band at its foot — after the destination line, relationship rows, blocks, and every other capture consequence, never displacing them. The rows come from `bob capture-related` after typing settles; the app only schedules the call and paints what Bob returned. A project-note title uses the same band on its card.

The band takes zero pixels unless a match clears Bob's bar: no header, no placeholder, and never a "No duplicates" line. Percentages, scores, spinners, and empty states are never shown. Held rows stay put while you type and swap only when the settled result changed, with a 120 ms cross-fade (instant with Reduce Motion) and no height animation.

A single-item card shows a hairline, a `SIMILAR TASKS` header with an optional `+N` capsule and a trailing `⌘1–2` hint, then at most two rows. Each row is one line: a `⌘N` keycap, the status glyph, the title with matched words semibold and tail-truncated, an optional project `folder` or reading `book` glyph, at most one capsule, then `route · Status`. The locator truncates first, then the title; capsules never wrap or shrink. Capsules are **Same title** and **Possible duplicate** (warning tint), **Done 8d ago** / **Canceled 8d ago** (secondary on quaternary), or **Related** / **Prerequisite** / **Blocked by this** after you act. Closed titles are secondary and never struck through.

A bulk draft puts at most one row on each task-creating card, with a leading `⧉` mark and no header; numbering continues down the stack. If the band would make the auxiliary region scroll, every band folds to one line before anything else moves, for example `⧉ 2 similar tasks · Possible duplicate: Install new UPS battery   ⌘1`.

Each row is one VoiceOver element, labelled `<title>, <capsule>, <route>, <status or closed text>`. One announcement fires per settled non-empty change that differs from the last; typing never announces, and focus never moves to the band. Hover shows the full title and note path without changing layout. Setting **Show similar tasks while capturing** (on by default) hides the band and stops the related lane.

Pressing `⌘1`–`⌘5` focuses that row and opens its action strip on a second line; pressing the same key again unfocuses it. In a folded band, `⌘1` shows that row and its strip until unfocused. The strip lists only the actions Bob offered, always in the order `~ + & * / ⌫`, with the default preselected. The footer swaps to key hints while a row is focused, naming the default so the meaning of Return stays visible.

| Action | Keys | Draft edit |
| --- | --- | --- |
| Relate | `~` | Appends Bob's `relation_to` at the item anchor |
| Add as note | `+` | Replaces the item's route with Bob's `parent`, or appends it when there is no route |
| Needs it | `&` | Appends Bob's `dependency` at the item anchor |
| Blocks it | `*` | Appends Bob's `blocked_task` at the item anchor |
| Open | `/` | Opens the task in Obsidian, keeping the draft |
| Discard mine | `⌫` | Deletes the item's range |

Defaults come from Bob: `similar` rows default to Relate, closed rows default to Open, `possible_duplicate` rows default to Add as note, and `same_title` rows default to Discard mine (or Add as note when the item has authored children). Every splice is undoable through the native text view, then runs the live preview again; `⌘Z` restores a discarded item. Focusing a held row after more typing fires the related lane at once and applies the chosen action against the fresh anchors. When the task is gone, the band announces "Similar tasks changed" and unfocuses. Open keeps the draft and hides the panel. Return is never intercepted: with no row focused it captures as today.

Each focused row exposes one VoiceOver custom action per offered strip action; the strip itself is labelled with the row, the default, and the available actions.

Rows for tasks that still need a block ID offer the same strip, but choosing a link action opens the Add block ID prompt prefilled with Bob's first suggestion (Tab cycles them). Submitting writes the ID now, before Return, and splices the matching `~` / `@+` / `&` / `*` replacement; Escape cancels with no write and keeps the band focus. Open and Discard mine need no ID.

`↓` on the last visible row of an item reveals that item's next hidden match, up to Bob's limit. Unfocusing the band collapses the reveal back to the capped rows.
