Skip to content

Plannotator Inbox: the first run says less (words of record, one rhythm, equal cards) - #1761

Merged
backnotprop merged 4 commits into
mainfrom
feat/inbox-first-run-words
Oct 7, 2026
Merged

backnotprop merged 4 commits into
mainfrom
feat/inbox-first-run-words

Conversation

@backnotprop

@backnotprop backnotprop commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

Story

The owner saw the built first run and called it jumbled, with too much narrative labelling. The record now carries his ruling ("Addendum: the empty state, as the owner saw it built", .product/approved/plannotator-inbox-window-2026-10-07/approval.md): the words of record, verbatim, no comma in any header, one vertical rhythm, equal cards, and the revealed command opening below the row. This PR makes the window say exactly that, with no new behaviour.

What changed

  • packages/inbox/components/EmptyState.tsx: heading No agent has written yet. Three cards, each the host mark and name (Claude Code, Pi, OpenCode) and one line (Plannotator's mod / extension / plugin writes here. Nothing to install.), then a small text link Use MCP instead. The link reveals that host's command with Copy in one box BELOW the card row (one open at a time, the same link closes it; the open card's border takes a primary tint). The check-mark headline is gone. Then Other agents and Add the Inbox as a local MCP server., then the tabs.
  • packages/inbox/components/ConnectPicker.tsx: the selected tab shows the artefact (command with Copy, deeplink button, or file snippet under its path), ONE short note, and the folded Another way. The eyebrow repeating the harness name and the lead line are gone. CodeBox loses its narrow wrap form, which only the old in-card reveal used.
  • packages/inbox/harnesses.ts: HarnessPanel is now { artefacts, note?, another? }. Every harness keeps its command and fallback exactly; each note is cut to one sentence. Codex's note is the record's words: Also adds it to the Codex app and the IDE extension. Restart them after. The Another way summaries lose their commas, because they are part of a button's label.
  • packages/inbox/inbox.css: .ib-empty is a flex column with one gap (--ib-rhythm: 28px) between the heading, the cards, Other agents and the tabs. The cards stretch to one height, with the line taking the slack so the links line up. The reveal sits 12px under the row. The warning-tinted note box, the eyebrow, the lead and the wrap rules are removed.
  • Settings' compact picker uses the same ConnectPicker, so it shows the same panel: artefact, one note, Another way. Nothing else in Settings changed.
  • AGENTS.md (Inbox section): the first-run sentence now describes what is built.

The record section it makes real

"Addendum: the empty state, as the owner saw it built (2026-10-07)", every bullet:

  • Heading No agent has written yet: done.
  • The three card lines verbatim, the Use MCP instead link revealing the host's command with Copy, no check-mark headline: done.
  • Other agents with Add the Inbox as a local MCP server., the tabs, the command box with Copy and one short note (Codex's verbatim), Another way kept, no eyebrow: done.
  • One vertical rhythm, equal card heights, the revealed box opening below the row without making its card taller: done, and asserted.
  • Headers carry no comma: asserted on every tab.

Proofs

Built and compiled as LANE-RULES "Build" says (bun run --cwd apps/review build && bun run build:hook, then bun build apps/hook/server/index.ts --compile --no-compile-autoload-bunfig --define '__CLI_VERSION__="0.0.0-dev"' --outfile .local/plannotator). Then PLANNOTATOR_BROWSER=none bun run test:e2e:inbox: all four specs (inbox, notifications, decisions, attachments), 43 passed.

The first-run flow in tests/e2e/inbox.spec.ts now asserts, against the compiled binary in headless Chromium:

  • The heading and each card's name and line, matched exactly.
  • Other agents and its line.
  • Codex selected: the command, the single note verbatim, Another way, no eyebrow. Copy puts the command on the clipboard.
  • One rhythm: the three gaps between the empty state's blocks are equal.
  • Equal cards: the three cards have one height before any reveal and the same heights after it.
  • Below the row: the revealed box's top is at or below the bottom of the card row. Its text is the host's exact command, for Claude Code and then Pi. One reveal is open at a time, and the same link closes it.
  • Unclipped: with the e2e binary's long temp path, every visible code box (the card reveal, the Codex box, and Settings' compact picker) has scrollWidth <= clientWidth. The box wraps (pre-wrap, overflow-wrap: anywhere) and Copy stays top-aligned beside the text.
  • No comma: on every tab, no heading, tab, button, link or file label in the first run contains a comma, and each panel has at most one note.
  • The Cursor deeplink and the Claude app JSON, as before.

notifications.spec.ts matches the new heading exactly.

Captures at 1440 by 900 (.local/proof/ in the worktree):

  • Codex selected: 1.3-first-run-codex-light.png and -dark.png
  • Claude Code's Use MCP instead revealed below the row: 1.3-first-run-claude-code-light.png and -dark.png
  • Also refreshed: 1.4-first-run-cursor, 1.5-first-run-claude-app and 7.1-settings, which shows the compact picker.

Gates

  • bun run typecheck: green.
  • bun run check:release-version: green (v0.28.7).
  • bun test packages apps/hook tests scripts under a temp PLANNOTATOR_DATA_DIR and HOME: 5787 pass, 1 fail. The failure is environmental. annotate-cli.test.ts "exits 1 with one line..." fails only because this session exports FORCE_COLOR=3, which puts ANSI codes in front of Resolved:, so the test's startsWith("Resolved:") filter misses that line. With FORCE_COLOR unset the file is 13 of 13 green. This PR does not touch that file.
  • DOM allowlist (scripts/dom-test-allowlist.test.ts): green. No DOM-gated test file was added.
  • packages/inbox unit tests (harnesses.test.ts: every panel has an artefact and every JSON snippet parses): green.
  • packages/ui and packages/core are unchanged, so no smoke:package run. The guide chain is untouched.

Left out, and deviations

  • No new behaviour. No new tabs, harnesses, commands or routes.
  • Review fixes (blocker and two items, same push):
    • The Claude app tab's one note is now Merge it into mcpServers in Claude > Settings > Developer > Edit Config, then quit and reopen Claude. claude.ai connectors cannot reach this computer. The e2e asserts it.
    • Goose's note is now Opens Goose to add the extension.; the research does not verify that Goose asks for a confirmation.
    • Code boxes wrap at spaces (word-break: normal; overflow-wrap: anywhere), so a long path still wraps in full.
  • Deviation, commas in summaries: the Another way summaries drop their commas (... > STDIO then Restart) because they sit inside a button label, and the ruling says no header or label carries a comma.
  • Not in the record, added: the open card's border tint. It shows which card the box below the row belongs to.
  • The rhythm value: 28px. The record names the rule (one gap everywhere), not a number.

…hm, equal cards)

The empty state as the owner ruled it built: 'No agent has written yet', one
line per Plannotator connection card with 'Use MCP instead' opening the
host's command below the row, 'Other agents' with one line, and one short
note per harness tab (no lead, no eyebrow). Headers carry no comma; the e2e
asserts the words, the rhythm, equal card heights and the reveal below the row.
… line and says merge; Goose note verified; code wraps at spaces)
@backnotprop
backnotprop merged commit 12f21b6 into main Oct 7, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant