feat(miner-governor): persist governor cross-attempt state (#5134) - #5203
Conversation
Every governor-*.js wrapper (governor-write-rate-limit.js, governor-chokepoint.js) is a pure in/out transform: it computes and returns updated rate-limit buckets/backoff attempts/cap usage but nothing writes them to disk, so they reset to zero on every process start. Adds governor-state.js (a real SQLite store, mirroring the package's local-store.js/claim-ledger.js conventions) holding rate-limit buckets/backoff, budget/turn/termination cap usage, per-repo reputation history, and own-submission history for self-plagiarism checks. governor-chokepoint-persisted.js composes this with the existing, UNMODIFIED evaluateGovernorChokepointGate (every prior caller/test of it is untouched) rather than changing that function directly, since this issue is flagged as the safety-critical core of its gap-fill batch and a wrapper is a smaller, more isolated surface to review. Convergence-history persistence is deliberately out of scope: it belongs on the portfolio-queue table per non-convergence.ts's own doc comment, not a new competing store. Closes #5134
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
gittensory-ui | f296936 | Commit Preview URL Branch Preview URL |
Jul 12 2026, 09:12 AM |
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5203 +/- ##
=======================================
Coverage 94.34% 94.34%
=======================================
Files 473 473
Lines 39963 39963
Branches 14569 14569
=======================================
Hits 37702 37702
Misses 1585 1585
Partials 676 676
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-12 09:26:23 UTC
⏸️ Suggested Action - Manual Review
Review summary Blockers
Nits — 6 non-blocking
Concerns raised — review before merging
Review context
Contributor next steps
Signal definitions
[BETA] Chat with GittensoryAsk Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands 🟩 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.
|
|
An AI reviewer flagged a likely defect, but its confidence was below this repository's configured close-confidence floor, so this is held for a maintainer to confirm instead of closing automatically. Resolve the flagged defect (see the review notes), or ask a maintainer to override. |
…rnor state (#5134) (#5214) #5203 added evaluateGovernorChokepointGatePersisted and governor- state.js, but attempt-runner.js -- the one real production caller -- still imported and called the old, non-persisting evaluateGovernorChokepointGate directly, so the reset-on-process- start bug #5134 was filed to fix was never actually fixed for the real pipeline, only the infrastructure to fix it existed. Switches the import/call to evaluateGovernorChokepointGatePersisted, adds an optional AttemptDeps.governorState field, and loosens AttemptGovernorContext's rateLimitBuckets/rateLimitBackoffAttempts/ capUsage to optional (via the new GovernorChokepointInputPersisted type) -- without that, callers would still be forced to hand-thread honest-but-stale zero defaults on every invocation, silently defeating the persistence an explicit input value always overrides. Flagged by the gittensory review gate on #5203 after it had already merged; recovered as this fresh PR since pushing to the merged branch would have orphaned the commit.
Summary
governor-*.jswrapper (governor-write-rate-limit.js,governor-chokepoint.js) is a pure in/out transform — it computes and returns updated rate-limit buckets/backoff attempts/cap usage but nothing writes them to disk, so the mutable counters that should gate the next decision reset to zero on every process start.governor-state.js: a real SQLite store (mirroringlocal-store.js/claim-ledger.js's existing conventions —GITTENSORY_MINER_GOVERNOR_STATE_DBenv var,~/.config/gittensory-miner/governor-state.sqlite3default, 0700/0600 permissions) holding rate-limit buckets + backoff attempts, budget/turn/termination cap usage, per-repo reputation history, and own-submission history (for self-plagiarism checks).governor-chokepoint-persisted.js:evaluateGovernorChokepointGatePersisted(input, options)composes this persistence with the existing, unmodifiedevaluateGovernorChokepointGate— loads rate-limit/backoff/capUsage before evaluating (unless the caller already supplied an explicit override), saves the returned mutated rate-limit state after.evaluateGovernorChokepointGateitself, and every one of its 25 existing tests, is untouched — kept as a separate composing wrapper rather than a behavior change to an already-relied-upon function, given this issue's own "needs its own dedicated review" flag.capUsageis loaded but deliberately not saved by this wrapper:budget-cap.ts'sGovernorCapUsagehas no mutator (unlike the rate-limit buckets), since only the caller knows how much an attempt actually spent — known after it runs, not at gate-check time. Saving the nextcapUsagestays the caller's job via the exportedsaveCapUsage.non-convergence.ts's own doc comment says its counters belong on theportfolio-queuetable (a pre-existing store), once that table grows attempt-history columns — inventing a second, competing store for the same concept here would violate the same non-duplication principle the ledger/state split (acceptance criterion 2) is built on. Reputation/self-plagiarism persistence primitives are built and tested (loadReputationHistory/saveReputationHistory/recordOwnSubmission/listRecentOwnSubmissions) but not yet auto-wired into the persisted gate the way rate-limit/cap-usage are — those are per-actionClass === "open_pr"-scoped optional fields onGovernorChokepointInputalready, and wiring them up is natural work for whoever builds the real attempt-lifecycle caller (Build the autonomous repeat/supervising loop (discover → attempt → manage → repeat) #5135) alongside constructing the rest of that input.Acceptance criteria (from #5134)
test/unit/miner-governor-chokepoint-persisted.test.ts's "ACCEPTANCE CRITERION" test opens a governor-state handle, runs one gate check, closes it, opens a brand new handle on the same on-disk file (simulating a fresh CLI process), and confirms the second invocation now denies.governor-ledger.js's audit trail remains the authoritative history log; this adds decision-input state, not a second history log.governor-ledger.jsis untouched.evaluateGovernorChokepoint's precedence ladder is unchanged. The engine's pure calculator and the miner-libevaluateGovernorChokepointGatewrapper are both untouched (25 existing tests for the latter still pass unmodified).Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run typechecknpm run test:coveragelocally (736 test files, 0 failures, 14,596 tests passed).packages/gittensory-miner/**is outside vitest'scoverage.includeglob (onlysrc/**+packages/gittensory-engine/src/**are collected), socodecov/patchcannot measure this diff — full unit coverage was still written as real correctness verification (44 new tests across the 2 new files, plus confirmed zero regression on the 25 existinggovernor-chokepoint.jstests).npm run build:miner+npm run test:miner-pack— also fixed a pre-existing gap found in the process:packages/gittensory-miner/package.json'sbuildscript'snode --checkfile list is hand-maintained, not generated from the directory, and was missing entries for new files (a separate follow-up fixes the same gap for the not-yet-merged Wire CLI dispatch for the real attempt pipeline (attempt command) #5132 PR).npx tsx scripts/check-engine-parity.tsnpm audit --audit-level=moderatenpm run test:workers/npm run build:mcp/npm run test:mcp-pack/npm run ui:*— skipped, nosrc/**,apps/**, or MCP-surface files touched.If any required check was skipped, explain why:
packages/gittensory-miner/**andtest/unit/*.ts.Safety
Notes
evaluateGovernorChokepointGatePersistedwrapper (rather than modifyingevaluateGovernorChokepointGateitself) is the right tradeoff, and whether the capUsage load-but-don't-save split is correctly reasoned givenGovernorCapUsagehas no mutator upstream.