feat(service,features,desktop): tell Inbox items apart by whose agent asks them
Merged
DA
4d ago+542+542+012345678901234567890123456789-68-68-01234567890123456789
Implements the plan "Is there a way to distinguish between Inbox items per person?" (https://tryluke.dev/stage/plan/d4c1b75b-9298-4197-82c9-1a607d2cf91b), where the developer chose options A + B + C.
Summary
Before this change, notifications, the Dock badge, and the sidebar's Inbox count included only items from agents you started. The Inbox list, Home, and a task's Inbox tab drew every member's items the same way, blue dot included. You could only see whose agent was asking by hovering over its tile.
- The item says whose it is. Each inbox item now carries
startedBy(a member reference), read from theuser_idthe row was already written under. No migration is needed. An item from an older service with nostartedBycounts as the reader's own, the same ruleagent-notices.tsalready uses. - A. Faces on teammates' rows. A teammate's item shows their face beside its time, the way the sidebar marks a teammate's task. Your own rows show no face.
- B. Needs you means yours. The blue dot, the Needs you filter and its dot, group counts, the item chosen first, Next / J, a task's own Inbox tab, and Home's Inbox section now count only your own agents' open items, which matches the Dock badge. A teammate's open item gets a hollow ring, labelled "Waiting on " for screen readers. Any member can still answer it.
- C. Group by person is a new View options choice. Your items come first as You, then each teammate's, the one with the most recently changed item first. Rows there name their task instead of showing a face. Each person's group folds like a task group, and the choice is kept across launches like the other groupings.
Left unchanged on purpose:
- Factory still counts every open question, because it shows what is holding a task up, whoever is asked.
- A person's page still lists everything waiting on that person.
Evidence
pnpm check:affected: typecheck, lint, knip, and discarded-effect pass. Every test package passes except one desktop file,src/main/app-menu.test.ts, which fails in my sandbox because the Electron binary isn't installed ("Electron failed to install correctly"). That file is unrelated to this change, and CI installs Electron.pnpm exec vitest run packages/service/src/agents/coder-host/inbox-store.test.ts: 7 passed, on PGlite. A teammate and the starter both readstartedByas the agent's starter.pnpm exec vitest run apps/desktop/src/renderer/tasks/inbox-model.test.ts: 18 passed (+4).- Screenshots: I rendered the real
InboxListin jsdom with the desktop stylesheet and captured it with Playwright. Images follow below.
| Group by task | Needs you on | Group by person |
|---|---|---|
![]() | ![]() | ![]() |
Invariants
-
./scripts/check.shgreen. (CI) - JSON Schema goldens changed under
LUKE_UPDATE_FIXTURES=1. Each of the five inbox answer schemas (inbox-wire-inboxItemSchema,-inboxAnswerSchema,-inboxAnsweredSchema,coding-agent-view-codingAgentInboxAnswerViewSchema,-codingAgentInboxAnsweredViewSchema) gains one optionalstartedByproperty, a member reference (userIdandnamestrings), and nothing else. - Every behavior change has a test that fails without it: four new model tests (only your open items need you; first choice and Next skip a teammate's item; Group by person order and holders; folding a person's group) and the store assertion on
startedBy. No change-detector tests. - Gateway envelope goldens unchanged.
- No new
astype assertion. - No
Effect.run*outside the edges. - No new raw async primitives.
- No discarded Effect.
- Test count: +4 desktop model tests. The store test file's count is unchanged (one test gains assertions and a new name).
- Replaces no hand-rolled file.
- No
CLAUDE.md/AGENTS.mdsentence names these parts. -
PRIVACY.mdunchanged. A member could already see who started any agent on its card, so the starter's name reaches nobody new. - No dependency changes.
- Barrel/door rule unaffected.
Notes
- Blockers or follow-up verification: I haven't seen this on the Mac. A quick look at the window Inbox in a team workspace with a teammate's open item would confirm the face, the hollow dot, and Group by person.
Made with Luke
Summary by cubic
Lets you tell Inbox items apart by whose agent asks them, so needs-you signals match the Dock badge and sidebar count.
- Each item now carries
startedBy, the member who started the agent, read from theuser_idthe row was already written under; no migration needed. Items without it count as the reader's own. - A teammate's rows show their face beside the time, and their open items get a hollow ring labeled "Waiting on " for screen readers; any member can still answer them.
- The blue dot, Needs-you filter, group counts, first choice, Next/J, a task's Inbox tab, and Home's Inbox now count only your own open items.
- Group by person is a new View-options choice, kept across launches: yours first as You, then each teammate's, most recently changed first.
- Factory still counts every open question, and a person's page still lists everything waiting on them.


