feat: attach to an earlier review of the same diff on events #29
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/same-diff-attach"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Events now send
attach_same_diff: true, so a rebase that leaves the PR's diff unchanged reuses the service's earlier review instead of starting a new one. A manualworkflow_dispatchsendsfalseand still starts fresh.Reuse lets an earlier review return after a later one marked its threads superseded. The reconcilers counted those threads as posted, leaving the returning review's findings with no live thread; they now repost them.
A 422
diff-unreadablefrom the service now ends the run with its own outcome and a re-run remedy.Merge after j4k/review#142. Enrolled repos see no change until the align pin moves. The local
attach_same_difftype insrc/review/api.tsbreaks the build once a published@j4k/reviewdeclares the field, so it goes with that bump.A run cancelled between labelling an old thread superseded and resolving it can leave that thread open beside the fresh one.
🤖 Generated with Claude Code
Review
01M445XX16DSK1ZPJXFRG8AK47— head49f287c3161debaa4069d03fbcdaa0fdcaea5abcReview — j4k-oss/review-wrapper @
47c7ab2f66Scope: diff against base tree
e69943819640Status: dispatched — coverage complete (5/5 slots terminal)
Facts: current review-wide projection
Computed under:
Findings (5)
medium — README outcomes table copies every member of
OUTCOMESand its exit code fromOUTCOME_EXIT01M4460WHPR42RVC894XYHHR2QREADME.md(snippet)01M4464JEE7KQN5XV4FYGXWQYE· valid: Grounded row 13 confirms that the README table restates outcomes with exit codes. The body names the sources (OUTCOMES and OUTCOME_EXIT in src/contract/types.ts) and lists every member and exit code. The table covers the same twelve outcomes plus row 11, which the table itself labels as a flag, not an outcome, so no outcome and no exit code is mismatched. Severity is medium. No exception applies. The README is not generated or read by code, the outcome set is this repository's own, the table is not a dated record, and it is not a table of contents for choosing what to open. Its reader can open the source, so the sandboxed-reader exception does not apply. The correction follows the guideline: point to the sources, move per-outcome detail into each OUTCOMES entry's comment, and keep in prose only the row-11 and head-moved detail that no member definition can hold.medium — README paragraph enumerates the HTTP 422 problem types
toFailureclassifies, framed as the complete set01M44617NH6GQ6P74MFWDZT4RVREADME.md(snippet)01M4464JEE7KQN5XV4FYGXWQYE· valid: The grounded excerpt names both 422 problem types and says 'the wrapper retries neither', followed by 'Unclassified service rejections...'. That framing presents the two types as the complete classified set. The body names the source (the status === 422 && problem.type branches of toFailure in src/review/session.ts) and lists its two members. They match the copy, so this is medium. The third-party exception does not apply. The service defines the problem-type vocabulary, but the README describes which types the wrapper chooses to classify, and that is a selection the subject makes. The correction points to toFailure and lists no members, so it does not restate the set.medium — Outcomes header comment re-lists the table rows that
OUTCOMESdefines directly below it01M4460EPAG60AS8PW0MQ03K9Hsrc/contract/types.ts(snippet)01M4464JEE7KQN5XV4FYGXWQYE· valid: Grounded exact anchor shows the header enumerating 'rows 1–10, 12, 13'. The body names the source (OUTCOMES in src/contract/types.ts, directly below) and lists its members by row comment (1–10, 12, 13), compares them with the copy, and finds no mismatch. So the copy agrees, which makes this medium, not high. No exception applies: a code comment is not read by the system, not a dated record, and the list claims to be the whole set. Because the comment describes the adjacent array, the guideline's correction is to delete the enumeration. The proposed fix does that and keeps only what the array cannot show, the note about the excluded row 11. Medium is correct.01M4460KEGVT32PYF5ZKJ9MDKW(writing-quality)low — README restates the
diff-unreadablemeaning that table row 13 directly above already gives01M4461DCY4ADTWA9YKT5XCVSCREADME.md(snippet)01M4464JEE7KQN5XV4FYGXWQYE· valid: Both sides are grounded. Row 13 (anchor of 01M4460WHPR42RVC894XYHHR2Q) reads 'the service could not read the PR's diff from the forge', and the paragraph's parenthetical repeats that clause word for word a few lines later. Under the writing skill's 'One Idea, One Place', the duplicate should go. Deleting it loses nothing, because row 13 keeps the meaning, and the problem-type mapping and the no-retry rule remain. The paragraph also leaves forge-host-mismatch unexplained in the same way, so the result reads consistently. Low is appropriate.low — Comment calls a superseded thread "closed", but the check is the label alone and a labelled thread can stay open
01M4461DPCHEBNQQMHCR63NNKRsrc/reconcile/inline.ts(snippet)01M4464JEE7KQN5XV4FYGXWQYE· valid: The grounded comment says a superseded thread 'was closed'. The reviewer's trace is specific and coherent. postedClaimIds skips a conversation when isSuperseded is true. isSuperseded only checks for a '<!-- review:superseded:' marker comment. The scenario-7 test expects a labelled but open thread ('headA claim+superseded open') followed by a fresh post. In review-thread vocabulary, 'closed' plausibly reads as resolved, which contradicts the label-only rule and the open state the test pins. A maintainer could then switch the check to resolution state and break that case. The correction describes the label and keeps the A, B, A reasoning, so it loses nothing. Low is appropriate for a misleading comment.Other claims
01M4460KEGVT32PYF5ZKJ9MDKWmedium — Outcomes header comment restates the row set that theOUTCOMESarray directly below already defines →01M4460EPAG60AS8PW0MQ03K9H01M4460ZCR7EHPVD63SMPTH5SSlow — Test names carry "scenario N" numbers (1, 2, 4, 7, 10–12) from a list nothing in the repository definesCoverage
Coverage pass: 01M445XX2WEGF4M429DDMPW1B3
Accounting: complete
Slot health: healthy
@ -84,16 +84,19 @@ the secret.| 10 | `clean-findings` | Full reconcile. | 0 || 11 | superseded | A flag, not an outcome; it does not itself change the exit code. Coverage and report accounting stay pinned; triage, claims, and findings remain review-wide. | — || 12 | `head-moved` | No PR comment or conversation-resolution writes; the newer run owns the comment surface. See the timing below. | 0 || 13 | `diff-unreadable` | No comment — the service could not read the PR's diff from the forge. Names the re-run remedy. | 1 |medium — README outcomes table copies every member of
OUTCOMESand its exit code fromOUTCOME_EXITlens
restated-sets· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4460WHPR42RVC894XYHHR2Qof review01M445XX16DSK1ZPJXFRG8AK47@ -95,2 +93,2 @@`unknown-commit`, and HTTP 413 `tree-too-large`. Unparseable error responses retainthe HTTP status and raw body. A rejection before reconciliation writes no comments.HTTP 422 with problem type `/problems/forge-host-mismatch` receives the forge-hostremedy, and `/problems/diff-unreadable` (the service could not read the PR's diff fromlow — README restates the
diff-unreadablemeaning that table row 13 directly above already giveslens
writing-quality· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4461DCY4ADTWA9YKT5XCVSCof review01M445XX16DSK1ZPJXFRG8AK47@ -94,3 +93,3 @@HTTP status, problem type, title, and detail in the job log, including `unknown-tree`,`unknown-commit`, and HTTP 413 `tree-too-large`. Unparseable error responses retainthe HTTP status and raw body. A rejection before reconciliation writes no comments.HTTP 422 with problem type `/problems/forge-host-mismatch` receives the forge-hostremedy, and `/problems/diff-unreadable` (the service could not read the PR's diff fromthe forge) receives a re-run remedy; the wrapper retries neither. Unclassified servicemedium — README paragraph enumerates the HTTP 422 problem types
toFailureclassifies, framed as the complete setlens
restated-sets· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M44617NH6GQ6P74MFWDZT4RVof review01M445XX16DSK1ZPJXFRG8AK47@ -36,3 +36,3 @@}// ---- Outcomes: the §7 failure/exit table (rows 1–10, 12; row 11 is the// ---- Outcomes: the §7 failure/exit table (rows 1–10, 12, 13; row 11 is themedium — Outcomes header comment re-lists the table rows that
OUTCOMESdefines directly below itlens
restated-sets· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4460EPAG60AS8PW0MQ03K9Hof review01M445XX16DSK1ZPJXFRG8AK47@ -25,3 +27,3 @@}async function existingClaimMarkers(forge: ForgeClient, prNumber: number): Promise<string[]> {// A superseded thread was closed for a later Review, with no way back, so it no longerlow — Comment calls a superseded thread "closed", but the check is the label alone and a labelled thread can stay open
lens
writing-quality· armdefault· tally 1 valid / 0 invalid / 0 uncertainclaim
01M4461DPCHEBNQQMHCR63NNKRof review01M445XX16DSK1ZPJXFRG8AK47Tracked in #30, which replaces the copied outcome rows, the 422 problem-type list and the row list in the
types.tsheader with pointers toOUTCOMES,OUTCOME_EXIT,toFailure,FAILURE_REMEDIESandprefixFor. It is stacked on this PR.Tracked in #30, which replaces the copied outcome rows, the 422 problem-type list and the row list in the
types.tsheader with pointers toOUTCOMES,OUTCOME_EXIT,toFailure,FAILURE_REMEDIESandprefixFor. It is stacked on this PR.Tracked in #30, which replaces the copied outcome rows, the 422 problem-type list and the row list in the
types.tsheader with pointers toOUTCOMES,OUTCOME_EXIT,toFailure,FAILURE_REMEDIESandprefixFor. It is stacked on this PR.Tracked in #30, which replaces the copied outcome rows, the 422 problem-type list and the row list in the
types.tsheader with pointers toOUTCOMES,OUTCOME_EXIT,toFailure,FAILURE_REMEDIESandprefixFor. It is stacked on this PR.Tracked in #31, which rewords the comment to say a thread labelled superseded is final even when a cancelled run left it open, matching the label-only check in
isSuperseded. It is stacked on this PR.The unadjudicated claim
01M4460ZCR7EHPVD63SMPTH5SSis valid: the test names insrc/reconcile/returning-review.test.tscarried "scenario N" numbers that no file in this repository defines. Tracked in #31, which renames those tests to say what each one sets up and asserts. It is stacked on this PR.