You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
board: ask the reviewer about a review finding - #940
Lets you ask the reviewer about one finding before you post it: is it real, is it overstated, what does the data say. The question goes to the reviewer's own Claude session, which already has the code and the review loaded. You talk it through in its pane, and if the finding changes, the reviewer re-raises its gate with the revision. You finish the review on the board as usual.
This replaces the PR's first design (a separate question agent in its own questions workspace). Reusing the reviewer's session saves a cold start, and needs no new workspace and no Flock change.
Every finding, ticked or not, gets an "ask a question" link in its card header. It opens a textarea under the header; "send to the review pane" (or cmd/ctrl+enter, which never posts the review from there) sends the question. One question at a time.
On an open gate the link is disabled while the review pane is gone. On a parked gate it stays live: asking resumes the reviewer's session with the question.
When the reviewer re-raises the gate, an open sheet moves onto the new gate by itself, with no page refresh. /data.json now carries gateReplacements (old gate to the newest gate in its chain), and the decision queue swaps the replaced gate for its successor in place, without counting it as answered.
A revised card says "Revised in the review pane", then what changed (severity, lines, wording, fix, comment), with "show original". The board works this out by comparing the new gate with the one it replaced in the same run (kept in memory), with nothing stored.
Your picks, notes and comment edits carry over to the re-raised gate: its form seeds from gate-kit's per-gate draft on the gate it replaced, then drops that draft. A revised finding takes the reviewer's new comment instead of your edit.
Board server (apps/board/src)
POST /review/finding-question types /board:review-finding-question <gate> <finding> "<question>" into the reviewer's pane through pane:send, then brings Flock forward on that pane.
It asks rt which pane runs the review's Claude session (paneSelf) and types nothing when none does, so a stale pane on file never gets the line.
On a parked gate with no pane running, it resumes the session with the line as its prompt, under the same tab label as the parked-gate resume, so an answer later focuses that tab instead of starting a second pane.
If the pane shows the gate's question form, it presses Escape first. Any other prompt is refused: "the review pane is waiting on a prompt; answer it there first".
It refuses when the gate isn't the MR's open or parked review gate, or the finding isn't in it.
No schema change and no new route for drafts.
rt daemon (lib/daemon/gates-store.ts)
Opening a gate now supersedes a parked gate of the same subject and kind, not only an open one, so a session resumed off a park can re-raise its gate.
Skill
New board:review-finding-question (apps/board/skills-src/review-finding-question/). Inside the review session it:
restates the finding and the question;
sends a read-only Explore agent (code, logs, New Relic, QA databases through sdm's read-only resources; prod only when you name it);
reports a verdict, the evidence, what it couldn't check, and a proposed change;
asks for the outcome with a mattstack:wrap-up form: revise and re-raise the gate, leave it as is, or keep asking.
On revise, it confirms the wording in another form, rewrites that finding in the report, and rebuilds the gate exactly as the first one was built. Only if the old gate is still pending does it stop the old wait and re-raise, then hold at the new gate.
Written test-first with superpowers:writing-skills. Agents without the skill dug through code and data inside the reviewer's session, reported in a different shape each time, offered prod unasked, and risked ending the run when the old gate closed. Agents with it did none of that.
Design files: B48 and B48b in docs/apps/design/board/board.pen (renamed from B23/B23b, which main now uses for another frame).
Verification
Rebuilt on main at 870166b20 as one commit, plus the review fixes in their own commit.
bun run board:test: 4125 pass. bun run board:typecheck: green. The gate store and handler tests: 155 pass. The board skills drift guard passes. bun run check is green apart from the console app's tests (getClientRects is not a function locally; this PR changes nothing in the console, and main's CI is green).
Ran it live on a real review, from the board into the pane and back.
Notes
The board keeps the last few replaced gates in memory only. After a board restart, the revised notice, the draft carry-over and the sheet's move to the new gate skip one re-raise (a manual refresh picks the new gate up).
The parked supersede takes effect once the dev daemon runs this code.
Add board flow for asking the reviewer about a review finding
Adds a question UI on finding cards in the review gate sheet. Questions go to a new local POST /review/finding-question route, which validates the gate and finding, then sends the question to the review agent's existing pane via herdr. If the pane shows a prompt that is not the Claude Code question form, it sends Escape and retries (finding-question.ts, ReviewGateSheet.tsx).
Adds the board:review-finding-question skill workflow for the review agent: investigate via a read-only helper, present evidence and a verdict, and wait for the human's choice before revising the report or re-raising the gate (SKILL.md).
Saves and restores review-sheet drafts (ticked findings, comments, outcome, notes) across gate rebuilds via GET/PUT /review/sheet-draft. Drafts are dropped on a final verdict, on re-review launch, and when the MR leaves the board. Saved comment text is skipped for findings revised in the current gate (review-sheet-draft.ts).
Detects revised findings by comparing the open review-post gate with its superseded predecessor, and shows a revised strip with the original title and body (review-revision.ts, ReviewDraftCard.tsx).
GateCache now retains replaced gate rows, exposes an old-to-new replacement mapping in board data, and the decision queue replaces a superseded gate with its successor without marking it answered (cache.ts, decision-queue.ts).
Behavioral Change: POST /review/finding-question returns 409 for missing panes or unlisted findings and 400 for blank, over-2,000-character, or malformed questions; older servers omit the new gateReplacements field.
This repository does not receive automatic reviews because it has fewer than 10 stars.
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: defaults
Review profile: CHILL
Plan: Advanced
Run ID: d32e3801-fdc9-457d-ad97-82c7f7bf85ae
Walkthrough
Changes
The board adds a per-finding question flow to the active review session. It also detects revised findings across superseding review gates and saves review-sheet edits for restoration across gate rebuilds.
The local endpoint validates the request and review gate before sending a question to the review pane. If the pane is at the question form, it sends Escape and retries once. The skill defines read-only investigation and human-approved revision steps. API documentation, tests, and design documents also change; earlier question-flow plans and specifications are marked superseded.
The cache retains predecessor gates and exposes replacement mappings. The server supplies revision data for changed findings and gate replacements. The decision queue follows mapped successors when reconciling its entries.
The server stores validated drafts by merge request. The client restores eligible draft fields and saves changes after a debounce. Drafts are removed on fresh review launches, qualifying review verdicts, and board departure.
The review sheet sends questions through the board action and displays per-finding question controls. Finding cards show revision summaries and can reveal the original finding text.
sequenceDiagram
participant ReviewGateSheet
participant Board
participant FindingQuestionEndpoint
participant handleFindingQuestion
participant ReviewPane
ReviewGateSheet->>Board: submit gate ID, finding ID, question, optional tab ID
Board->>FindingQuestionEndpoint: POST /review/finding-question
FindingQuestionEndpoint->>handleFindingQuestion: validate and handle request
handleFindingQuestion->>ReviewPane: send question to the review session
ReviewPane-->>handleFindingQuestion: delivery result
handleFindingQuestion-->>Board: HTTP result
Board-->>ReviewGateSheet: success or refusal
Loading
Possibly related PRs
m4ttstack/mattstack#947: Reworks the review-card components that this change extends with question controls, revision details, and draft restoration.
m4ttstack/mattstack#950: Reworks the same review-sheet components for card rendering and timelines, which must account for the added per-finding behavior.
Suggested reviewers:m4ttheweric
Security architecture risk: Moderate · up to 497e5
The question flow validates the selected review, but delivery does not always verify that it reaches that review’s session. If a saved destination has been reused, question content may reach an unrelated session. Exposure is limited by local-only access and existing delivery checks.
Retained concerns
Medium · security · inferred: Finding-question delivery can fall back to an unverified stored pane when the intended review session cannot be resolved. If that pane now hosts another running session, a request valid for the original review can disclose question content to the unrelated session. Successful live-session resolution prevents this, but missing-session fallback does not fail closed.
Security review details
Security Blast Radius
inferred — The supported exposure is the local board and its review sessions. An accepted local caller selects an MR’s open gate and listed finding. A reused destination can extend delivery to another local session; remote reachability, cross-tenant access and production privilege expansion were not established.
Security Findings and Attack Paths
inferred — If review A’s saved pane is reused by session B and A cannot be resolved, a question valid for A can reach B. The sink accepts an idle or working application session without checking its review identity. Conversely, a resolvable live session overrides the stale pane, and nonmatching application types are refused. No exploited misdelivery was demonstrated.
Trust Boundaries and Controls
observed — The route combines local-peer, host and forwarded-header checks with an exact application/json media-type requirement. It then requires the supplied gate to be the MR’s open review gate and the finding to belong to that gate. These controls constrain request reachability and selection, but do not authenticate the final receiving session.
Resilience and Maintainability Implications
observed — Draft restoration requires the saved gate or its identified predecessor, and revised findings exclude saved comment text. Saving waits for a successful restore read and stops on submission. Terminal review verdicts delete drafts, while iterate and hold retain them. Concurrent writers remain last-arrival-wins rather than versioned.
Hardening Proposals
proposed — Use strict session-bound delivery for finding questions: reject unavailable or mismatched session identity instead of falling back to a stored pane. Preserve that identity requirement through screen inspection, Escape and retry.
Pre-merge checks: 4 · 1
Failed checks: 1 warning
Check name
Status
Explanation
Resolution
Docstring Coverage
Docstring coverage is 73.91% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta…
Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed checks: 4 passed
Check name
Status
Explanation
Description Check
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
The title clearly and concisely describes the pull request's main change: adding a board flow for asking the reviewer about a review finding.
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage
Explanation
Docstring coverage is 73.91% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 46 functions across 30 files. (8 skipped: 8 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
Finishing Touches
Generate docstrings
Commit to this branch
Create a new PR
Generate unit tests (beta)
Commit to this branch
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Warning
Review coverage is incomplete: 1 file could not be fully reviewed. Findings from completed review steps are included; see review info for details.
Tip
🎯 Customize your risk assessments
Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.
✅ Automatic approvals, with your rules
Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.
Recent review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: defaults
Review profile: CHILL
Plan: Advanced
Run ID: 3e680997-dc57-4cc4-8e51-6261409b22fd
Commits
Reviewing files that changed from the base of the PR and between 870166b and 497e548.
Files not fully reviewed because their changes were unavailable: 1
docs/apps/design/board/board.pen
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
issue: cmd+enter in this box posts the whole review, since this only catches Escape and sheet-keys.ts submits from any field. could cmd/ctrl+enter stopPropagation here and send the question instead, with a dom test?
The reason will be displayed to describe this comment to others. Learn more.
Fixed: cmd/ctrl+enter in the question box stops there and sends the question, and an empty one sends nothing. The DOM tests cover both keys and check the sheet's own listener never sees them.
The reason will be displayed to describe this comment to others. Learn more.
issue: if the session's gone, the daemon falls back to this stored pane id, which can be stale (livePane ends in ?? claimed). so another agent's pane can get the slash command, and maybe the Escape too. could we resolve the session first, i think paneSelf does it, and 409 with NO_REVIEW_PANE when nothing runs it?
The reason will be displayed to describe this comment to others. Learn more.
It resolves the session first now, with paneSelf and no pane id, so the stored pane is never the fallback. When nothing runs the session it's a 409 with NO_REVIEW_PANE and nothing gets typed or escaped.
The reason will be displayed to describe this comment to others. Learn more.
issue: past the 90 minute park the sweep closes the pane and this drops the ask link with no reason, so older reviews just lose the feature. could the route resume the session with the question as its prompt instead? the catch is supersede only closes open rows, so the re-raise has to close the parked gate too.
The reason will be displayed to describe this comment to others. Learn more.
Done. A parked gate keeps its ask link, and the route resumes the session through resumeAgentPane with the question as the prompt, under the same mrTabLabel(iid, undefined, '↺') as the parked resume, so an open resume tab only gets focused. gates-store.ts now supersedes open and parked rows, with a test.
The reason will be displayed to describe this comment to others. Learn more.
issue: a re-review relaunch also supersedes the open gate, and finding ids are positional, so a fresh run's f2 can show "Revised" with an unrelated original behind it. could we ignore a predecessor older than the lane's runStartedAt?
The reason will be displayed to describe this comment to others. Learn more.
issue: this skips comment and fix, but the skill can revise the comment. then the pane says revised, the sheet shows nothing, and an older edit silently wins. could we compare those too?
> Superseded by [the review finding question design](2026-10-27-review-finding-question-design.md): the question now runs in the reviewer's own pane, with no separate question agent.
| `POST /draft` | flip one of your own MRs between draft and ready, by rewriting the title prefix |
| `GET /review/sheet-draft?mr=<url>` | the review sheet's unsent ticks and edits for one MR, or `null`. Kept so a review gate the review agent re-raises after revising a finding restores them |
The reason will be displayed to describe this comment to others. Learn more.
issue: this isn't in a try/catch like the screen read and focus are, so a herdr failure here rejects the handler instead of returning the documented 409. could we catch it and return failureReason-style text?
suggestion: could we get some storybook stories for this? the review stories in Gates.stories.tsx don't pass onAskQuestion or a reviewRevision, so none of the new ui shows up there.
something like: the ask link, the question box open, sending and a 409 error, the pane gone reason, a parked gate's ask, and the revised strip. fine to go past the "variants go in dom tests" line in apps/board/AGENTS.md for these.
Added in 3137fd3: eight Review question: … stories under Gates/Board, one per state you listed plus "asked". They send through runLaunchFlow with a scripted reply so the toasts match the board, and the ones that need clicks get there in their play step. The AGENTS.md line names them as the exception now.
Every finding on the review sheet gets "ask a question". The board types
/board:review-finding-question <gate> <finding> "<question>" into the
review's own pane and brings Flock to it. There the reviewer explores with
a read-only helper, reports a verdict, and asks for the outcome with a
mattstack:wrap-up form. On a revise it rewrites the finding and re-raises
the gate; the human finishes the review on the board.
- POST /review/finding-question (finding-question.ts), which presses
Escape only over the gate's own question form.
- The board:review-finding-question skill.
- The open sheet follows a re-raised gate onto its successor: /data.json
carries gateReplacements and the decision queue swaps the old gate in
place.
- A revised card shows "Revised in the review pane" with the original,
derived by comparing the new gate with the one it replaced.
- Ticks and comment edits carry over to the re-raised gate through the kv
table, so the board schema is unchanged.
- Mockups B48 and B48b in docs/apps/design/board/board.pen.
Rebuilt on main as one commit; the branch's earlier 43-commit history
included a first design it later removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve the review session's pane before typing into it, resume a parked
review with the question, and seed a re-raised gate from gate-kit's draft
instead of a server-side store.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One story per state of the question flow, through the board's own launch
flow and toasts, so the UI can be worked on in Storybook.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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
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.
Lets you ask the reviewer about one finding before you post it: is it real, is it overstated, what does the data say. The question goes to the reviewer's own Claude session, which already has the code and the review loaded. You talk it through in its pane, and if the finding changes, the reviewer re-raises its gate with the revision. You finish the review on the board as usual.
This replaces the PR's first design (a separate question agent in its own
questionsworkspace). Reusing the reviewer's session saves a cold start, and needs no new workspace and no Flock change.Spec:
docs/superpowers/specs/2026-10-27-review-finding-question-design.md.What changed
Review sheet (
apps/board/src/client/board)/data.jsonnow carriesgateReplacements(old gate to the newest gate in its chain), and the decision queue swaps the replaced gate for its successor in place, without counting it as answered.Board server (
apps/board/src)POST /review/finding-questiontypes/board:review-finding-question <gate> <finding> "<question>"into the reviewer's pane throughpane:send, then brings Flock forward on that pane.paneSelf) and types nothing when none does, so a stale pane on file never gets the line.rt daemon (
lib/daemon/gates-store.ts)parkedgate of the same subject and kind, not only anopenone, so a session resumed off a park can re-raise its gate.Skill
board:review-finding-question(apps/board/skills-src/review-finding-question/). Inside the review session it:Exploreagent (code, logs, New Relic, QA databases through sdm's read-only resources; prod only when you name it);mattstack:wrap-upform: revise and re-raise the gate, leave it as is, or keep asking.superpowers:writing-skills. Agents without the skill dug through code and data inside the reviewer's session, reported in a different shape each time, offered prod unasked, and risked ending the run when the old gate closed. Agents with it did none of that.Design files: B48 and B48b in
docs/apps/design/board/board.pen(renamed from B23/B23b, whichmainnow uses for another frame).Verification
mainat870166b20as one commit, plus the review fixes in their own commit.bun run board:test: 4125 pass.bun run board:typecheck: green. The gate store and handler tests: 155 pass. The board skills drift guard passes.bun run checkis green apart from the console app's tests (getClientRects is not a functionlocally; this PR changes nothing in the console, and main's CI is green).Notes
🤖 Generated with Claude Code
Note
Add board flow for asking the reviewer about a review finding
POST /review/finding-questionroute, which validates the gate and finding, then sends the question to the review agent's existing pane via herdr. If the pane shows a prompt that is not the Claude Code question form, it sends Escape and retries (finding-question.ts, ReviewGateSheet.tsx).board:review-finding-questionskill workflow for the review agent: investigate via a read-only helper, present evidence and a verdict, and wait for the human's choice before revising the report or re-raising the gate (SKILL.md).GET/PUT /review/sheet-draft. Drafts are dropped on a final verdict, on re-review launch, and when the MR leaves the board. Saved comment text is skipped for findings revised in the current gate (review-sheet-draft.ts).GateCachenow retains replaced gate rows, exposes an old-to-new replacement mapping in board data, and the decision queue replaces a superseded gate with its successor without marking it answered (cache.ts, decision-queue.ts).POST /review/finding-questionreturns 409 for missing panes or unlisted findings and 400 for blank, over-2,000-character, or malformed questions; older servers omit the newgateReplacementsfield.Macroscope summarized 94450b5.
Summary by CodeRabbit