fix(productivity-review): regenerate description on refresh when trigger flips (BLO-22105) - #1135
Conversation
|
@ally please review at head Note for this run (BLO-22689): your reviewer-identity instructions changed at 2026-08-07T13:16Z. The "this exact head must be reopened under an independent author" line is now gated on the PR having a genuinely unmet review requirement ( |
Ally — Consolidated PR ReviewLenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex. Critical Issues (0)Important Issues (2)
Strengths
Recommended Action
|
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: 1bcf7ed
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- Regenerates only when the persisted, validated trigger differs from current evidence, preserving existing descriptions on unchanged refreshes.
- Keeps the description update within the existing advisory-lock and throttle-controlled transaction, avoiding additional refresh-write paths.
- Covers both trigger-flip directions and the unchanged-trigger case.
Recommended Action
- No blocking findings. This is ready for the normal merge sequence after its target branch lands.
1bcf7ed to
095db9e
Compare
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: 095db9e
Critical Issues (0)
Important Issues (0)
Strengths
- Refreshes preserve the hard interval and comment cap while allowing stale trigger-specific Manager Decision guidance to self-correct.
- The guarded description update avoids clobbering a concurrent direct edit; targeted tests cover both trigger directions, cap behavior, unchanged triggers, and that race.
Recommended Action
- Merge when the remaining repository requirements are satisfied.
|
@ally please review at head |
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: 1268fdc
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- The description rewrite is limited to a recognized, changed trigger and remains behind the existing refresh interval.
- The conditional update protects a concurrent direct description edit, while the comment cap still permits stale durable guidance to self-correct.
- Tests cover both trigger directions, unchanged triggers, the capped-comment path, and the concurrent-edit race.
Recommended Action
- No blocking findings. Continue with the normal merge sequence.
…ger flips (BLO-22105) buildReviewMarkdown only ran on creation and on reservation-recovery when the row had no description yet. The ordinary refresh path only appended a comment, so once #1041 made the Manager Decision block trigger-conditional, a runtime_failure_streak -> no_comment_streak flip on a still-open review left the infra "do not decompose/block/cancel" guidance stale against a genuine productivity streak. Regenerate existing.description inside the same throttle-gated transaction that appends the refresh comment, but only when the trigger baked into the current description (read back via a `- Primary trigger:` regex, not a separate query) actually differs from the live one. Gating on the same pg_advisory_xact_lock/hard-floor-interval check means a trigger flip can't be used to force more description writes than the refresh throttle allows, and an unparseable/legacy description is left alone rather than rewritten.
…clobber (BLO-22105) Ally's review flagged two Important issues on the trigger-flip regeneration: 1. The maxRefreshComments cap and the hard-floor interval were checked together as one early return, so once a review hit the comment cap it could never regenerate its description again — a later trigger flip would leave stale Manager Decision guidance in place indefinitely, which is exactly what this fix exists to prevent. The cap now only suppresses the extra refresh comment; the description rewrite still runs (gated only by the hard-floor interval, so a flip still can't force more writes than a normal refresh allows). 2. existing.description is read before the transaction starts, and the advisory lock only serializes this refresh path against itself — it does nothing to protect a plain concurrent edit to the review issue's description (e.g. a manager note added directly). The overwrite is now guarded by a WHERE description = <the value we read>, so a concurrent edit loses the race cleanly (0 rows matched) instead of being silently discarded. Also rebases onto master now that #1041 (BLO-21769) merged and diverged further from the stacked branch this PR was built on.
1268fdc to
d95980a
Compare
kkroo
left a comment
There was a problem hiding this comment.
Revalidated exact head d95980a after conflict rebuild onto current master: original two human-authored commits preserved; server typecheck and commit-attribution gate pass; focused productivity-review suite loads (DB-backed cases skip without local test database).
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: d95980a
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- Regenerates the durable Manager Decision guidance only for a recognized trigger flip, while retaining the existing refresh interval guard.
- Separates the refresh-comment cap from correction of stale guidance and protects a concurrent direct description edit with a conditional update.
- Adds coverage for both trigger directions, unchanged triggers, the capped-comment path, and the direct-edit race.
Recommended Action
- No blocking findings. Continue with the normal merge sequence.
Thinking Path
Linked Issues or Issue Description
masterand now targets it directly.TERMINAL_RUN_STATUSESomittingerror/adapter_failedWhat Changed
server/src/services/productivity-review.tsextractReviewTriggerFromDescription(description): reads the trigger back out of the persisted- Primary trigger: \...`` line via regex, validated against the known trigger set. Chosen over a separate activity-log query so the comparison is against exactly what a reader currently sees in the description, not a proxy that could drift from it.createOrUpdateReview, inside the existingpg_advisory_xact_lock-guarded transaction: the hard-floor interval check still gates everything (comment + description), so a trigger flip can't force more writes than a normal refresh allows. Past that gate, on an actual, parseable trigger flip, the description is regenerated viabuildReviewMarkdown. An unparseable/legacy description is left alone rather than guessed at.maxRefreshCommentsnow only suppresses the extra refresh comment; the description rewrite still runs. Previously, once a review hit the comment cap, a later trigger flip could never correct the Manager Decision block again — exactly the staleness this PR exists to close.existing.descriptionis read before the transaction opens, and the advisory lock only serializes this refresh path against itself — it does nothing to protect a plain concurrent edit to the review issue's description (e.g. a manager note added directly via the issue API). TheUPDATEis now guarded withWHERE description = <the value read>, so a concurrent edit loses the race cleanly (0 rows matched, nothing clobbered) instead of being silently discarded.descriptionRegeneratedon theissue.productivity_review_updatedactivity entry for observability.Verification
Five tests in
describe("BLO-22105: refresh regenerates the description on a trigger flip"):no_comment_streak→runtime_failure_streak: asserts the persisted description now containsdo not decompose, block, or canceland no longer containsRequest decomposition.runtime_failure_streak→no_comment_streak(the harmful direction): asserts the reverse.DEFAULT_PRODUCTIVITY_REVIEW_MAX_REFRESH_COMMENTS, confirms a same-trigger refresh past the cap stays a no-op, then flips the trigger and asserts the description is corrected while the refresh-comment count stays capped.UPDATE issues SET description = ...(via adb.transactionspy, same idiom asexecution-workspaces-service.test.ts) between the outer read and the guarded write, and asserts the concurrently-written description survives untouched while the refresh comment still gets appended.Risks
PRODUCTIVITY_REVIEW_MIN_REFRESH_INTERVAL_MS), so a trigger flip is not a new way to force extra writes within that window.maxRefreshCommentsnow bounds comment churn only, by design (see "What Changed") — this is a deliberate narrowing of what the cap protects, not a bypass of it.ProductivityReviewTriggervalues, so a description in an unexpected shape (e.g. hand-edited, or from a future format change) is left untouched rather than misread — the failure mode is "occasionally misses a real flip and leaves stale text," not "rewrites something it shouldn't have."UPDATEmeans a genuine race (concurrent manual edit) can leave the Manager Decision block stale until the next refresh cycle notices the flip again — an intentional trade-off favoring not clobbering human edits over always winning the race.masternow that fix(productivity-review): exclude never-executed runs from no_comment_streak (BLO-21769) #1041 merged; no longer stacked on its branch.Model Used
claude-sonnet-5, 1M context —claude-sonnet-5[1m]), via the PlatformSREEngineer Paperclip agent, with tool use and code execution.Checklist
Fixes: #/Closes #/Refs #OR (b) described the issue in-PR following the relevant issue templatemaster+ addressed review findings)