Skip to content

feat: unify outstanding feedback and apply suggested changes - #107

Open
pulkitxm wants to merge 1 commit into
claude/quinjet-ci-operationsfrom
claude/quinjet-feedback-queue
Open

pulkitxm wants to merge 1 commit into
claude/quinjet-ci-operationsfrom
claude/quinjet-feedback-queue

Conversation

@pulkitxm

Copy link
Copy Markdown
Owner

Stacked on #106. Review only the top commit.

An author coming back to a pull request reads three views to find what is outstanding: the conversation for threads, the checks for what failed, and the review verdicts for who is blocking. None of them says which of those is waiting on them.

$ quinjet pr feedback 42
changes   you     @hubot                           1 reviewer requested changes
failure   -       feature.txt:1                    use a slice
thread    you     feature.txt:1                    Please rename this file
outdated  others  feature.txt:1                    Left over from an older push
advisory  -       README.md:2                      Spell Checker

2 blocking, 3 advisory · 1 on you, 1 on others
next  changes @hubot
$ quinjet pr suggestions 42
COMMENT_1                feature.txt:1                +1 -1  @hubot  ready
COMMENT_2                src/lib.rs:12-14             +2 -3  @hubot  a later commit moved the code it was written against

1 ready to apply, 1 blocked

Decisions worth reviewing

The owner column is what makes one queue serve both an author and a reviewer. It is computed against the authenticated viewer: you when the newest word is somebody else's, others when it is yours, nobody for a check finding. A changes-requested verdict you wrote yourself is others, because you are waiting on the author rather than on yourself.

Blocking and advisory stay apart, for the same reason the merge gate keeps blockers and notes apart: a queue where everything looks equally urgent is a list. Rows are ordered by how directly they stand in the way, so the first row is always the most direct obstacle and the order is stable across reads.

Every row carries the command that resolves it, so a caller does not have to know the verb map. --full prints it.

Filters narrow rows and counts together, so the summary always describes what was printed and --exit-code reads the filtered counts. --no-checks does not read the annotations at all.

Applying a suggestion is where the care went. A suggestion's line numbers only mean something against the commit it was written for, so four things are checked before anything is written:

  1. The worktree is at the pull request's head — checked before the plan is worked out, so a caller on the wrong branch is told which branch to check out rather than that there is nothing to apply.
  2. The files have no uncommitted changes, so a local edit that exists nowhere else is never clobbered.
  3. No two suggestions overlap — there is no order that is obviously what the reviewers meant, so both are skipped rather than one silently winning.
  4. Every range is inside its file.

Files are written all or none; a failure part-way restores what was already written. Without --message the tree is left changed and unstaged; with it, exactly the files the plan touched are staged, so an unrelated edit elsewhere stays out of the commit.

Every skip is reported with its reason. A suggestion that quietly did not apply is worse than one that says why.

A replacement containing a fence is refused rather than escaped. It would close the suggestion fence early and land the rest as prose. A rewritten suggestion is not the one the author wrote, and posting it would put words in their mouth on somebody else's pull request.

Tests

  • 11 feedback unit tests: ordering across all five kinds, resolved threads never appearing, who owes the next word, your own request-for-changes being owned by others, check findings owned by nobody and pointing at their log, excerpt cutting, each filter and both together, truncation.
  • 18 suggestion unit tests: fence composition and its refusal, parsing single and multi-line ranges, two blocks in one comment, an empty replacement as a deletion, each GitHub-side blocker, listing counts and selection, and nine planner tests against real temporary worktrees covering line replacement, ordering, overlap refusal, out-of-range, missing file, a file with no trailing newline, and writing only the named files.
  • 14 black-box tests: the combined queue and its JSON, the three filters, the exit code, the full face, the suggestion listing, previewing without writing, applying with a commit, --all, both refusals with the file verified unchanged, the unknown-id hint, posting a suggestion with the fence in the payload, and the fence refusal.
  • 8 renderer tests and 17 argument-parsing cases.

