feat(review): add a config-as-code content-lane deliverable gate - #7703
Merged
Conversation
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
loopover-ui | e8fe3bb | Commit Preview URL Branch Preview URL |
Jul 21 2026, 10:08 AM |
Registries with a "one entry file per contribution" content lane (e.g. an issue naming a specific path under a configured entryFileGlob) could have their linked issue auto-satisfied by a PR that never touches that path -- a test-only or unrelated-file PR closes the issue without delivering the content it asked for. Add checkContentLaneDeliverable(), a pure, spec-driven check: it scans the linked issue's text for a path token matching the resolved repo's RegistryLaneSpec and verifies the PR's changed files actually touch it. Wire it behind a new contentLaneDeliverableGateMode setting (off by default, advisory/block like every other gate dimension), fully wired through the DB, engine focus-manifest parser, OpenAPI schema, and .loopover.yml -- no repo-specific logic anywhere in the check itself, so any repo with a contentLane: config gets the same protection.
Contributor
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
JSONbored
force-pushed
the
claude/loopover-gittensory-orb-bugs-a63c52
branch
from
July 21, 2026 09:48
715afc2 to
60afcee
Compare
Bundle ReportChanges will increase total bundle size by 4.76kB (0.06%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: loopover-uiAssets Changed:
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #7703 +/- ##
==========================================
- Coverage 88.56% 88.56% -0.01%
==========================================
Files 725 725
Lines 76266 76299 +33
Branches 22705 22721 +16
==========================================
+ Hits 67544 67572 +28
- Misses 7680 7681 +1
- Partials 1042 1046 +4
Flags with carried forward coverage won't be shown. Click here to find out more.
|
…ngine twin packages/loopover-engine/src/advisory/gate-advisory.ts is a hand-duplicated twin of src/rules/advisory.ts (#4518's gate-decision twin pair), enforced by scripts/check-engine-parity.ts's version-skew check. The new contentLaneDeliverableGateMode field and its isConfiguredGateBlocker branch were added to the host copy but never mirrored to the engine copy, so self-hosters consuming @loopover/engine directly would silently lack the new gate dimension, and CI's engine-parity check correctly failed the PR.
… from the engine twin While mirroring contentLaneDeliverableGateMode into gate-advisory.ts, found that linkedIssueSatisfactionGateMode (#4069, merged 2026-07-07) was never mirrored either -- CI's engine-parity check only diffs against each PR's own changed files, so a prior PR that touched only the host twin without updating the engine twin (and without bumping packages/loopover-engine/package.json) went undetected. Any self-hoster consuming @loopover/engine's predicted-gate logic directly would silently never predict a linked_issue_scope_mismatch blocker for a repo with linkedIssueSatisfaction: block configured. Backfilled now while in the area.
This was referenced Jul 21, 2026
Closed
This was referenced Jul 23, 2026
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.
Summary
Investigated a reported gate bug: for repos with a "one entry file per contribution" content lane (a registry where each PR is expected to add/edit one entry file matching a configured
entryFileGlob), the gate's linked-issue satisfaction check only looks at CI-green + AI score + closing keywords -- it never checks whether the PR actually delivers the content the issue asked for. A PR that adds only a test file (or otherwise never touches the path the linked issue names) can still auto-merge and auto-close the issue, leaving the registry entry undelivered.Root cause: there was no deterministic check anywhere in the pipeline that cross-references a linked issue's text against the PR's actual changed files for content-lane repos specifically.
Fix: a new, fully generic, spec-driven check --
checkContentLaneDeliverable(spec, issueText, changedFiles)(src/review/content-lane/registry-logic.ts) -- pure function, no repo-specific logic. It extracts path-shaped tokens from the linked issue's title/body, matches them against the repo's resolvedRegistryLaneSpec(entry/provider/artifact patterns), and reports whether the PR's changed files touch the mentioned path.contentLaneDeliverableGateModesetting (off/advisory/block, off by default) -- the same three-state pattern every other gate dimension in this codebase already uses. Fully wired through the DB (migration + Drizzle schema), the engine's.loopover.ymlfocus-manifestparser/serializer, the OpenAPI schema,.loopover.yml.example/config/examples/loopover.full.yml, and the docs-drift manifest.contentLane:spec resolved (viaresolveRegistryLaneSpec) -- a repo with no content-lane config is always a no-op, so this adds zero behavior for the vast majority of repos LoopOver reviews.A second, related report (a content-free "Registry surface review" hard-blocker rejecting PRs that correctly fill in previously-missing fields on existing entries) was investigated separately and traced to the same root cause already fixed and merged in #7670 (an in-place edit was being misread as a duplicate resubmission). No further code change was needed for that one; it's most likely still being observed live due to self-hosted deployment lag on the versioned Docker image.
Also fixed along the way (2 follow-up commits, caught by CI):
packages/loopover-engine/src/advisory/gate-advisory.tsis a hand-duplicated "twin" ofsrc/rules/advisory.ts(the gate-decision logic), enforced byscripts/check-engine-parity.ts's version-skew check. My newcontentLaneDeliverableGateModebranch only landed on the host copy at first -- CI correctly failed on the resulting skew. Mirrored it into the engine twin.linkedIssueSatisfactionGateMode(feat(review): wire linked-issue satisfaction into the deterministic gate #4069, merged 2026-07-07) was also never mirrored into the engine twin, and has been silently drifted for two weeks -- CI's engine-parity check only diffs against each PR's own changed files, so a PR that touches only one twin without updating the other (and without bumping the engine package version) goes undetected once merged. Any self-hoster consuming@loopover/engine's predicted-gate logic directly would silently never predict alinked_issue_scope_mismatchblocker for a repo withlinkedIssueSatisfaction: blockconfigured. Backfilled it while already looking at this file.Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run db:migrations:check,npm run db:schema-drift:checknpm run cf-typegen:checknpm run docs:drift-check,npm run manifest:drift-check,npm run engine-parity:drift-checknpx tsc --noEmit -p tsconfig.json-- cleannpm audit --audit-level=moderate-- 0 vulnerabilitiestest/unit/check-engine-parity-script.test.ts(38 tests),test/contract/engine-parity.test.ts(14 tests),npm run test --workspace @loopover/engine(5 tests) -- all passing after the twin-mirroring fixes.npm run test:coverage-- not obtained clean this round: two unrelated test files (miner-repo-clone.test.ts,agent-sdk-driver.test.ts, both doing real git subprocess work) failed only under heavy concurrent load from multiple simultaneous full-suite runs on this machine, and passed cleanly every time re-run in isolation; a third, pre-existing failure inminer-cross-repo-evaluation.test.tsis unrelated to this diff (from feat(miner): add a dry-run full-execution mode to the cross-repo evaluation harness #7668, already flagged separately). Codecov's owncodecov/patchcheck will independently verify patch coverage in CI.Safety
npm run ui:openapiregenerated).UI Evidencesection -- N/A, no UI changes..loopover.yml.example+ its byte-matchedconfig/examples/loopover.full.ymlsibling, plus real doc-page mentions inhow-reviews-work.mdx/tuning.mdx/github-app.mdx); changelog itself intentionally not touched.Notes
contentLaneDeliverableGateModeis opt-in and defaults toofffor every repo -- zero behavior change anywhere until a repo's.loopover.yml(or dashboard/API settings) explicitly sets it. Nothing in the check itself is specific to any one repo or registry; any repo with acontentLane:spec gets the same protection. Activating it for any specific repo is a private server-config change, not something this PR does.The two engine-twin-parity fixes are pure backfills of already-shipped host behavior into the engine package copy -- no new gate behavior, no host-side change, just closing a silent drift gap so
@loopover/engineconsumers see the same gate predictions the live host does.