needs_action is wired but nothing populates it — proposal: client-side attention projection over existing events (+ WF-08 completion)
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## What we found
The feed's `needs_action` category is wired end-to-end but nothing can ever populate it:
- `crates/buzz-db/src/feed.rs:167` defines `needs_action` as kinds `46010`/`40007` p-tagging the user.
- Nothing in the tree emits either kind. The WF-08 TODO at `crates/buzz-workflow/src/executor.rs:663` suspends workflow approvals without emitting `46010`.
- `46010` is absent from `required_scope_for_kind()` in `crates/buzz-relay/src/handlers/ingest.rs`, so a client cannot submit one even deliberately.
Net effect: `needs_action` returns an empty list on every surface (relay SQL, desktop Tauri mapping, mobile). The slot exists and waits; no producer exists. (File references are against `28ae6cd2`.)
## The user problem behind it
Operators running several agents get a feed that answers "what happened" but not "what is stuck on me". Asks for a decision, an approval, or a manual step drown in ambient activity, so agents block on a human who cannot see that they are the blocker. `VISION_ACTIVITY`'s own framing applies: waiting should be a rendered state, and a polished view should be a zoom level on the same truth, not a different feed.
## Proposal (for discussion before any feature PR)
A client-side **attention projection** over events the relay already stores, rather than a new pipeline:
- Projects only mention and actionable-ask items from the existing feed (layered on `buildInboxItems`); ambient activity excluded by construction.
- Deterministic, pure-function ask extraction (no model calls, unit- and regression-testable).
- Every resolution posts an ordinary threaded kind-9 reply p-tagging the asker, so the asking agent wakes through today's trigger path. Nothing is resolved silently.
- **Zero new event kinds, zero relay changes** — consistent with `VISION_PROJECTS` ("custom kinds only where genuinely novel").
- Ships behind a `preview-features.json` flag, off by default.
- Packaging lean: an Inbox mode/section rather than a fourth sibling surface, per the precedent in #3117.
Separately and complementarily: completing WF-08 so workflow approvals emit `46010` would give the reserved category its first real producer. We are happy to take that on as its own thread of work.
## Evidence this is buildable small
We built this in our fork ([VenusOne-Lee/buzz](https://github.com/VenusOne-Lee/buzz), branch `buzz-one`) and have been using it daily against a live community relay: projection library, deterministic extractor with regression tests reproducing real field misclassifications, five posting actions with a client-side undo before publish, all behind a preview flag. Current suite: 3832 unit tests plus Playwright coverage of the full card lifecycle.
If the direction is agreeable we would split it into small, independently mergeable PRs:
1. Pure projection library + full unit/regression suite (no UI, no routes).
2. The rendering consuming the library, unreachable without the flag.
3. Nav entry + the flag definition, off by default, with screenshots.
None of these touch the relay or add kinds. Is this a direction you'd merge, and do you have a preference on the Inbox-integrated packaging versus a separate gated screen?
## Acceptance criteria (adopted 2026-08-18)
Adopted from the field audit in [this comment](https://github.com/block/buzz/issues/4335#issuecomment-5317330390); mapping and design resolutions in [our reply](https://github.com/block/buzz/issues/4335#issuecomment-5331346646).
1. Signed per-thread work state (active / needs-human / complete) without editing the root — signed `46010`/`40007` events are the explicit state layer; the client-side projection is the reading layer over them plus ordinary replies.
2. State is updatable by the accountable agent or an authorized steward even on a root they did not author; anyone may set state on their own behalf (same trust model as issue assignment; enforced in projection validation).
3. State visible on collapsed channel roots and thread headers.
4. Cross-channel "Needs me" view with a count, deep-linking to the unresolved ask.
5. Each needs-human item carries the requested person, accountable owner, concrete ask, and timestamp; resolving clears it.
6. Atomic, auditable state transitions: conflicts resolve deterministically (latest valid signed state per thread by `created_at`, event-id tie-break); counts are computed from the projection, never stored.
7. Desktop/mobile parity, phased: desktop rendering first, mobile renders the same shared projection.
Revised PR sequence: (1) WF-08 completion + relay `required_scope_for_kind()` fix, (2) projection library, (3) rendering (collapsed roots, thread headers, Needs-me), (4) navigation. Existing unit and Playwright coverage will be adapted to assert each criterion explicitly.
Contributor guide
Research direction
Start with crates/buzz-db/src/feed.rs:167, crates/buzz-workflow/src/executor.rs:663, and required_scope_for_kind() in crates/buzz-relay/src/handlers/ingest.rs. Review the existing unit and Playwright coverage, then follow the revised PR sequence: WF-08 and relay scope support, the projection library, desktop rendering, and navigation. Done means the listed acceptance criteria are covered with desktop/mobile parity and the preview flow remains testable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend, desktop, mobile
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100