Review of PR #35 — “Needs you becomes an inbox”
by Nick Palenchar · one commit (a220d872) · 15 files, +427 / −27 · reviewed together with Codex
Request changes. The idea and the sheet work well; the one-click buttons, though, decide differently from the card in four places, and two of them can destroy or land work by accident.
What the PR does
Clicking “need you” in the bar no longer jumps to the next card. It slides out an inbox sheet on the right listing everything waiting for you on every canvas, newest first. Each entry has one-click buttons (Approve, Accept and start / Dismiss, Keep / Remove, or a question's options) plus “Go to card”. Tab still jumps through this canvas's cards. As a side cleanup, the three right-hand sheets now share one container component.
Must fix before merge
- blocker“Approve” on a prototype throws it away. The inbox doesn't know about prototypes and offers a plain Approve; the server treats approving a prototype as “seen enough” and deletes its workspace and branch. The card itself offers “Build on it” / “Discard” instead.
- blockerA handover with a question the inbox can't render lands the work without an answer. If the agent's handover asks a multiple-choice question, one with more than four options or a free-text one, the entry shows the question text and, below it, “Approve”. One click merges the work, and the question goes unanswered.
- blocker“Remove” on a withdrawn card deletes it with no undo. On the card, “Remove” is the red button and comes with an undo; in the inbox, “Keep” is the highlighted default and “Remove” deletes the card and stops its worker at once. That breaks the rule that a button that is easy to click by accident and does a lot gets an undo.
- blockerThe buttons duplicate the card's decision logic, and it has already drifted. Every proposal without questions reads “Accept and start”, but on the card an idea proposal reads “Discuss”, and one scheduled for later reads “Accept” and waits. Approve always reads “Approve”, never “Approve (PR)”, and there is no “Direct to main”. The project's rule: an interaction shared by several places is built once in shared code. The fix is to have the card and the inbox take their buttons from the same code.
Should fix
- fixApproving from the inbox doesn't fold the card on the canvas. On the card, an approval at once shows “being approved …” and drops out of Tab; from the inbox the canvas card keeps looking as if it were waiting until the server catches up. Sharing the card's action path would fix this too.
- fix“Go to Obeya” for another canvas only switches canvas. Obeya's sheet stays closed there, so the unread answer the entry pointed to isn't shown.
- fixA new question can stay hidden. An answered entry is remembered by canvas/card/kind until the server drops it. If the connection blips and the same card asks a new question meanwhile, the new one carries the same key and stays hidden until a reload.
- fixThe phone diverges. The phone's “For you” list is already a cross-canvas inbox, but it gets none of the one-click buttons. The project's rule is that the phone follows the desktop with the same controls (see question 1).
Nits
- nitTwo strings are unused (
inbox.close, inbox.answered). The new inbox block is inserted between the phone view's comment and its strings, so that comment now labels the wrong block.
- nitDesign doc: one very long unwrapped line. The paragraph repeats what “Sheets” already says, and its “exactly one button is primary” is not true for entries that only have “Go to card”.
- nitThe decision is logged as “(owner, 2026-11-01)” (see question 2).
Checked and fine
- okNo data leak: the inbox now goes to every connected page with every canvas's titles and questions, but only you and your paired devices can connect, and they can see every canvas anyway.
- okNothing hidden: only the 15 files the feature needs. No dependency, script or settings changes.
- okMerges cleanly onto today's main (main has moved two commits since, all voice/narration).
- okThe server re-sends the inbox only when it changed, and every waiting card has a stored waiting time, so it doesn't spam pages.
- okThe shared sheet container is a good cleanup.
- okCodex ran the type check and the new tests, and they pass. I didn't run the full suite on the contributor's code myself, because this session's sandbox doesn't let me execute outside code. The PR's demo video already shows the feature, so there's no second video.
Questions for you
1. Should the phone's “For you” get the same one-click buttons?Otherwise desktop and phone handle the same list in two different ways.
2. Was “inbox instead of jump, newest first” your decision?The design doc logs it as yours (“owner, 2026-11-01”). If it was Nick's call, the line should say so, or you confirm it.
3. Should you be able to approve from the inbox without having watched the demo?Today, approving happens on the card beside the demo. In the inbox, one click merges work you haven't seen. One option is to keep only “Go to card” for handovers and keep one-click buttons for questions and proposals.
Draft comment for the PR (not posted)
Thanks, Nick — the inbox reads well, and pulling the sheets into one container is a nice cleanup. A few things need to change before it can merge:
1. A prototype's handover gets "Approve", which on the server discards the prototype (workspace and branch deleted). The card offers Build on it / Discard instead.
2. A handover whose question can't be shown as quick options (multiple choice, more than 4 options, free text) shows "Approve" under the question, so one click lands the work unanswered. Such entries should only lead to the card.
3. "Remove" on a withdrawn card deletes it and stops its worker without an undo, and "Keep" is the default. On the card, Remove is the danger button with an undo.
4. The quick replies re-implement the card's buttons, and they have already drifted: idea proposals and scheduled proposals aren't "Accept and start", Approve misses "(PR)" and "Direct to main", and folder repos are handled differently. The repo's rule (CLAUDE.md) is that a shared interaction is built once: please have detail.tsx and the inbox take their actions from the same code. That also makes an inbox approval fold the card on the canvas the way the card's own button does.
5. "Go to Obeya" for another canvas only switches canvas; Obeya's sheet should open there.
6. The optimistic `acted` key (canvas/card/kind) can hide a new question on the same card after a reconnect; include something that changes with the question (e.g. waitingSince).
7. Nits: `inbox.close` and `inbox.answered` are unused; the `inbox` strings block was inserted under the phone view's comment; please wrap the long line in the-canvas.md.