docs(readme): reframe intro around two-sided autonomy and the accountability layer#9117
Merged
Merged
Conversation
Contributor
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
loopover-ui | 85ed584 | Commit Preview URL Branch Preview URL |
Jul 27 2026, 01:55 AM |
…hosted loops in development
Bundle ReportChanges will increase total bundle size by 467 bytes (0.01%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: loopover-uiAssets Changed:
|
❌ 1 Tests Failed:
View the top 1 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
This was referenced Jul 27, 2026
JSONbored
added a commit
that referenced
this pull request
Jul 27, 2026
…repair scans for state a crash used to lose Four ways a badly-timed process death left permanent damage. #9007 made this urgent rather than theoretical: busy deploys currently end in SIGKILL, so "killed at the wrong moment" is the normal case, not the rare one. On Postgres the queue is deliberately multi-instance (that is what the FOR UPDATE SKIP LOCKED claim is for), so "every processing row" is not "my crashed predecessor's work" — during any overlapped or rolling deploy it also includes jobs a SIBLING is running right now. Both processes then ran the same PR pass concurrently, producing duplicate gate check-runs and verdict thrash. Recovery is now scoped to rows whose lease has actually expired, the same definition the runtime reaper already uses, so boot and steady-state stop disagreeing about what "abandoned" means, and the re-pend is a compare-and-swap so a sibling finishing first cannot be resurrected. Two related holes in the same file. The lease is now heartbeated by the worker that holds it: without that, the timeout was a ceiling on job DURATION rather than on liveness, so a legitimately long pass — a large PR, a slow AI review, a rate-limited GitHub window — was reclaimed and double-run purely for taking too long, and the activeJobIds guard meant to prevent that only covers one process's in-memory set, which is the wrong scope for a shared queue. And a reclaim now costs an attempt: it never did, so a job that reliably wedges past its lease was requeued forever with attempts frozen, never reaching the dead-letter threshold that exists precisely to stop a poison job from burning the queue. Statements ran individually and the file was recorded applied only after the last one succeeded, so a crash mid-file re-ran the WHOLE file next boot. Harmless for pure DDL and destructive for the several migrations carrying real DML — the table-rebuild INSERT ... SELECT pattern, plus UPDATE/DELETE steps — where a re-run either double-inserts or raises a PK conflict that, not matching the tolerated "already exists" shape, throws and bricks boot outright. Each file now runs as one transaction with its ledger row committed inside it, via a new execTransaction on both self-host adapters. It could not reuse exec: on Postgres each exec call takes whatever connection the pool hands out, so a BEGIN and its COMMIT issued as separate calls can land on different connections and mean nothing. The pre-existing drift tolerance is preserved rather than replaced — a database that already drifted must still heal itself instead of failing to boot, and that only works per-statement. But ONLY drift falls back. Any other failure rethrows with the transaction already rolled back, because retrying a genuinely broken file per-statement would re-apply its valid statements after the rollback and leave exactly the partial state this fix exists to prevent. pr_outcome is what the fleet calibration export INNER JOINs gate_decision against, so a PR missing one does not lose a data point, it vanishes from calibration entirely — neither numerator nor denominator. Both writers are in-process and best-effort: a process that dies between the GitHub mutation and the record call loses the direct write, and on the next pass the PR is already terminal so the planner plans nothing and it never fires; the webhook that would have caught it was delivered while the container was down and GitHub does not redeliver. Nothing scanned for the gap — the repair sweep only visits OPEN PRs. These losses are not a random sample: a superseded close is by definition a wrong close, so they skew toward the gate's mistakes and their absence biased published accuracy upward. Pass 1 of the flag-then-close double-check enqueues a single delayed job to run Pass 2, and that message was the only thing that could finish the sequence. Its documented "next sweep / CI event" backstop is vacuous: #never-endless-reregate makes an already-regated PR permanently sweep-ineligible while the flag itself suppresses merge and approve, and the violation memory is permanent so the flag could never clear either. Pass 1 now also records the deadline, and a watchdog re-enqueues Pass 2 for any flag past it. audit_events is the right store: durable, already queried by type, and repo-agnostic — unlike the label, which is per-repo configurable and would need settings resolution before a cross-repo scan could even recognize it. Both repair scans ride the re-gate sweep's existing fan-out tick rather than each earning a job type and a cron entry for a bounded DB scan, and run before the fan-out so neither can cost the tick its actual work. Also fixes main: test/unit/docs-beta-onboarding.test.ts asserted the doc still says "base-agent", which #9117 intentionally retired when it repositioned the product away from "a deterministic base-agent for the Gittensor ecosystem" toward an agent stack for both sides of the pull request on any GitHub repo. The guard exists to stop LoopOver claiming to BE the official Gittensor frontend, and its other four assertions cover that on their own; pinning the retired wording only made it veto an intended product change. Local gate green end to end (npm run test:ci, exit 0). 100% line and branch coverage on all 210 added src lines. Closes #9023 Closes #9026 Closes #9027 Closes #9031
JSONbored
added a commit
that referenced
this pull request
Jul 27, 2026
…repair scans for state a crash used to lose (#9144) Four ways a badly-timed process death left permanent damage. #9007 made this urgent rather than theoretical: busy deploys currently end in SIGKILL, so "killed at the wrong moment" is the normal case, not the rare one. On Postgres the queue is deliberately multi-instance (that is what the FOR UPDATE SKIP LOCKED claim is for), so "every processing row" is not "my crashed predecessor's work" — during any overlapped or rolling deploy it also includes jobs a SIBLING is running right now. Both processes then ran the same PR pass concurrently, producing duplicate gate check-runs and verdict thrash. Recovery is now scoped to rows whose lease has actually expired, the same definition the runtime reaper already uses, so boot and steady-state stop disagreeing about what "abandoned" means, and the re-pend is a compare-and-swap so a sibling finishing first cannot be resurrected. Two related holes in the same file. The lease is now heartbeated by the worker that holds it: without that, the timeout was a ceiling on job DURATION rather than on liveness, so a legitimately long pass — a large PR, a slow AI review, a rate-limited GitHub window — was reclaimed and double-run purely for taking too long, and the activeJobIds guard meant to prevent that only covers one process's in-memory set, which is the wrong scope for a shared queue. And a reclaim now costs an attempt: it never did, so a job that reliably wedges past its lease was requeued forever with attempts frozen, never reaching the dead-letter threshold that exists precisely to stop a poison job from burning the queue. Statements ran individually and the file was recorded applied only after the last one succeeded, so a crash mid-file re-ran the WHOLE file next boot. Harmless for pure DDL and destructive for the several migrations carrying real DML — the table-rebuild INSERT ... SELECT pattern, plus UPDATE/DELETE steps — where a re-run either double-inserts or raises a PK conflict that, not matching the tolerated "already exists" shape, throws and bricks boot outright. Each file now runs as one transaction with its ledger row committed inside it, via a new execTransaction on both self-host adapters. It could not reuse exec: on Postgres each exec call takes whatever connection the pool hands out, so a BEGIN and its COMMIT issued as separate calls can land on different connections and mean nothing. The pre-existing drift tolerance is preserved rather than replaced — a database that already drifted must still heal itself instead of failing to boot, and that only works per-statement. But ONLY drift falls back. Any other failure rethrows with the transaction already rolled back, because retrying a genuinely broken file per-statement would re-apply its valid statements after the rollback and leave exactly the partial state this fix exists to prevent. pr_outcome is what the fleet calibration export INNER JOINs gate_decision against, so a PR missing one does not lose a data point, it vanishes from calibration entirely — neither numerator nor denominator. Both writers are in-process and best-effort: a process that dies between the GitHub mutation and the record call loses the direct write, and on the next pass the PR is already terminal so the planner plans nothing and it never fires; the webhook that would have caught it was delivered while the container was down and GitHub does not redeliver. Nothing scanned for the gap — the repair sweep only visits OPEN PRs. These losses are not a random sample: a superseded close is by definition a wrong close, so they skew toward the gate's mistakes and their absence biased published accuracy upward. Pass 1 of the flag-then-close double-check enqueues a single delayed job to run Pass 2, and that message was the only thing that could finish the sequence. Its documented "next sweep / CI event" backstop is vacuous: #never-endless-reregate makes an already-regated PR permanently sweep-ineligible while the flag itself suppresses merge and approve, and the violation memory is permanent so the flag could never clear either. Pass 1 now also records the deadline, and a watchdog re-enqueues Pass 2 for any flag past it. audit_events is the right store: durable, already queried by type, and repo-agnostic — unlike the label, which is per-repo configurable and would need settings resolution before a cross-repo scan could even recognize it. Both repair scans ride the re-gate sweep's existing fan-out tick rather than each earning a job type and a cron entry for a bounded DB scan, and run before the fan-out so neither can cost the tick its actual work. Also fixes main: test/unit/docs-beta-onboarding.test.ts asserted the doc still says "base-agent", which #9117 intentionally retired when it repositioned the product away from "a deterministic base-agent for the Gittensor ecosystem" toward an agent stack for both sides of the pull request on any GitHub repo. The guard exists to stop LoopOver claiming to BE the official Gittensor frontend, and its other four assertions cover that on their own; pinning the retired wording only made it veto an intended product change. Local gate green end to end (npm run test:ci, exit 0). 100% line and branch coverage on all 210 added src lines. Closes #9023 Closes #9026 Closes #9027 Closes #9031
JSONbored
added a commit
that referenced
this pull request
Jul 27, 2026
…ors, and stop judging a fix you cannot see (#9145) Three ways the AI reviewer acted confidently on input it had silently altered, truncated, or should never have trusted in the first place. #9035 — attacker-controlled text reached the prompt with no structural defense. Title, body and diff were concatenated straight in. "Judge ONLY the diff" tells the model what to look at; it never says that what it is looking at is DATA. The only defense was regex defang, which is deliberately narrow and which paraphrase or encoding walks past — and the same text reaches BOTH consensus reviewers, so a successful steer suppresses both and never even trips the single-rejection ai_review_split rule that exists to catch one reviewer being wrong. Each untrusted region is now fenced, with a system rule saying content between the markers is data and cannot change the rules, the output format, or the verdict. Forged markers are stripped from inside the region so a body cannot close its own fence early — without that, fencing would be worse than none. And a DETECTED attempt now holds the PR for a human. Defang recorded these and, by design, never let them affect the disposition, so a caught attacker got a normal roll. Manipulation aimed at the reviewer is evidence of intent, and the one thing it must not buy is an automated decision. Held, never closed: the detector is a regex running over a repository whose own subject matter is AI review, so a false positive is entirely possible, and a hold costs a contributor a wait where a close would cost them their PR. It reuses the existing ai_review_inconclusive hold path, so no gate-decision twin changes. #9076 — the defang shifted every inline anchor after it. The injection patterns' `[^.]{0,N}` gaps deliberately span newlines, so one match can swallow two or three diff lines including their `+`/`-` markers and even an `@@` header. Replacing all of that with a single-line literal collapsed those newlines. The reviewer counts a finding's line over the DEFANGED text, but the finding is validated and posted against the ORIGINAL patch — so every anchor after a multi-line redaction shifted, and a shifted anchor that still landed inside the commentable set passed validation and posted publicly on the wrong line of a contributor's PR. The redaction now re-emits one newline per newline consumed, so the two coordinate systems stay congruent. Two more on the same surface. Blocker-severity findings now anchor to ADDED lines only: rightSideLinesFromPatch admits unchanged context too, while the prompt asks for an added line and warns that a wrong line is worse than none — set membership was the only check, and context satisfies it, so a model miscounting by one to three lines landed on context and posted. That file conflated two different properties throughout: "GitHub will accept this anchor" and "this anchor is correct". Nits still allow context, because a misplaced nit is noise while a misplaced blocker costs someone their PR. And an empty patch line now counts as the context line it is instead of desynchronizing every later line number in the file (the trailing split artifact of a patch ending in a newline is dropped first, so the two cases stay distinct). #9075 — a confident "you didn't fix the issue" computed from a window that never contained the fix. linked-issue-satisfaction's own header claims "NO gate wiring, NO disposition change… advisory-only either way". That is stale: under linkedIssueSatisfactionGateMode: "block" an `unaddressed` verdict pushes a critical-path finding reading "this PR does not appear to satisfy its linked issue's scope." Meanwhile the module re-slices the already-truncated diff to 60k under the header "Unified diff (truncated if large):" — a hedge, not a fact, which leaves the model to guess whether it is seeing everything. A PR whose fix sits in a dropped hunk, a filtered file, or past character 60,000 got that public verdict anyway. The confidence floor does not help: it guards against a model being unsure, not against a model being sure about the wrong input. The header now states the fact, and an `unaddressed` verdict over a known-truncated diff degrades to `partial`. Only `unaddressed` — "addressed" over a truncated diff is the model finding POSITIVE evidence, which truncation cannot manufacture. Same reasoning #8961 already applies to truncated PR bodies. POLICY REVERSAL, called out explicitly. selectContextSectionsWithinBudget's `break` was pinned by a test asserting it is "a hard priority cutoff, not a bin-packing optimization". That reasoning holds for sections that are genuinely model context. It does not hold for what actually sat at the bottom of the list: testEvidence is ~200 characters and is not context at all but a deterministic classifier FACT ("this PR changes no test paths"), so one large RAG block silently discarded it on exactly the large PRs where it matters most, with no marker anywhere. An oversized section is now skipped rather than ending the loop. Priority order still decides who gets first refusal on the budget; every included section still genuinely fits. Both tests encoding the old rule are inverted with the reasoning in place. Also fixes main, same one-line change as #9144 (identical, so the two merge cleanly): docs-beta-onboarding asserted the doc still says "base-agent", which #9117 intentionally retired when it repositioned the product. Local gate green end to end (npm run test:ci, exit 0). 100% line and branch coverage on all 317 added src lines. Closes #9035 Closes #9075 Closes #9076
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the stale "deterministic control plane" opening — that described the original project scope. The intro now leads with what LoopOver actually is today: the autonomous maintainer review agent, the miner stack (MCP copilot + autonomous miner runtime), and the outcome-scored accountability layer (fairness report, certified close-precision guarantee, replayable backtest corpus). Also drops "autonomous PR agent" from the it-is-not list, since the miner runtime is exactly that now.
Paired with (already applied directly): updated GitHub repo description and topics.