fix(agent-actions): close hard-blocked contributor PRs in auto mode - #2856
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2856 +/- ##
=======================================
Coverage 96.01% 96.02%
=======================================
Files 259 259
Lines 28304 28334 +30
Branches 10291 10298 +7
=======================================
+ Hits 27177 27207 +30
Misses 491 491
Partials 636 636
🚀 New features to boost your workflow:
|
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-04 02:33:52 UTC
⏸️ Suggested Action - Manual Review
Review summary Nits — 6 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
ea61c4b to
87a286b
Compare
VPS evidence (system_flags) showed closehold:<repo> engaged for all three review-active repos since 2026-06-28, silently downgrading every heuristic close to a human hold regardless of autonomy.close=auto. Three compounding, generic self-host engine bugs: - The close-precision circuit breaker treated every heuristic close identically, including ones backed by concrete, non-judgment evidence (a committed secret, red CI, a base conflict, a deterministic linked-issue duplicate, a dual-model AI consensus defect). Added closeConcreteEvidence, round-tripped through the approval-queue staging path, and scoped downgradeCloseToHold to exempt it - a hard blocker now closes even while the breaker is engaged, matching every other deterministic close kind. - The self-tune breaker's auto-clear tick only reconsidered projects present in the current gate-eval report, but a project whose closes are 100% suppressed stops producing new decided samples for that action class and can drop out of the report entirely - stranding its flag engaged forever regardless of cooldown. Widened the auto-clear candidate set to the union of the eval report and every currently-engaged per-project flag. - The eval read across every review_audit source, including the frozen, no-longer-written 'reviewbot' source from before the gittensory-native convergence. A dead system's historical close predictions could permanently anchor a live repo's measured close precision. Scoped the tick to source='gittensory-native'. Also adds a bounded-cardinality gittensory_precision_breaker_downgrades_total counter so an engaged breaker is visible without querying review_audit directly.
…tric miscount Gate review (round 2) found two reachable defects in the prior commit: - ai_consensus_defect was wrongly classified as closeConcreteEvidence, letting a green PR with only an AI-derived blocker bypass the close-precision breaker it exists to check. Two independent models agreeing is still a judgment call, not deterministic evidence - removed it from CONCRETE_EVIDENCE_BLOCKER_CODES, and hardened hasConcreteCloseEvidence to also exclude anything in advisory.ts's own AI_JUDGMENT_BLOCKER_CODES so this can't silently regress again. - precisionBreakerDowngradeDirections detected a close downgrade by checking whether any close action remained in the post-breaker plan, so a plan with a kept deterministic close plus a dropped heuristic close recorded no downgrade. Switched to reference-identity survival checks (does this specific planned action still exist in the breaker's output), which correctly handles multiple close actions. Also reuses advisory.ts's/pre-merge-checks.ts's existing exported code constants for two of the nine concrete-evidence codes instead of retyping them, and adds a source-text parity test guarding the remaining seven against silent producer-side drift.
… fix npm run test:coverage (and CI's validate/validate-code) failed with "DUPLICATE_ONLY_BLOCKER_CODES is not iterable": agent-actions.ts sits inside a genuine module-load cycle (scoring/model.ts -> db/repositories.ts -> agent-actions.ts -> rules/advisory.ts -> scoring/preview.ts -> scoring/model.ts), and eagerly spreading another module's export into a top-level array literal reads it before that module has necessarily finished initializing on the cycle's first pass. Reverted the two CONCRETE_EVIDENCE_BLOCKER_CODES entries back to plain string literals and extended the parity test to cover all nine codes instead of seven. AI_JUDGMENT_BLOCKER_CODES stays imported - it is only read inside a function body, not at module-eval time, so it isn't exposed to the same hazard.
codecov/patch flagged src/queue/processors.ts's incr() call inside runAgentMaintenancePlanAndExecute as uncovered: precisionBreakerDowngradeDirections and applyPrecisionBreakers were already exercised as pure functions in precision-breakers-chain.test.ts, but nothing drove the LIVE integration path (a real webhook, a real engaged breaker, a real withheld mutation) through this exact call site. Added an end-to-end regression alongside the existing convergence-chain test, seeding a holdonly breaker flag before the CI-completion re-review step and asserting both the withheld merge and the resulting counter.
…dProjectScopes codecov/patch flagged an else-if arm as a partial branch: the query's own WHERE clause (key LIKE 'holdonly:%' OR 'closehold:%') guarantees prefix can only ever be "holdonly" or "closehold", so the second === check could never see any other value. Collapsed to a plain else -- same behavior, no unreachable branch left to cover.
…r, address gate nits The gate's deterministic secret scanner flagged reason: "leaked secret" / "secret leaked" test fixtures as a possible generic_secret_assignment hit - no real credential, just wording that matched the heuristic's shape. Reworded to "hard blocker", which the tests don't depend on semantically. Also addresses the round-3 review nits: - Added a dedicated regression test that forces agent-actions.ts and scoring/model.ts to load together in the same module graph, so a reintroduced eager cross-module read on the documented load cycle fails a test directly instead of only being caught incidentally by unrelated suites. - Tightened the CONCRETE_EVIDENCE_BLOCKER_CODES parity test to require the actual producer assignment shape (code: "..." or a SOME_CONST = "..." export) rather than the bare literal appearing anywhere in the file, which a stale comment could have satisfied. - Documented the maintenance path in listEngagedProjectScopes's plain else: if the WHERE clause ever grows a third prefix, it must go back to an explicit branch with its own test, not stay silently bucketed as closehold.
87a286b to
400e03d
Compare
…gression The deterministic secret scanner's generic_secret_assignment pattern matches any `token: "..."` (or api_key/secret/password/etc.) assignment whose value is 16+ characters and doesn't look like a known placeholder string. The new holdonly-breaker test's hand-rolled fetch stub used "installation-token" (18 chars, no placeholder markers) in an ADDED line, which the scanner flags regardless of the hundreds of pre-existing, unchanged occurrences of that same literal elsewhere in this file. Shortened to a value under the length threshold; the token's actual content was never asserted on.
Summary
system_flagson edge-us-01) showedclosehold:<repo>engaged for all three review-active repos since 2026-06-28 07:00:17, silently downgrading every heuristic close to a human hold — regardless ofautonomy.close=auto,agent_dry_run=0, and correct repo config. Investigated the full gate-to-action decision path (planAgentMaintenanceActions→applyPrecisionBreakers→executeAgentMaintenanceActions) and found three compounding, generic self-host engine bugs (no repo-specific logic anywhere in this diff):downgradeCloseToHolddowngraded everycloseKind: "heuristic"close identically, including ones backed by concrete, non-judgment evidence — a committed secret, red CI, a base conflict, or a deterministic linked-issue-overlap duplicate. AddedcloseConcreteEvidencetoPlannedAgentAction, round-tripped it through the approval-queue staging path (AgentPendingActionParams,actionParams), and scoped the breaker to exempt it — a hard blocker now closes even while the breaker is engaged, matching the existing exemption already given toblacklist/contributor_cap/review_nag/linked-issue-hard-rulecloses. Bothai_consensus_defect(a dual-model AI verdict) andai_review_splitstay fully subject to the breaker — the gate review (round 2) correctly flagged an earlier version of this diff for treating a dual-model AI consensus as "concrete": two models agreeing is still a judgment call, not deterministic evidence, and a systematically-wrong AI-driven close is exactly the failure mode this breaker exists to catch.hasConcreteCloseEvidencenow also defensively excludes anything in advisory.ts's ownAI_JUDGMENT_BLOCKER_CODES, so this can't silently regress again.runSelfTuneBreakeronly reconsidered projects present in the currentcomputeGateEvalreport, but a project whose closes are 100% suppressed stops producing new decided samples for that action class and can drop out of the report entirely — stranding its flag engaged forever, no matter how long the 24h cooldown has elapsed. Widened the auto-clear candidate set to the union of the eval report and every currently-engaged per-project flag (still never touches a human-set:globalflag).computeGateEvalread across everyreview_auditsource, including the frozen, no-longer-writtenreviewbotsource from before the gittensory-native convergence (verified on the VPS: 256 oldclosepredictions vs. zero fromgittensory-native, which only ever recordsmerge/holdfor its own gate check). A dead system's historical close predictions could permanently anchor a live repo's measured close precision, so it could never legitimately "recover." Scoped the tick tosource: 'gittensory-native'.gittensory_precision_breaker_downgrades_total{direction}counter (extracted as a pure, directly-testedprecisionBreakerDowngradeDirectionshelper) so an engaged breaker is visible without queryingreview_auditdirectly — no raw SHAs/PR numbers/free text.precisionBreakerDowngradeDirectionscompares each planned merge/close action's survival by reference identity (not "is any action of that class still present anywhere"), so a plan carrying both a kept deterministic close and a dropped heuristic close is still correctly counted as a close downgrade — another defect the round-2 gate review caught in the first version of this metric.last_regated_at/no current-head gate outcome) is already adequately covered by the existing hourly per-repo sweep plus the foreground-liveness/reconciliation-repair work already merged in fix(selfhost): keep review queue live and verify configured CI #2843/fix(queue): prioritize live PR work under GitHub rate pressure #2847 — no additional code needed there.CONCRETE_EVIDENCE_BLOCKER_CODESnow reuse advisory.ts's/pre-merge-checks.ts's existing exported constants (DUPLICATE_ONLY_BLOCKER_CODES,PRE_MERGE_CHECK_BLOCKING_CODE) instead of retyping the literal; the remaining seven have no single canonical export to import (each is either module-private or a literal duplicated across several unrelated producer files), so a new source-text parity test guards them against silent producer-side drift instead.Scope
src/settings/agent-actions.ts,src/types.ts,src/services/agent-action-executor.ts,src/review/outcomes-wire.ts,src/queue/processors.ts,src/selfhost/metrics.ts+ their test files onlyValidation
git diff --checknpm run typecheckagent-actions.test.ts,agent-action-executor.test.ts,outcomes-wire.test.ts,precision-breakers-chain.test.ts,agent-approval-queue.test.ts,auto-tune.test.ts— 415/415 passingnpm audit --audit-level=moderate— 0 vulnerabilitiesnpm run test:coverage(full unsharded) — not re-run locally beyond the directly-affected suite; CI runs the full gate unshardedIf any required check was skipped, explain why:
test:coverage/test:workers/UI checks were not re-run locally beyond the directly-affected suite, per this repo's own guidance that CI already runs the full gate unsharded.Safety
Notes
SELECTqueries againstsystem_flags/review_auditover the existing Tailscale SSH access) is not reproduced here — only the code fix and its reasoning.