Notes

  • session.rs and pull_request.rs crossed the 500-line limit again; both are split by concern (session/actions.rs, session/feedback.rs, session/workspaces.rs, pull_request/prepared.rs).
  • The shared review fixture now carries a suggestion block and an outdated thread, so the earlier review-progress tests assert two unresolved threads instead of one.
  • git::github::tests::operations::discovers_distinct_fetch_and_push_repositories_for_each_remote fails in my sandbox on main too (global config rewrites git@github.com: to HTTPS). Unrelated.

Docs: feedback.md, suggestions.md, review-suggest.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_011n3Xp6dLNibg3gCBN9y5ij


Generated by Claude Code

@pulkitxm
pulkitxm deployed to pukbot-production August 29, 2026 13:05 — with GitHub Actions Active
@pulkitxm
pulkitxm deployed to pukbot-production August 29, 2026 13:05 — with GitHub Actions Active
@pukbot pukbot Bot added size/XXL documentation Improvements or additions to documentation rust git cli labels Aug 29, 2026
@pulkitxm
pulkitxm deployed to pukbot-production August 29, 2026 14:07 — with GitHub Actions Active
@pulkitxm
pulkitxm deployed to pukbot-production August 29, 2026 14:07 — with GitHub Actions Active
@pulkitxm
pulkitxm force-pushed the claude/quinjet-feedback-queue branch from e97b47c to 2762e94 Compare August 29, 2026 14:09
@pulkitxm
pulkitxm deployed to pukbot-production August 29, 2026 14:09 — with GitHub Actions Active
@pulkitxm
pulkitxm deployed to pukbot-production August 29, 2026 14:09 — with GitHub Actions Active
@pulkitxm
pulkitxm force-pushed the claude/quinjet-feedback-queue branch from 2762e94 to 24fc6e5 Compare August 29, 2026 14:15
@pulkitxm
pulkitxm deployed to pukbot-production August 29, 2026 14:15 — with GitHub Actions Active
@pulkitxm
pulkitxm deployed to pukbot-production August 29, 2026 14:15 — with GitHub Actions Active
@pulkitxm
pulkitxm marked this pull request as ready for review August 29, 2026 14:43
An author coming back to a pull request reads three views to find what is
outstanding: the conversation for threads, the checks for what failed, and
the review verdicts for who is blocking. None of them says which of those
is waiting on them.

`quinjet pr feedback` is one queue out of all three, ordered by how directly
each row stands between the pull request and merging, and with an owner
column computed against the authenticated viewer: `you` when the newest
word is somebody else's, `others` when it is yours, `nobody` for a check
finding. A changes-requested verdict you wrote yourself is `others`, because
you are waiting on the author rather than on yourself.

Blocking and advisory are kept apart for the same reason the merge gate
keeps blockers and notes apart: a queue where everything looks equally
urgent is a list. Every row also carries the command that resolves it, so a
caller does not have to know the verb map.

`quinjet pr suggestions` reads the suggestion blocks reviewers left and
applies them to the working tree, and `quinjet pr reviews suggest` writes
one without having to remember the fence.

Applying is where the care went. A suggestion's line numbers only mean
something against the commit it was written for, so four things are checked
before anything is written: the worktree is at the pull request's head, the
files have no uncommitted changes, no two suggestions overlap, and every
range is inside its file. The head check happens before the plan is worked
out, so a caller on the wrong branch is told which branch to check out
rather than that there is nothing to apply. Files are written all or none.

Every skip is reported with its reason. A suggestion that quietly did not
apply is worse than one that says why. And a replacement containing a fence
is refused rather than escaped: a rewritten suggestion is not the one the
author wrote, and posting it would put words in their mouth.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011n3Xp6dLNibg3gCBN9y5ij
@pukbot

pukbot Bot commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

This pull request has had no activity for 45 days. Comment or push to keep it open, otherwise it closes in 14 days.

@pukbot pukbot Bot added the Stale label Oct 14, 2026

This branch was successfully deployed

1 active deployment
pukbot-production — e5508425 Deployed Aug 29, 2026 by pulkitxm via Size label #344
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli documentation Improvements or additions to documentation git rust size/XXL Stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants