Skip to content

fix(review-desk): Use one rule for items that need a person - #2503

Merged
dcramer merged 2 commits into
mainfrom
fix/review-desk-needs-you
Nov 1, 2026
Merged

dcramer merged 2 commits into
mainfrom
fix/review-desk-needs-you

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Part of #2488

The review desk had three different "needs you" signals. The nav count used open items of any kind that were assigned to the viewer. The "Waiting on you" marker also used items for Everyone. The empty desk list said "Nothing needs you right now." But the list shows every open item the viewer can see.

Under "Two goals" in #2488, only an open question waits on a person. This PR adds one rule, reviewItemNeedsUser in access.ts: an open action item assigned to the User needs that User. A notice, an item for Everyone, and an item without assignees need no one. The nav count and the marker now both use this rule. The marker also requires that the item is linked to the Conversation.

  • The count field mine is now needsViewer. The dashboard nav, the mock reporting route, and the e2e mock use the new name.
  • The desk list does not change. Its empty state now says "No open items."
  • These exports had no users outside their own file, so they are no longer exported: isSameTenant, ReviewItemKind, ReviewItemSubject, ReviewItemFilters, SlackReviewItemFormTarget, and reviewItemPayload. countReviewItems had one caller, so countReviewItemsNeedingUser replaces it.

The review desk API integration test now checks that a notice assigned to the viewer and an action item for Everyone do not count and do not mark a Conversation. It also checks that a taken action item does.

via David Cramer.

--

View Session [Sentry]

@vercel

vercel Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
junior-docs Ready Ready Preview Nov 1, 2026 8:17pm UTC

Request Review

@dcramer
dcramer merged commit f309657 into main Nov 1, 2026
44 checks passed
@dcramer
dcramer deleted the fix/review-desk-needs-you branch November 1, 2026 20:35
dcramer added a commit that referenced this pull request Nov 2, 2026
…n item (#2504)

Part of #2488 (track 4: A5, L1).

Prompt texts told the agent to ask a person in plain text. They now ask
with `addReviewItem`, and only when the person can give what is missing.
A non-blocking scope choice does not go on the desk. Since #2503, each
open action item that is assigned to a person marks the Conversation
"Waiting on you". So the desk must hold only decisions that need the
person.

**The rule (one owner each, per `policies/agent-steering.md`):**

- **When to ask: the task execution rule** (`system-prompt-rules.ts`):
> Ask the user a question only when they can give what is missing:
access that they control, or a decision that is truly theirs and blocks
safe progress. Ask it with `addReviewItem`, never in plain text. When
only part of the work is blocked, deliver the rest in this Turn and ask
about the blocked part with `addReviewItem`. When nobody in the
Conversation can give what is missing, such as another person's calendar
that returns notFound, state the gap and add no item. A scope choice
that does not block the work is not a question: choose the conventional
option, deliver the work, and state the choice in your reply. Do not add
an item for a scope choice, an offer, or a follow-up idea.

The existing rule against ending with an offer stays as it is. Partial
delivery and the ask go together: a blocked part never stops the rest of
the work, and a blocked part that the person can unblock still goes on
the desk (Bugbot). A gap that nobody in the Conversation can fill, such
as one attendee's calendar that returns `notFound`, is stated in the
reply with no item. The Google Calendar integration eval covers that
case.
- **How to ask and when to wait: the `addReviewItem` description**
(`tools/review-items.ts`). It drops its own "ask only for a decision
that is truly the person's" sentence, because the system prompt owns
that now.
- **Automation run rule** (`system-prompt-rules.ts`): it now reads "Ask
a person with `addReviewItem` only for a decision that is truly theirs
and blocks the work." It drops "with a recommended default, then finish
the run". The tool description owns that (recommended option first, and
finish only when the next step needs the answer).

**Other prompt changes:**

- **Blocked child result** (`agent-invocations/result.ts`): when only a
person can give what the child needs, such as approval, the parent adds
one action item that names the exact action. Its `dedupe_key` comes from
the child conversation and the blocked action, so a repeat block updates
the same item. Two rules stay: the parent's own text is not approval,
and after the answer the parent tells the child to try again with
`messageAgent`.
- **Child Guardian denial** (`guardian/gate.ts`): only the wording about
how the parent asks changes. Guardian decisions and
`ACTION_CONFIRMATION_INSTRUCTIONS` (A2, deferred) do not change.
- **Drafting rule** (`system-prompt-rules.ts`): "ask one focused
question" now names `addReviewItem`.
- **Agent invocations guidance** (`agent-invocations/AGENTS.md`): a
delivery rule says that when Guardian blocks a child action, the parent
adds one action item with `addReviewItem` instead of a plain-text
question, deduped by child Conversation and action. (`main` replaced the
old `README.md` with this `AGENTS.md`; the README edit moved here.)

**Evals** (`asking.eval.ts`):

- A blocked child result makes the parent call `addReviewItem`, and the
reply text of the result Turn has no question.
- A non-blocking scope choice (a list-of-dicts to CSV function) adds no
`addReviewItem` item. The reply gives the function and states a choice
it made, and has no ask or offer.

The blocked-child integration eval and the child Guardian approval eval
accept the card-only `no_reply` result.

**Card answers and child approval.** A click on the Slack card in the
root thread reaches the root Conversation as Slack input from the person
who clicked. When that person is the child's Actor, the child's action
review reads it as `user`. A desk answer on the dashboard to a Slack
root arrives as a web Message. On `main` it reads as `other person`.
#2505 fixes that.

<!-- junior-request-attribution:start -->
via @dcramer.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:agent%3A45b85781e491a1a70c491c85bc40ba09 -->

--

[View
Session](https://junior-prod.sentry.dev/conversations/agent%3A45b85781e491a1a70c491c85bc40ba09)
[[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A45b85781e491a1a70c491c85bc40ba09/?project=4510944073809921)

<!-- junior-session-footer:end -->

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: David Cramer <[email protected]>
Co-authored-by: David Cramer <[email protected]>

This branch was successfully deployed

1 active deployment
Preview – junior-docs — 30577815 Deployed Nov 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: high PR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant