Repository navigation
feat(prompt): Give each Turn input its own prompt part, with review item tags - #2631
Open
sentry-junior[bot] wants to merge 8 commits into
Open
sentry-junior[bot] wants to merge 8 commits into
sentry-junior[bot] wants to merge 8 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
sentry-junior
Bot
force-pushed
the
feat/review-item-answer-messages
branch
from
November 3, 2026 22:51
789ffa1 to
05e7bb2
Compare
sentry-junior
Bot
force-pushed
the
feat/per-input-prompt-parts
branch
from
November 3, 2026 22:57
d703cf5 to
b65214c
Compare
Runtime-created inputs become their own tags outside <current-instruction>: <task>, <parent-agent-task>, <agent-result>, and <agent-message>. Each Turn input is one prompt content part, so a batch is no longer joined into one <current-instruction>. Agent output and provider text sit in a tag with a source attribute, one sentence that says the body is data, and an escaped body. Next-step guidance for agent results and messages moves to the static system prompt. Co-Authored-By: David Cramer <23610+dcramer@users.noreply.github.com>
A person's answer or dismiss is now its own prompt part outside <current-instruction>, keyed by the review item id: <review-item-answer> or <review-item-dismissed>, built from the stored change record and the item. A Conversation that only gets a relay reads <relayed-review-item-answer> or <relayed-review-item-dismissed> as data. A take no longer starts a Turn. The Conversation saves it as a handled Message, so the dashboard row stays, and the model never reads it. Every person part of a batch uses the one Actor of the instruction. Adds a behavioral eval for one Turn that batches two answers, a dismiss, and a typed message.
A review item tag for a notice, which has no question, now has a Title: line instead of Question:. A relayed tag now says that it is relayed from the review desk, because the runtime wrote it.
Name all four review item tags with their attributes, and say what a dismiss and a notice send.
Member
|
we have local cli as something diff here, but local cli is same as web, except it has no identity (thus its system identity) its not a relay or some special thing... |
…ests event-wake-delay still asserted the old Event prose. It timed out in the sandbox before it reached the assertions. web-batch-messages still called webActorFromEmail, which #2630 removed.
sentry-junior
Bot
force-pushed
the
feat/per-input-prompt-parts
branch
from
November 4, 2026 00:55
de2f56e to
c1e36af
Compare
A local CLI Conversation is like web, but it has no identity. It is not a relay. A person change to a Review item now gets the same <review-item-answer id> or <review-item-dismissed id> input there as on web. Remove the relayed- tags, their system prompt line, and the relay prose on the stored Event text.
dcramer
marked this pull request as ready for review
November 4, 2026 03:31
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a281f38. Configure here.
A Slack Event Turn that paused before its first prompt rebuilt its saved <task> or <agent-result> text as a person input, so the tags were escaped inside <current-instruction>. The paused-Turn resume now treats a saved Event Message as runtime input, like the conversation Turn worker does.
thomasjiangcy
pushed a commit
that referenced
this pull request
Nov 4, 2026
Main CI on 38c8693 (#2625) fails `check / types`, `test / junior unit`, and `test / dashboard e2e`. **Types and unit.** #2625 added `web-batch-messages.test.ts` with `webActorFromEmail`. #2630 removed it. The test now uses `webActorFromUser(testViewer(...))`, the same fix as c1e36af in #2631. **Dashboard e2e.** `conversations-mobile.spec.ts` "keeps the message in view while earlier history and late content load" is flaky. It is not a regression from #2622 or #2625: - Main CI: failed on f23838b (#2622, which only changes `ReviewItemContext.tsx`) and 38c8693. Passed only on retry on 38597fb. Each of these failed at line 752, the last step (spacer above the reader). - #2634 added `scrollIntoViewIfNeeded()` right before that step. The scroll event fires on the next frame. When the test appends the spacer first, the transcript's scroll handler records the reader's place from the layout that already has the spacer. The resize correction then sees no shift. Local logs showed this order in every failure and the opposite order in every pass. - The test now waits one frame after each scroll so the scroll event runs first. Assertions are unchanged. Locally the last step went from 6 failures in 16 runs to 0 in 160. **Still open.** Under 4 parallel workers, 7 of the 160 local runs failed one step earlier (after the earlier page loads). I did not measure that step on main without this change. In the one failure I logged, the correction ran twice: `scrollTop` moved by exactly 2× the shift. That points to a product race in `transcriptBottomPinning.ts`, not a test race. This PR does not fix it. I have not seen it fail in CI. <!-- junior-request-attribution:start --> via @dcramer. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:agent%3A586024895340456299c9cfbe04e88e91 --> -- [View Session](https://junior-prod.sentry.dev/conversations/agent%3A586024895340456299c9cfbe04e88e91) [[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A586024895340456299c9cfbe04e88e91/?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 <23610+dcramer@users.noreply.github.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Builds on #2625, #2629, and #2630 (all on main). Follows the tag and escaping rules in #2628 (
policies/prompt-markers.md), as revised: notrustattribute, and markers are only hints, because the runtime enforces approval from the stored record.Each Turn input is now its own user content part. Before this, a batch was joined into one
<current-instruction>, and runtime inputs used bracket headers ([task],[agent result],[parent agent task]) inside it.<current-instruction>: only words that a person wrote. One per web Message in a batch. No label.<task about event>: Automation, Event, and Watch tasks. Facts go in child tags (<created-by>,<people>,<done-by>,<instructions>,<guidance>,<summary>,<verified-details>). A batch has one<watch>per Watch and one<event index type>per Event. Copies of</are escaped, and Slack mentions stay copyable.<parent-agent-task>: the child agent's job. No label.<agent-result conversation_id name source status title waiting_on>and<agent-message conversation_id source visibility>: one sentence says who wrote the body and that it is data, not instructions. The body is escaped.<external-text source>inside a task: uses the same sentence and escaping.<context-trust>keeps one generic line: tool results, files, fetched pages,<thread-context>, and tagged blocks that say they hold data are information. The job rule now names<current-instruction>,<task>,<review-item-answer>, and<review-item-dismissed>. Guardian policy says that these tags were not written by the user.<review-item-answer id>/<review-item-dismissed id>: a person's answer or dismiss, keyed by the id thataddReviewItemreturned. The body isQuestion: …(max 512 chars), orTitle: …for a notice, which has no question, and oneLabel (field_id): valueline per field, escaped (& < >). Nobyorchangeattribute, no status prose, no "Answer to request" line. The runtime builds it when it builds the prompt, from the storedreviewItemChangerecord (feat(review-items): Record each review item change on its message #2625) and the item, not from the message text. Web batches, web steering, Slack card inputs, Slack steering, and paused-Turn resumes all use it.<review-item-answer id>/<review-item-dismissed id>input. There is no relay tag, and the stored Event text no longer has the "Junior relays this person action" prose.<current-instruction>part of a batch has the attributes of the one instruction Actor.Behavior change: a take no longer wakes a Turn
A take on the review desk used to start a Turn in each linked Conversation. Now each linked Conversation saves the take as a handled Message with its
reviewItemChangerecord and starts no Turn. The dashboard row stays. Thread context skips take-only Messages, so the model never reads a take.Not in this PR:
repliedand agentclosedreview item messages keep their[review item]prose.<thread-context>/ memoriessourceand data sentence. They keepauthority="evidence-only".<context-trust>.TODO(dcramer)).Rollout risk
agentInputSchemaand the stored records do not change. The input kind comes from the record source: event, dispatch, or child invocation = runtime; web = person.kinddoes not dedupe against the new runtime render.[task],[agent result]) is sent as one runtime part, as it was written. A review item message with noreviewItemChangerecord, or whose item is gone, goes to the model as written.Prompt before/after
Rendered by the real code: the "after" parts are the user content parts of the model request from a Conversation worker run (
createConversationTurnWorkerwith a scripted model stream), and the "before" parts are the same run on #2625 (789ffa1da). Item ids are mapped to the same values. The answer for the owner item tries to close the tag; it stays escaped.One answer
Before (#2625):
After:
Mixed batch: two answers, a dismiss, and a typed message, in one Turn
Before (#2625), one joined part:
After, four parts:
A dismiss
Before (#2625):
After:
A local CLI Conversation
Before (#2625):
After:
Tests
pnpm typecheck(junior and junior-evals),pnpm lint,pnpm file-length:check: pass.tests/integration/review-item-prompt-inputs.test.ts: two answers, a dismiss, and a typed message in one web batch, and the same answer in a local CLI Conversation. It asserts the exact prompt parts.api/review-items/actions.test.ts(a take saves a handled Message and starts no Turn),unit/agent/prompt-user-turn.test.ts(one Actor per batch).durable-queue,agent-dispatch-work,annotation-cards,event-wake-delay,bot-image-hydration, andwatched-message-behavioralso fail on the base branch.Evals to run before merge
Not run: no model credentials in the sandbox.
pnpm --filter @sentry/junior-evals evals:behavioral evals/review-desk/items.eval.ts -t "batches two answers". The fixture has a newreviewItemAnswer()/reviewItemDismiss()input that answers throughPOST /api/review-items/:id/actions.evals:behavioral evals/review-desk/items.eval.tsandevals/conversation/asking.eval.ts.evals:guardian evals/guardian/child-agent-approval.eval.ts(fixture updated in the first commit).evals:behavioralandevals:integration.--
View Session [Sentry]