Skip to content

feat(miner): track real per-issue attempt-history on the portfolio queue for the Governor - #5662

Closed
lourincedaging0-commits wants to merge 1 commit into
JSONbored:mainfrom
lourincedaging0-commits:feat-portfolio-attempt-history
Closed

feat(miner): track real per-issue attempt-history on the portfolio queue for the Governor#5662
lourincedaging0-commits wants to merge 1 commit into
JSONbored:mainfrom
lourincedaging0-commits:feat-portfolio-attempt-history

Conversation

@lourincedaging0-commits

Copy link
Copy Markdown
Contributor

Closes #5654.

Problem

buildAttemptGovernorContext (attempt-input-builder.js) hardcoded convergenceInput to a first-attempt literal { attempts: 0, consecutiveFailures: 0, reenqueues: 0, reachedDone: false } because miner_portfolio_queue tracked no attempt history. So the Governor's non-convergence detector (packages/gittensory-engine/src/portfolio/non-convergence.ts, fully built + tested since Wave 3) was never fed real data — it always read "fresh" and had never actually detected a stuck/looping item.

Change

  • Schema (portfolio-queue.js): additive attempts / consecutive_failures / reenqueues columns via a defensive per-column migration (mirrors the existing leased_at migration idiom; NOT NULL DEFAULT 0, so every pre-existing row reads "fresh").
  • Counters: +1 attempts on every claim (dequeueNext, batchClaim); +1 reenqueues and +1 consecutive_failures on every in_progress -> queued transition that never reached done (markFailed and the stuck-lease reclaim sweep — exactly non-convergence.ts's reenqueue trigger); consecutive_failures reset to 0 on markDone (lifetime attempts/reenqueues survive). requeueItem (a completed done row re-run) is deliberately excluded — it reached done, so it is not a stuck loop.
  • Read: getAttemptHistory(...) returns a real PortfolioConvergenceInput; reachedDone is strictly status === 'done', never fabricated.
  • Wiring: the queue-driven caller (loop-cli) reads it and threads it through runMinerAttempt into buildAttemptGovernorContext, which stays pure and just forwards it (a one-off direct attempt has none → fails open to a fresh item). non-convergence.ts's classifier and thresholds are untouched.
  • Hand-written .d.ts for both portfolio-queue and attempt-input-builder updated to match.

Validation

New suite test/unit/miner-portfolio-queue-attempt-history.test.ts, covering every changed line/branch:

  • Migration — a pre-existing on-disk store missing the columns gains them (old rows read fresh-zero); a store already carrying them is not re-altered (defensive branch), and its values survive.
  • Counters — full claim -> markFailed -> ... -> markDone sequences; batch-claim attempt; reclaim sweep; the requeueItem exclusion; unknown-item fresh read.
  • InvariantreachedDone only ever reflects a real 'done' status across queued/in_progress/done.
  • Regression — a repeatedly re-enqueued item that never reaches done now produces a PortfolioConvergenceInput that classifyPortfolioConvergence classifies non_convergent — the detector's first real exercise — while a single fresh attempt still reads converging.
  • BuilderbuildAttemptGovernorContext forwards a real convergenceInput and defaults to a fresh literal when omitted.

…eue for the Governor

buildAttemptGovernorContext hardcoded convergenceInput to a first-attempt literal because the
portfolio-queue table tracked no attempt history -- so the non-convergence detector (built since
Wave 3) never saw real data and always read 'fresh'. Grow miner_portfolio_queue with additive
attempts / consecutive_failures / reenqueues columns (defensive per-column migration, mirroring
the leased_at idiom); count an attempt on every claim, a re-enqueue + consecutive failure on every
in_progress->queued transition that never reached done (markFailed and the stuck-lease reclaim
sweep), and reset the consecutive streak on markDone. Add getAttemptHistory returning a real
PortfolioConvergenceInput, and thread it from the queue-driven caller (loop-cli) through
runMinerAttempt into buildAttemptGovernorContext, which stays pure and just forwards it (a one-off
direct attempt has none, so it fails open to a fresh item). non-convergence.ts's classifier and
thresholds are untouched.

Closes JSONbored#5654
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@lourincedaging0-commits

Copy link
Copy Markdown
Contributor Author

Closing — #5654 was merged by #5661 while this was in progress; this duplicates already-landed work.

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Track real per-issue attempt-history on the portfolio queue, feed the Governor's convergenceInput

1 participant