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
downgradeCloseToHold only considers a close downgradable when closeKind === "heuristic" (src/settings/agent-actions.ts ~617-620). Six close paths carry other closeKind values — blacklist, contributor_cap, review_nag, copycat, screenshot_table, linked-issue-hard-rule — so the close-precision circuit breaker returns their plans untouched in both Reason A (project breaker) and Reason B (per-rule precision). They also get no executor-side live recheck: every guard at src/services/agent-action-executor.ts ~416-439 requires closeKind === "heuristic".
The stated justification ("zero-hallucination, deterministic") is sound for blacklist and contributor_cap — those read facts about an account. It is not sound for screenshot_table, whose determinism is a regex heuristic over free-text markdown, and which is our top close reason (170 all-time). A deterministic rule can still be systematically wrong; that is exactly what the breaker exists to catch.
Related ordering hazard
The five anti-abuse short-circuits sit above both the conclusion === "skipped" return (~950) and the CI-pending settle (~994). So a screenshot-table close executes on a PR whose gate was never evaluated and whose CI is still running — "push a commit → closed before CI finishes."
Latent false-positive classes in the screenshot gate (code-confirmed, NOT currently firing)
I checked 8 recently screenshot-closed PRs against GitHub: all had zero images in the body, so those closes were correct and these paths are latent rather than active. Filed so they are fixed before they bite:
Staleness on any second push (packages/loopover-engine/src/review/screenshot-table-gate.ts ~417-433): same evidence fingerprint + different head ⇒ violated. A rebase or CI retrigger without re-uploading screenshots closes a compliant PR. Amplified because presenceModeEvidenceFingerprint (~350-352) filters urls.length >= 2, so the common one-image-per-row layout fingerprints as "[]" and is permanently stale from push chore(release): prepare public gittensory launch #2.
hasImageOutsideTable (~160-166) is a bare per-line regex with no code-fence awareness: a correct table plus a CI badge, logo, or fenced markdown example ⇒ violated.
hasCommittedImageFile (~173-179) is scopedPaths.length === 0 || matchesAny(...), so when the gate is scoped by labels only it checks every changed path — a UI PR that adds any image asset is closed, table or not.
Fix
Split the breaker exemption: keep it for identity-based closes (blacklist, cap); subject content-inspection closes (screenshot_table, linked-issue rule 4) to the per-rule precision check with their own rule ids.
Move the short-circuits below the CI-pending settle.
Fix the three screenshot FP classes: fingerprint single-image rows, only treat evidence as stale when the push touched in-scope visual paths, and require a non-empty whenPaths for the committed-image check.
downgradeCloseToHoldonly considers a close downgradable whencloseKind === "heuristic"(src/settings/agent-actions.ts~617-620). Six close paths carry othercloseKindvalues —blacklist,contributor_cap,review_nag,copycat,screenshot_table,linked-issue-hard-rule— so the close-precision circuit breaker returns their plans untouched in both Reason A (project breaker) and Reason B (per-rule precision). They also get no executor-side live recheck: every guard atsrc/services/agent-action-executor.ts~416-439 requirescloseKind === "heuristic".The stated justification ("zero-hallucination, deterministic") is sound for
blacklistandcontributor_cap— those read facts about an account. It is not sound forscreenshot_table, whose determinism is a regex heuristic over free-text markdown, and which is our top close reason (170 all-time). A deterministic rule can still be systematically wrong; that is exactly what the breaker exists to catch.Related ordering hazard
The five anti-abuse short-circuits sit above both the
conclusion === "skipped"return (~950) and the CI-pending settle (~994). So a screenshot-table close executes on a PR whose gate was never evaluated and whose CI is still running — "push a commit → closed before CI finishes."Latent false-positive classes in the screenshot gate (code-confirmed, NOT currently firing)
I checked 8 recently screenshot-closed PRs against GitHub: all had zero images in the body, so those closes were correct and these paths are latent rather than active. Filed so they are fixed before they bite:
packages/loopover-engine/src/review/screenshot-table-gate.ts~417-433): same evidence fingerprint + different head ⇒ violated. A rebase or CI retrigger without re-uploading screenshots closes a compliant PR. Amplified becausepresenceModeEvidenceFingerprint(~350-352) filtersurls.length >= 2, so the common one-image-per-row layout fingerprints as"[]"and is permanently stale from push chore(release): prepare public gittensory launch #2.hasImageOutsideTable(~160-166) is a bare per-line regex with no code-fence awareness: a correct table plus a CI badge, logo, or fenced markdown example ⇒ violated.hasCommittedImageFile(~173-179) isscopedPaths.length === 0 || matchesAny(...), so when the gate is scoped by labels only it checks every changed path — a UI PR that adds any image asset is closed, table or not.Fix
whenPathsfor the committed-image check.Refs #9030, #9040.