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
orb(observability): the orphaned review_targets table silently disables the anomaly alerter, the reputation quality signal, and the AMS bridge — and the reputation half expires to empty around 2026-09-20 #9136
review_targets has no live writer anywhere — stated outright in the code itself
(src/db/repo-identity-rename.ts:585-586: "has NO live writer anywhere in this codebase"; src/review/public-stats.ts:275: "the convergence cutover orphaned (nothing writes it anymore)"). It
was orphaned by the 2026-06-22 convergence cutover.
Three subsystems still read it as their primary source and are therefore inert or expiring, with no
alarm on any of them.
1. The Discord anomaly alerter can never fire
runAnomalyAlerts bails at if (anomalies.length === 0) return;. detectAnomalies(health, calibration)
draws every line from computeAgentHealth / computeCalibration, whose queries are all FROM review_targets or JOIN review_targets t ON t.id = a.target_id (src/review/ops.ts:219-249, :294-299).
The remaining two inputs come from defaultOpsHealthDeps (alerts-wire.ts passes no deps): validateAgentConfig: () => [] and isHoldOnly: async () => false. So configIssues is always [], holdOnly always false, every count 0.
Even with LOOPOVER_REVIEW_OPS=1 and a valid DISCORD_WEBHOOK_URL, the alerter runs hourly, computes an
all-zero snapshot, and returns. The whole "reversals / DLQ spike / disputed closes / calibration drift /
manual-rate spike" channel is dead — and the same zeros are served to the operator by the /status and /calibration ops endpoints as an apparently healthy snapshot.
There is a second, independent break: review_audit.target_id is "owner/repo#123"
(outcomes-wire.ts:275-277) while review_targets.id is a different id namespace, so the reversal/DLQ
joins could not match even if the table were repopulated.
2. The reputation quality signal is a slowly-expiring ghost
#9015 repointed getSubmitterCadence to pull_requests and left the comment "reads the LIVE ledger" —
but getSubmitterReputation, getSubmitterReputationAcrossInstall, and listSubmitterCohortRows
(src/review/submitter-reputation.ts:302-312, :338-353, :388-399) still query FROM review_targets … terminal_at >= datetime('now', ?). With the ledger frozen at 2026-06-22 and a 90-day window, those
queries return a shrinking set that reaches permanently empty around 2026-09-20.
Consequences: promptInjection > 0 → "low" — the only hard-abuse rule in the reputation model — can
never fire on post-cutover data; "trusted" is unreachable, which makes the entire src/review/ams-reputation-bridge.ts (an upgrade-only bridge whose sole output is "trusted") inert by
construction; the low_reputation skip in evaluateVisualVisionGate
(src/review/visual/visual-findings.ts:88) and evaluateScreenshotTableVisionGate
(screenshot-table-vision.ts:68) is inert and has no compensating hold — so restoring the signal
without fixing those reproduces #9015's "suspicion buys less scrutiny" shape.
3. The AMS-vs-human cohort dashboard silently empties
src/review/ams-miner-cohort.ts (#6488) degrades to present: false.
Dedup
#9015 is closed; its fix point 2 ("restore a live writer for review_targetsor repoint the
cadence query") was satisfied by the narrower half only. Reporting the remainder as an incomplete fix.
The review_targets-frozen fact is noted in the prior audit's notes but no issue owns the consequences.
Requirements
Decide once: repoint every reader at the live ledgers (pull_requests + audit_events with the owner/repo#n target key, as public-stats.ts and ops-wire.ts already do), or restore a writer.
Do not leave both halves half-done again — enumerate every reader in the PR description.
Fix the target_id namespace mismatch in the reversal/DLQ joins.
Before restoring the reputation signal, give the two vision-gate skips a compensating hold.
Test Coverage Requirements
99%+ patch coverage, branch-counted; a test per repointed query asserting non-empty results against live
fixtures, and both arms of the staleness assertion.
Problem
review_targetshas no live writer anywhere — stated outright in the code itself(
src/db/repo-identity-rename.ts:585-586: "has NO live writer anywhere in this codebase";src/review/public-stats.ts:275: "the convergence cutover orphaned (nothing writes it anymore)"). Itwas orphaned by the 2026-06-22 convergence cutover.
Three subsystems still read it as their primary source and are therefore inert or expiring, with no
alarm on any of them.
1. The Discord anomaly alerter can never fire
runAnomalyAlertsbails atif (anomalies.length === 0) return;.detectAnomalies(health, calibration)draws every line from
computeAgentHealth/computeCalibration, whose queries are allFROM review_targetsorJOIN review_targets t ON t.id = a.target_id(src/review/ops.ts:219-249,:294-299).The remaining two inputs come from
defaultOpsHealthDeps(alerts-wire.tspasses no deps):validateAgentConfig: () => []andisHoldOnly: async () => false. SoconfigIssuesis always[],holdOnlyalways false, every count 0.Even with
LOOPOVER_REVIEW_OPS=1and a validDISCORD_WEBHOOK_URL, the alerter runs hourly, computes anall-zero snapshot, and returns. The whole "reversals / DLQ spike / disputed closes / calibration drift /
manual-rate spike" channel is dead — and the same zeros are served to the operator by the
/statusand/calibrationops endpoints as an apparently healthy snapshot.There is a second, independent break:
review_audit.target_idis"owner/repo#123"(
outcomes-wire.ts:275-277) whilereview_targets.idis a different id namespace, so the reversal/DLQjoins could not match even if the table were repopulated.
2. The reputation quality signal is a slowly-expiring ghost
#9015 repointed
getSubmitterCadencetopull_requestsand left the comment "reads the LIVE ledger" —but
getSubmitterReputation,getSubmitterReputationAcrossInstall, andlistSubmitterCohortRows(
src/review/submitter-reputation.ts:302-312,:338-353,:388-399) still queryFROM review_targets … terminal_at >= datetime('now', ?). With the ledger frozen at 2026-06-22 and a 90-day window, thosequeries return a shrinking set that reaches permanently empty around 2026-09-20.
Consequences:
promptInjection > 0 → "low"— the only hard-abuse rule in the reputation model — cannever fire on post-cutover data;
"trusted"is unreachable, which makes the entiresrc/review/ams-reputation-bridge.ts(an upgrade-only bridge whose sole output is"trusted") inert byconstruction; the
low_reputationskip inevaluateVisualVisionGate(
src/review/visual/visual-findings.ts:88) andevaluateScreenshotTableVisionGate(
screenshot-table-vision.ts:68) is inert and has no compensating hold — so restoring the signalwithout fixing those reproduces #9015's "suspicion buys less scrutiny" shape.
3. The AMS-vs-human cohort dashboard silently empties
src/review/ams-miner-cohort.ts(#6488) degrades topresent: false.Dedup
#9015 is closed; its fix point 2 ("restore a live writer for
review_targetsor repoint thecadence query") was satisfied by the narrower half only. Reporting the remainder as an incomplete fix.
The
review_targets-frozen fact is noted in the prior audit's notes but no issue owns the consequences.Requirements
pull_requests+audit_eventswith theowner/repo#ntarget key, aspublic-stats.tsandops-wire.tsalready do), or restore a writer.Do not leave both halves half-done again — enumerate every reader in the PR description.
target_idnamespace mismatch in the reversal/DLQ joins.window, so the next orphaning is loud rather than silent. This is the generalisable fix — the same
class produced orb(db): the review-effort metric is silently broken on Postgres — avg(text) errors and the failure is swallowed #9084 and the DLQ dead-alert findings.
Test Coverage Requirements
99%+ patch coverage, branch-counted; a test per repointed query asserting non-empty results against live
fixtures, and both arms of the staleness assertion.
Links & Resources
src/review/ops.ts~219-249, ~294-299;src/review/alerts.ts~243-244;src/review/alerts-wire.ts~31-37;src/review/submitter-reputation.ts~114-124, ~302-312, ~338-353, ~388-399;src/db/repo-identity-rename.ts~585-586;src/review/public-stats.ts~275maintainer-only — observability and reputation integrity.