diff --git a/README.md b/README.md index 9dfc632353..780cffe324 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,8 @@ LoopOver CI and LoopOver review score, gate, and comment on pull requests. The r **Check-run and comment surfaces, disambiguated** (a common point of confusion — these are three independent, separately-configured things, not layers of the same feature): -- **`Gittensory Orb Review Agent`** (`gate.*` / `settings.reviewCheckMode`, off by default) — the authoritative GitHub Check Run carrying the gate's pass/fail verdict. This is the one worth making a required status check. -- **`Gittensory Context`** (`settings.checkRunMode` / `settings.checkRunDetailLevel`, off by default) — a separate, purely advisory Check Run. At its default `checkRunDetailLevel: minimal` it publishes no findings at all; even at `standard`/`deep` it only re-renders content already shown elsewhere. Never make this one required. +- **`LoopOver Orb Review Agent`** (`gate.*` / `settings.reviewCheckMode`, off by default) — the authoritative GitHub Check Run carrying the gate's pass/fail verdict. This is the one worth making a required status check. +- **`LoopOver Context`** (`settings.checkRunMode` / `settings.checkRunDetailLevel`, off by default) — a separate, purely advisory Check Run. At its default `checkRunDetailLevel: minimal` it publishes no findings at all; even at `standard`/`deep` it only re-renders content already shown elsewhere. Never make this one required. - **Inline review comments** (`GITTENSORY_REVIEW_INLINE_COMMENTS` + `.gittensory.yml`'s `review.inline_comments`, off by both by default) — real, reply-able line-anchored PR review comment threads (CodeRabbit-style). This is the ONLY one of the three that posts an interactive per-line thread; the two check runs above never do. With `.gittensory.yml`'s `review.suggestions` also on, a precise line-anchored fix is additionally rendered as a one-click, committable GitHub suggested-change block. With `review.finding_categories` also on (off by default), each finding is additionally tagged with a category — security/correctness/performance/maintainability/tests/style — in both the inline comment label and the unified comment's "Finding categories" collapsible; a deterministic path/keyword fallback covers whatever the model omits. See [Tuning your reviews](https://gittensory.aethereal.dev/docs/tuning) for the full flag, setting, and `.gittensory.yml` reference. diff --git a/apps/gittensory-ui/public/openapi.json b/apps/gittensory-ui/public/openapi.json index 52dc9dd651..3460e0f059 100644 --- a/apps/gittensory-ui/public/openapi.json +++ b/apps/gittensory-ui/public/openapi.json @@ -3838,7 +3838,7 @@ "comment_only", "label_only" ], - "description": "Governs ONLY the PR comment and label -- never the Gittensory Context check (checkRunMode) or the Gittensory Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run." + "description": "Governs ONLY the PR comment and label -- never the LoopOver Context check (checkRunMode) or the LoopOver Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run." }, "commentMode": { "type": "string", @@ -9199,7 +9199,7 @@ "comment_only", "label_only" ], - "description": "Governs ONLY the PR comment and label -- never the Gittensory Context check (checkRunMode) or the Gittensory Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run." + "description": "Governs ONLY the PR comment and label -- never the LoopOver Context check (checkRunMode) or the LoopOver Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run." }, "includeMaintainerAuthors": { "type": "boolean" @@ -9704,7 +9704,7 @@ "comment_only", "label_only" ], - "description": "Governs ONLY the PR comment and label -- never the Gittensory Context check (checkRunMode) or the Gittensory Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run." + "description": "Governs ONLY the PR comment and label -- never the LoopOver Context check (checkRunMode) or the LoopOver Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run." }, "commentMode": { "type": "string", @@ -10111,7 +10111,7 @@ "comment_only", "label_only" ], - "description": "Governs ONLY the PR comment and label -- never the Gittensory Context check (checkRunMode) or the Gittensory Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run." + "description": "Governs ONLY the PR comment and label -- never the LoopOver Context check (checkRunMode) or the LoopOver Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run." }, "commentMode": { "type": "string", diff --git a/packages/gittensory-engine/src/advisory/gate-advisory.ts b/packages/gittensory-engine/src/advisory/gate-advisory.ts index 62fd986eae..2dfda8c334 100644 --- a/packages/gittensory-engine/src/advisory/gate-advisory.ts +++ b/packages/gittensory-engine/src/advisory/gate-advisory.ts @@ -13,7 +13,7 @@ import type { CollisionReport } from "../types/predicted-gate-types.js"; import { isDuplicateClusterWinnerByClaim } from "../signals/duplicate-winner.js"; import type { GuardrailPathMatch } from "../signals/change-guardrail.js"; import { nowIso } from "../utils/json.js"; -import { GITTENSORY_GATE_CHECK_NAME } from "../review/check-names.js"; +import { LOOPOVER_GATE_CHECK_NAME } from "../review/check-names.js"; import { CLA_CHECK_UNRESOLVED_CODE, CLA_CONSENT_MISSING_CODE } from "../review/cla-check.js"; import { REVIEW_THREAD_BLOCKER_CODE } from "../review/review-thread-findings.js"; import { labelMatchesPattern } from "../scoring/label-match.js"; @@ -338,7 +338,7 @@ function advisory( ): Advisory { const severity = highestSeverity(findings); const conclusion = conclusionForSeverity(severity, findings); - const title = conclusion === "success" ? "Gittensory advisory passed" : "Gittensory advisory available"; + const title = conclusion === "success" ? "LoopOver advisory passed" : "LoopOver advisory available"; return { id: randomUUID(), targetType, @@ -441,8 +441,8 @@ function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy return { enabled: true, conclusion: "neutral", - title: `${GITTENSORY_GATE_CHECK_NAME} — not evaluated yet`, - summary: "Gittensory has not finished syncing this repo/PR. The gate stays advisory and re-evaluates automatically; no action is needed.", + title: `${LOOPOVER_GATE_CHECK_NAME} — not evaluated yet`, + summary: "LoopOver has not finished syncing this repo/PR. The gate stays advisory and re-evaluates automatically; no action is needed.", blockers: [], warnings, }; @@ -472,7 +472,7 @@ function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy return { enabled: true, conclusion: "neutral", - title: `${GITTENSORY_GATE_CHECK_NAME} — held for human review`, + title: `${LOOPOVER_GATE_CHECK_NAME} — held for human review`, summary: "The AI review could not be completed for this change, so the gate is held for a human reviewer rather than passed automatically. It re-evaluates on the next update.", blockers: [], warnings: gateWarnings, @@ -490,7 +490,7 @@ function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy return { enabled: true, conclusion: "neutral", - title: `${GITTENSORY_GATE_CHECK_NAME} — held for manual review`, + title: `${LOOPOVER_GATE_CHECK_NAME} — held for manual review`, summary: holds.map((h) => sanitizeForCheckRun(h.title)).join("; "), blockers: [], warnings: [...gateWarnings, ...holds], @@ -499,7 +499,7 @@ function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy return { enabled: true, conclusion: "success", - title: `${GITTENSORY_GATE_CHECK_NAME} passed`, + title: `${LOOPOVER_GATE_CHECK_NAME} passed`, summary: "No configured hard blocker was found. Advisory findings, if any, stay advisory.", blockers, warnings: gateWarnings, @@ -511,7 +511,7 @@ function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy return { enabled: true, conclusion: "failure", - title: `${GITTENSORY_GATE_CHECK_NAME}: ${titleDetail}`, + title: `${LOOPOVER_GATE_CHECK_NAME}: ${titleDetail}`, summary: blockers .map((finding) => `${sanitizeForCheckRun(finding.title)}${finding.action ? ` — ${sanitizeForCheckRun(finding.action)}` : ""}`) .join("; "), diff --git a/packages/gittensory-engine/src/focus-manifest.ts b/packages/gittensory-engine/src/focus-manifest.ts index 2aeb0c5728..90f672ac22 100644 --- a/packages/gittensory-engine/src/focus-manifest.ts +++ b/packages/gittensory-engine/src/focus-manifest.ts @@ -70,14 +70,14 @@ export type FocusManifestIssueDiscoveryPolicy = "encouraged" | "neutral" | "disc * only chooses which deterministic blockers are active, never who can be blocked. There is no single * gate master switch: each per-dimension mode (`linkedIssue`, `duplicates`, `readinessMode`, etc.) * independently controls whether that dimension evaluates. `checkMode`/`enabled` (#2852) is a separate - * axis entirely: whether/how the "Gittensory Orb Review Agent" check-RUN publishes, independent of gate + * axis entirely: whether/how the "LoopOver Orb Review Agent" check-RUN publishes, independent of gate * evaluation itself (which always runs regardless of `checkMode`/`enabled`) — see {@link ReviewCheckMode}. */ export type FocusManifestGateConfig = { present: boolean; /** `gate.enabled` (legacy): a boolean shorthand for `checkMode` below -- `true` maps to `"required"`, * `false` maps to `"disabled"` (see resolveEffectiveSettings/applyGateConfigOverrides). Despite the name, - * this controls ONLY whether the "Gittensory Orb Review Agent" check-run publishes -- it has NO effect on + * this controls ONLY whether the "LoopOver Orb Review Agent" check-run publishes -- it has NO effect on * gate evaluation, disposition, comments, labels, audit, spend, or autonomous merge/close, all of which run * identically regardless of this field. It also cannot express `checkMode`'s third state (`"visible"`), and * is silently ignored once `checkMode` is set (see the parse-time warning a few lines below this type). @@ -1373,7 +1373,7 @@ function parseGateConfig(value: JsonValue | undefined, warnings: string[]): Focu if (gate.firstTimeContributorGrace === true) { warnings.push(`Manifest field "gate.firstTimeContributorGrace" is currently reserved/inert — it does not soften a blocker outcome for first-time contributors.`); } - // gate.enabled only controls whether the "Gittensory Orb Review Agent" check-run publishes (the legacy + // gate.enabled only controls whether the "LoopOver Orb Review Agent" check-run publishes (the legacy // enabled -> reviewCheckMode alias in applyGateConfigOverrides) -- it does NOT gate spend, merge, comment, // label, or close behavior, and it cannot express checkMode's "visible" state. checkMode always wins when // both are set, so once an operator sets checkMode, a lingering enabled becomes pure inert noise they have @@ -1383,7 +1383,7 @@ function parseGateConfig(value: JsonValue | undefined, warnings: string[]): Focu // side effect instead, twice). if (gate.enabled !== null && gate.checkMode === null) { warnings.push( - `Manifest field "gate.enabled" only controls whether the Gittensory Orb Review Agent check-run publishes — it does not gate spend, merge, comment, label, or close behavior, and it cannot express reviewCheckMode's "visible" state. Set "gate.checkMode" (required/visible/disabled) explicitly instead of "gate.enabled".`, + `Manifest field "gate.enabled" only controls whether the LoopOver Orb Review Agent check-run publishes — it does not gate spend, merge, comment, label, or close behavior, and it cannot express reviewCheckMode's "visible" state. Set "gate.checkMode" (required/visible/disabled) explicitly instead of "gate.enabled".`, ); } gate.present = diff --git a/packages/gittensory-engine/src/review/check-names.ts b/packages/gittensory-engine/src/review/check-names.ts index c2054e4e14..e7eee08c41 100644 --- a/packages/gittensory-engine/src/review/check-names.ts +++ b/packages/gittensory-engine/src/review/check-names.ts @@ -1 +1 @@ -export const GITTENSORY_GATE_CHECK_NAME = "Gittensory Orb Review Agent"; +export const LOOPOVER_GATE_CHECK_NAME = "LoopOver Orb Review Agent"; diff --git a/packages/gittensory-engine/src/types/manifest-deps-types.ts b/packages/gittensory-engine/src/types/manifest-deps-types.ts index 8f0749e288..6fb9e70d24 100644 --- a/packages/gittensory-engine/src/types/manifest-deps-types.ts +++ b/packages/gittensory-engine/src/types/manifest-deps-types.ts @@ -163,7 +163,7 @@ export type RepositorySettings = { * Selection-time only — real-time webhook-driven review is not gated by this and can process any PR at * any time regardless of the chosen order. */ regateSweepOrderMode: "staleness" | "oldest-first"; - /** The actual runtime authority for whether the "Gittensory Orb Review Agent" check-run publishes (#2852). + /** The actual runtime authority for whether the "LoopOver Orb Review Agent" check-run publishes (#2852). * See {@link ReviewCheckMode}. */ reviewCheckMode: ReviewCheckMode; /** Auto-project/milestone matching (#3183). See {@link ProjectMilestoneMatchMode}. Always populated by the DB diff --git a/src/github/app.ts b/src/github/app.ts index 6460989ccd..fd99d509a6 100644 --- a/src/github/app.ts +++ b/src/github/app.ts @@ -28,15 +28,17 @@ import { type GateCheckPolicy, } from "../rules/advisory"; import { - GITTENSORY_CONTEXT_CHECK_NAME, - GITTENSORY_GATE_CHECK_NAME, GITTENSORY_LEGACY_GATE_CHECK_NAME, + GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME, + LOOPOVER_CONTEXT_CHECK_NAME, + LOOPOVER_GATE_CHECK_NAME, } from "../review/check-names"; export { - GITTENSORY_CONTEXT_CHECK_NAME, - GITTENSORY_GATE_CHECK_NAME, GITTENSORY_LEGACY_GATE_CHECK_NAME, + GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME, + LOOPOVER_CONTEXT_CHECK_NAME, + LOOPOVER_GATE_CHECK_NAME, } from "../review/check-names"; export type { CachedGitHubResponse, GitHubResponseCache } from "./client"; export { @@ -714,7 +716,7 @@ export async function createOrUpdateCheckRun( repoFullName, advisory, { - name: GITTENSORY_CONTEXT_CHECK_NAME, + name: LOOPOVER_CONTEXT_CHECK_NAME, conclusion: advisory.conclusion, output: formatCheckRunOutput(advisory, detailLevel, annotationContext), mode, @@ -745,12 +747,12 @@ export async function createOrUpdateGateCheckRun( repoFullName, advisory, { - name: GITTENSORY_GATE_CHECK_NAME, + name: LOOPOVER_GATE_CHECK_NAME, status: "completed", conclusion: gate.conclusion, output: formatGateCheckOutput(gate), checkRunId: options.checkRunId, - supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME], + supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME, GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME], mode, }, ); @@ -769,16 +771,16 @@ export async function createOrUpdatePendingGateCheckRun( repoFullName, advisory, { - name: GITTENSORY_GATE_CHECK_NAME, + name: LOOPOVER_GATE_CHECK_NAME, status: "in_progress", output: { - title: "Gittensory Orb Review Agent is evaluating", + title: "LoopOver Orb Review Agent is evaluating", summary: - "Gittensory is running deterministic public PR hygiene checks.", + "LoopOver is running deterministic public PR hygiene checks.", text: "The review agent blocks every author on the repo's configured hard blockers (duplicate PRs by default); on everything else, and while state is still syncing, it stays advisory.", }, updateExisting: "in_progress_only", - supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME], + supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME, GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME], mode, }, ); @@ -799,16 +801,16 @@ export async function createOrUpdateSkippedGateCheckRun( repoFullName, advisory, { - name: GITTENSORY_GATE_CHECK_NAME, + name: LOOPOVER_GATE_CHECK_NAME, status: "completed", conclusion: "skipped", checkRunId: options.checkRunId, output: { - title: "Gittensory Orb Review Agent skipped", + title: "LoopOver Orb Review Agent skipped", summary: reason, - text: "Gittensory does not post late first comments on closed or merged pull requests.", + text: "LoopOver does not post late first comments on closed or merged pull requests.", }, - supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME], + supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME, GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME], mode, }, ); @@ -817,7 +819,7 @@ export async function createOrUpdateSkippedGateCheckRun( /** * Finalize a previously-posted pending Gate check to a NEUTRAL (non-blocking) terminal state when the * evaluation could not finish (a transient error/timeout in the work between posting the pending check and - * completing it). This guarantees the "Gittensory Orb Review Agent is evaluating" run never hangs in_progress forever; + * completing it). This guarantees the "LoopOver Orb Review Agent is evaluating" run never hangs in_progress forever; * it does not block the PR and re-runs on the next push. Targets the known pending check_run id so it * updates the SAME run rather than creating a second one. */ @@ -835,17 +837,17 @@ export async function createOrUpdateErroredGateCheckRun( repoFullName, advisory, { - name: GITTENSORY_GATE_CHECK_NAME, + name: LOOPOVER_GATE_CHECK_NAME, status: "completed", conclusion: "neutral", output: { - title: "Gittensory Orb Review Agent — could not finish evaluating", + title: "LoopOver Orb Review Agent — could not finish evaluating", summary: "A transient error interrupted gate evaluation. This does NOT block the PR and re-runs automatically on the next push.", - text: "Gittensory finalizes the review-agent check to a neutral, non-blocking state when evaluation is interrupted, so the check never hangs in_progress. Push a new commit or use the 'Re-run Gittensory review' checkbox to re-evaluate.", + text: "LoopOver finalizes the review-agent check to a neutral, non-blocking state when evaluation is interrupted, so the check never hangs in_progress. Push a new commit or use the 'Re-run LoopOver review' checkbox to re-evaluate.", }, checkRunId: options.checkRunId, - supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME], + supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME, GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME], mode, }, ); @@ -871,17 +873,17 @@ export async function createOrUpdateOverriddenGateCheckRun( repoFullName, advisory, { - name: GITTENSORY_GATE_CHECK_NAME, + name: LOOPOVER_GATE_CHECK_NAME, status: "completed", conclusion: "neutral", output: { - title: `Gittensory Orb Review Agent — overridden by @${options.actor}`, + title: `LoopOver Orb Review Agent — overridden by @${options.actor}`, summary: "A maintainer set the review-agent check to neutral for THIS commit only. This does NOT permanently bypass the review agent; a new push re-evaluates it.", text: `Overridden by @${options.actor}: ${options.reason}`, }, checkRunId: options.checkRunId, - supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME], + supersedeLegacyNames: [GITTENSORY_LEGACY_GATE_CHECK_NAME, GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME], mode, }, ); @@ -914,7 +916,7 @@ async function createOrUpdateNamedCheckRun( // makeInstallationOctokit injects the shared per-request timeout (a stalled PATCH can never orphan the // in_progress check) AND suppresses the check-run writes under a non-live mode (dry-run / pause / freeze). const octokit = makeInstallationOctokit(env, token, check.mode, githubRateLimitAdmissionKeyForInstallation(installationId)); - // Point the merge-box "Details" link at the repo's Gittensory maintainer panel instead of GitHub's generic + // Point the merge-box "Details" link at the repo's LoopOver maintainer panel instead of GitHub's generic // check page. Spread conditionally so a URL-construction failure (null) just omits it. (#audit-details-url) const detailsUrl = maintainerControlPanelUrl(env, repoFullName); const detailsUrlBody = detailsUrl ? { details_url: detailsUrl } : {}; @@ -1005,10 +1007,10 @@ async function createOrUpdateNamedCheckRun( status: "completed", conclusion: "neutral", output: outputForCheckRunUpdate({ - title: `${GITTENSORY_GATE_CHECK_NAME} superseded this legacy check`, + title: `${LOOPOVER_GATE_CHECK_NAME} superseded this legacy check`, summary: "This legacy check name was completed after the review-agent check was renamed.", - text: `Use ${GITTENSORY_GATE_CHECK_NAME} for current Gittensory review results.`, + text: `Use ${LOOPOVER_GATE_CHECK_NAME} for current LoopOver review results.`, }), ...detailsUrlBody, }, diff --git a/src/github/backfill.ts b/src/github/backfill.ts index d48046912b..e170254221 100644 --- a/src/github/backfill.ts +++ b/src/github/backfill.ts @@ -65,9 +65,11 @@ import type { import { errorMessage, nowIso, repoParts, strippedErrorMessage } from "../utils/json"; import { createInstallationToken, getAppInstallation } from "./app"; import { - GITTENSORY_CONTEXT_CHECK_NAME, - GITTENSORY_GATE_CHECK_NAME, + GITTENSORY_LEGACY_CONTEXT_CHECK_NAME, GITTENSORY_LEGACY_GATE_CHECK_NAME, + GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME, + LOOPOVER_CONTEXT_CHECK_NAME, + LOOPOVER_GATE_CHECK_NAME, shouldPublishReviewCheck, } from "../review/check-names"; import { buildReviewThreadBlocker, type ReviewThreadBlocker } from "../review/review-thread-findings"; @@ -2505,9 +2507,11 @@ const CI_PASSING_CONCLUSIONS = new Set(["success", "neutral", "skipped"]); // (#gate-self-deadlock — froze green-CI PRs as "CI still running". The Gate alone wasn't enough: the Context // check is posted the same way and re-created the deadlock, so exclude ALL bot-owned checks.) const BOT_OWNED_CHECK_NAMES = new Set([ - GITTENSORY_GATE_CHECK_NAME, + LOOPOVER_GATE_CHECK_NAME, + LOOPOVER_CONTEXT_CHECK_NAME, GITTENSORY_LEGACY_GATE_CHECK_NAME, - GITTENSORY_CONTEXT_CHECK_NAME, + GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME, + GITTENSORY_LEGACY_CONTEXT_CHECK_NAME, ]); const GITHUB_ACTIONS_VALIDATE_AGGREGATE_CONTEXT = "validate"; diff --git a/src/github/footer.ts b/src/github/footer.ts index 79c3335580..1833a71f30 100644 --- a/src/github/footer.ts +++ b/src/github/footer.ts @@ -1,4 +1,4 @@ -// Shared footer for public Gittensory PR comments — and the viral-growth loop that drives outside +// Shared footer for public LoopOver PR comments — and the viral-growth loop that drives outside // contributors to register on Gittensor. The audience-aware variant leads with an "earn" CTA for // contributors who are NOT yet registered (the conversion target); confirmed contributors get a // lighter line. The link persists on the PR forever, so every reviewed PR keeps inviting. @@ -8,7 +8,7 @@ // scoreability out of public output). This footer uses ONLY "earn" — a factual, public invitation, // not a payout guarantee or a private-score disclosure. -/** The Gittensory product site (marketing on-ramp / attribution target) -- the DEFAULT only. A +/** The LoopOver product site (marketing on-ramp / attribution target) -- the DEFAULT only. A * self-hoster with `PUBLIC_SITE_ORIGIN` set gets their own domain instead, both here and in * `gittensoryFooter` below (#4613). */ export const GITTENSORY_SITE_URL = "https://gittensory.aethereal.dev"; @@ -19,7 +19,7 @@ export const GITTENSORY_SITE_URL = "https://gittensory.aethereal.dev"; * whole worker binding type. */ export type GittensoryFooterEnv = { PUBLIC_SITE_ORIGIN?: string | undefined }; -/** The maintainer control panel for a repo on the Gittensory site (`/app?view=maintainer&repo=…`). Used as the +/** The maintainer control panel for a repo on the LoopOver site (`/app?view=maintainer&repo=…`). Used as the * check-run `details_url` so the merge-box "Details" link lands on the repo's review panel instead of GitHub's * generic check page, and as the in-comment control-panel link. Returns null only if URL construction throws. */ export function maintainerControlPanelUrl(env: { PUBLIC_SITE_ORIGIN?: string | undefined }, repoFullName: string): string | null { @@ -66,24 +66,24 @@ export function gittensorRepoEarnUrl(repoFullName: string): string { * distinction lives in the review BODY (full panel vs. minimal), not here. * Uses only "earn" wording — never reward/payout/score (forbidden in public comments). * `env.PUBLIC_SITE_ORIGIN` (same resolution as `maintainerControlPanelUrl` above) lets a self-hoster's - * own domain replace `GITTENSORY_SITE_URL` in the "Checked by Gittensory" attribution link (#4613) -- + * own domain replace `GITTENSORY_SITE_URL` in the "Checked by LoopOver" attribution link (#4613) -- * the Gittensor register link (`GITTENSOR_HOME_URL`) is a separate, shared network and is never rebranded. */ export function gittensoryFooter(env: GittensoryFooterEnv, opts: { earnUrl?: string | undefined; customText?: string | undefined } = {}): string { const siteUrl = env.PUBLIC_SITE_ORIGIN ?? GITTENSORY_SITE_URL; const earnUrl = opts.earnUrl ?? GITTENSOR_HOME_URL; // Maintainer-customized footer (via `.gittensory.yml review.footer.text`): the maintainer's public-safe - // lead replaces the default CTA copy, but the Gittensor register link + Gittensory attribution are + // lead replaces the default CTA copy, but the Gittensor register link + LoopOver attribution are // ALWAYS appended — the growth surface is preserved regardless of customization. if (opts.customText) { return [ opts.customText, "", - `[Gittensor](${GITTENSOR_HOME_URL}) lets GitHub contributors earn for the work they already do — [register to start earning →](${earnUrl}). Checked by [Gittensory](${siteUrl}).`, + `[Gittensor](${GITTENSOR_HOME_URL}) lets GitHub contributors earn for the work they already do — [register to start earning →](${earnUrl}). Checked by [LoopOver](${siteUrl}).`, ].join("\n"); } return [ `💰 **Earn for open-source contributions like this.** [Gittensor](${GITTENSOR_HOME_URL}) lets GitHub contributors earn for the work they already do — [register to start earning →](${earnUrl}).`, "", - `Checked by [Gittensory](${siteUrl}), a quiet PR intelligence layer for OSS maintainers.`, + `Checked by [LoopOver](${siteUrl}), a quiet PR intelligence layer for OSS maintainers.`, ].join("\n"); } diff --git a/src/openapi/schemas.ts b/src/openapi/schemas.ts index 94d678951b..34455e037f 100644 --- a/src/openapi/schemas.ts +++ b/src/openapi/schemas.ts @@ -783,7 +783,7 @@ export const RepositorySettingsSchema = z publicSurface: z .enum(["off", "comment_and_label", "comment_only", "label_only"]) .describe( - "Governs ONLY the PR comment and label -- never the Gittensory Context check (checkRunMode) or the Gittensory Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run.", + "Governs ONLY the PR comment and label -- never the LoopOver Context check (checkRunMode) or the LoopOver Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run.", ), includeMaintainerAuthors: z.boolean(), requireLinkedIssue: z.boolean(), @@ -877,7 +877,7 @@ export const RepoSettingsPreviewSchema = z publicSurface: z .enum(["off", "comment_and_label", "comment_only", "label_only"]) .describe( - "Governs ONLY the PR comment and label -- never the Gittensory Context check (checkRunMode) or the Gittensory Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run.", + "Governs ONLY the PR comment and label -- never the LoopOver Context check (checkRunMode) or the LoopOver Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run.", ), commentMode: z.enum(["off", "detected_contributors_only", "all_prs"]), publicAudienceMode: z.enum(["oss_maintainer", "gittensor_only"]), @@ -1281,7 +1281,7 @@ export const InstallationRepairSchema = z publicSurface: z .enum(["off", "comment_and_label", "comment_only", "label_only"]) .describe( - "Governs ONLY the PR comment and label -- never the Gittensory Context check (checkRunMode) or the Gittensory Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run.", + "Governs ONLY the PR comment and label -- never the LoopOver Context check (checkRunMode) or the LoopOver Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run.", ), commentMode: z.enum(["off", "detected_contributors_only", "all_prs"]), publicAudienceMode: z.enum(["oss_maintainer", "gittensor_only"]), @@ -2199,7 +2199,7 @@ export const RegistrationReadinessSchema = z publicSurface: z .enum(["off", "comment_and_label", "comment_only", "label_only"]) .describe( - "Governs ONLY the PR comment and label -- never the Gittensory Context check (checkRunMode) or the Gittensory Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run.", + "Governs ONLY the PR comment and label -- never the LoopOver Context check (checkRunMode) or the LoopOver Orb Review Agent gate check (reviewCheckMode), which are independent axes by design (#2852). Setting this to \"off\" does NOT silence either check-run.", ), commentMode: z.enum(["off", "detected_contributors_only", "all_prs"]), publicAudienceMode: z.enum(["oss_maintainer", "gittensor_only"]), diff --git a/src/queue/ai-review-orchestration.ts b/src/queue/ai-review-orchestration.ts index 2c6078d248..033f2f74a1 100644 --- a/src/queue/ai-review-orchestration.ts +++ b/src/queue/ai-review-orchestration.ts @@ -160,7 +160,7 @@ export function aiReviewLockContendedResult( ]; advisory.findings.push(...findings); return { - notes: "AI review is already running for this PR head in another Gittensory pass. Gittensory is holding this PR for manual review until that pass completes.", + notes: "AI review is already running for this PR head in another LoopOver pass. LoopOver is holding this PR for manual review until that pass completes.", reviewerCount: 0, inlineFindings: [], findings, @@ -805,7 +805,7 @@ export async function runAiReviewForAdvisory( detail: "The configured AI reviewer returned no usable public assessment for this PR head.", action: - "Fix the configured AI provider, then re-run Gittensory review before relying on the result.", + "Fix the configured AI provider, then re-run LoopOver review before relying on the result.", }; findings.push(unavailableFinding); args.advisory.findings.push(unavailableFinding); diff --git a/src/queue/gate-checks.ts b/src/queue/gate-checks.ts index 053805117f..6e11cc9a0e 100644 --- a/src/queue/gate-checks.ts +++ b/src/queue/gate-checks.ts @@ -7,7 +7,7 @@ // they group cleanly by concern here. import { recordAuditEvent, upsertCheckSummary } from "../db/repositories"; -import { GITTENSORY_GATE_CHECK_NAME } from "../github/app"; +import { LOOPOVER_GATE_CHECK_NAME } from "../github/app"; import { guardrailPathMatches } from "../signals/change-guardrail"; import type { RepositorySettings } from "../types"; import { nowIso } from "../utils/json"; @@ -40,7 +40,7 @@ export async function recordPublishedGateCheckSummary( repoFullName: args.repoFullName, pullNumber: args.pullNumber, headSha: args.headSha, - name: GITTENSORY_GATE_CHECK_NAME, + name: LOOPOVER_GATE_CHECK_NAME, status: "completed", /* v8 ignore next -- Gate publication always supplies a conclusion; this keeps the DB value defensive. */ conclusion: args.conclusion ?? null, diff --git a/src/queue/processors.ts b/src/queue/processors.ts index 73787bb246..1d019a26a0 100644 --- a/src/queue/processors.ts +++ b/src/queue/processors.ts @@ -131,7 +131,7 @@ import { getInstallationId, getRepositoryCollaboratorPermission, githubErrorStatus, - GITTENSORY_GATE_CHECK_NAME, + LOOPOVER_GATE_CHECK_NAME, isGitHubRateLimitedError, isForeignAppInstallation, } from "../github/app"; @@ -1068,7 +1068,7 @@ async function surfaceRepairPriorityPullNumbers( ); const currentGateCheck = checks.find( (check) => - check.name === GITTENSORY_GATE_CHECK_NAME && + check.name === LOOPOVER_GATE_CHECK_NAME && check.headSha === pr.headSha && check.status === "completed", ); @@ -3341,7 +3341,7 @@ async function prReadyForReview( } // Not authorized, staged, dry-run, or failed (conflict/transient) → fall through and review without mutating. } - // 2) wait for CI to finish before running the Gittensory review. Required contexts still define which failures + // 2) wait for CI to finish before running the LoopOver review. Required contexts still define which failures // block/close, but hasPending tracks any visible non-bot CI that is not settled yet. const ci = await cachedLiveCiAggregate(env, { repoFullName, @@ -9304,7 +9304,7 @@ async function maybePublishPrPublicSurface( const existingChecks = await listCheckSummaries(env, repoFullName, pr.number).catch(() => []); const currentGateCheck = existingChecks.find( (check) => - check.name === GITTENSORY_GATE_CHECK_NAME && + check.name === LOOPOVER_GATE_CHECK_NAME && check.headSha === advisory.headSha && check.status === "completed", ); @@ -10074,7 +10074,7 @@ async function maybePublishPrPublicSurface( ? { customText: reviewConfig.footerText } : {}), }), - reRunLabel: `${PR_PANEL_RETRIGGER_MARKER} Re-run Gittensory review`, + reRunLabel: `${PR_PANEL_RETRIGGER_MARKER} Re-run LoopOver review`, // #4589: only rendered when there's an actual gap AND the checkbox would work for this repo -- same // condition testCoverageBody gates its own (informational) collapsible on, so the two always agree. ...(missingTestsFinding && e2eTestGenAvailable @@ -10479,7 +10479,7 @@ async function maybeProcessGateOverrideCommand( AGENT_COMMAND_COMMENT_MARKER, "", "> [!NOTE]", - `> **${GITTENSORY_GATE_CHECK_NAME} overridden by @${actor}**`, + `> **${LOOPOVER_GATE_CHECK_NAME} overridden by @${actor}**`, "> The review-agent check was set to neutral for the current commit only. This does NOT permanently bypass the review; a new push re-evaluates it.", "", `- Reason: ${safeReason}`, diff --git a/src/review/check-names.ts b/src/review/check-names.ts index bf47771a07..5be48b6d4e 100644 --- a/src/review/check-names.ts +++ b/src/review/check-names.ts @@ -1,16 +1,30 @@ import type { ReviewCheckMode } from "../types"; -export const GITTENSORY_CONTEXT_CHECK_NAME = "Gittensory Context"; -export const GITTENSORY_GATE_CHECK_NAME = "Gittensory Orb Review Agent"; +export const LOOPOVER_CONTEXT_CHECK_NAME = "LoopOver Context"; +export const LOOPOVER_GATE_CHECK_NAME = "LoopOver Orb Review Agent"; /** Pre-rename check-run name ("Gittensory Gate"). NOT dead code: any self-hosted repo that still has an - * old-named check-run stuck pending from before the rename (e.g. a self-hoster who upgrades mid-flight, - * or a check-run left open across a deploy) would otherwise show a permanently-pending, never-completed - * status on GitHub. `finalizeLegacyPendingCheckRuns` in src/github/app.ts uses this name to find and - * complete (neutral, "superseded") any such stale legacy-named run once the new-named one finishes. Keep - * this until self-hosters can no longer be upgrading across the rename boundary. */ + * old-named check-run stuck pending from before that EARLIER rename (e.g. a self-hoster who upgrades + * mid-flight, or a check-run left open across a deploy) would otherwise show a permanently-pending, + * never-completed status on GitHub. `finalizeLegacyPendingCheckRuns` in src/github/app.ts uses this name + * to find and complete (neutral, "superseded") any such stale legacy-named run once the new-named one + * finishes. Keep this until self-hosters can no longer be upgrading across that rename boundary. */ export const GITTENSORY_LEGACY_GATE_CHECK_NAME = "Gittensory Gate"; +/** Pre-rebrand check-run name ("Gittensory Orb Review Agent"), retired by the LoopOver rebrand's hard + * cutover (#5327 — no dual-emit window). Same NOT-dead-code reasoning as + * {@link GITTENSORY_LEGACY_GATE_CHECK_NAME}: `finalizeLegacyPendingCheckRuns` also supersedes any run still + * pending under THIS name so a self-hoster mid-flight across the rebrand deploy never sees a permanently- + * pending status. */ +export const GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME = "Gittensory Orb Review Agent"; +/** Pre-rebrand check-run name ("Gittensory Context"), retired by the LoopOver rebrand's hard cutover + * (#5327). Unlike the two Gate-check legacy names above, this one is NOT fed into + * `finalizeLegacyPendingCheckRuns` (the Context check was never given that supersede treatment, even + * across the earlier "Gittensory Gate" rename) -- it exists solely so `BOT_OWNED_CHECK_NAMES` + * (src/github/backfill.ts) still recognizes a still-pending pre-rebrand Context run as bot-owned and + * excludes it from the CI-aggregate wait, avoiding the same self-deadlock class `BOT_OWNED_CHECK_NAMES`'s + * own comment describes. */ +export const GITTENSORY_LEGACY_CONTEXT_CHECK_NAME = "Gittensory Context"; -/** Single point of truth for whether `reviewCheckMode` publishes the Gittensory Orb Review Agent check-run +/** Single point of truth for whether `reviewCheckMode` publishes the LoopOver Orb Review Agent check-run * (#2852). `required` and `visible` both publish -- they are identical on the API-call side; the distinction * is purely about how the operator should configure GitHub branch protection (visible = never required). Only * `disabled` skips the check-run create/update calls entirely. */ diff --git a/src/review/content-lane-wire.ts b/src/review/content-lane-wire.ts index 0c939bc9ac..32afcce617 100644 --- a/src/review/content-lane-wire.ts +++ b/src/review/content-lane-wire.ts @@ -36,7 +36,7 @@ // maintainer-configured gate, and that explicit opt-in must still close a PR outright (see guard #1 for why a // genuinely critical finding, or one of these other configured gates, still wins outright). import { AI_JUDGMENT_BLOCKER_CODES, type GateCheckEvaluation, isAiJudgmentOnlyFailure, isDuplicateOnlyFailure } from "../rules/advisory"; -import { GITTENSORY_GATE_CHECK_NAME } from "./check-names"; +import { LOOPOVER_GATE_CHECK_NAME } from "./check-names"; import { isContentLaneEnabled } from "./content-lane/flag"; import { runSurfaceReview, type SurfaceReviewInput, type SurfaceReviewResult } from "./content-lane/orchestrator"; import type { RegistryLaneSpec } from "./content-lane/registry-logic"; @@ -146,7 +146,7 @@ export function applySurfaceGate( return { ...surface, conclusion: "neutral", - title: `${GITTENSORY_GATE_CHECK_NAME} — held for review`, + title: `${LOOPOVER_GATE_CHECK_NAME} — held for review`, summary: heldReason, warnings: [...generic.blockers, ...generic.warnings, ...surface.warnings], }; @@ -293,8 +293,8 @@ export async function evaluateWithSurfaceLane( return { enabled: true, conclusion: "neutral", - title: `${GITTENSORY_GATE_CHECK_NAME} — held for human review`, - summary: "The repo's .gittensory.yml could not be read, so Gittensory cannot confirm whether a registry content-lane is configured for this repo. The gate is held for a human reviewer rather than silently skipping the registry check. It re-evaluates on the next update.", + title: `${LOOPOVER_GATE_CHECK_NAME} — held for human review`, + summary: "The repo's .gittensory.yml could not be read, so LoopOver cannot confirm whether a registry content-lane is configured for this repo. The gate is held for a human reviewer rather than silently skipping the registry check. It re-evaluates on the next update.", blockers: [], warnings: gateEvaluation?.warnings ?? [], }; diff --git a/src/review/repo-profile.ts b/src/review/repo-profile.ts index 7e798da098..7cb63b996f 100644 --- a/src/review/repo-profile.ts +++ b/src/review/repo-profile.ts @@ -56,11 +56,11 @@ export type RepoProfileCommands = { }; export type RepoProfileContributionWorkflow = { - /** Whether the review gate (the "Gittensory Orb Review Agent" check) publishes a check at all, derived + /** Whether the review gate (the "LoopOver Orb Review Agent" check) publishes a check at all, derived * from `settings.reviewCheckMode` -- the actual runtime authority for that check's publication (#2852). * A prior `gateCheckMode` field was a deprecated read-back of this same value; it was removed entirely * (#5373). `checkRunMode` is NOT related -- it's a live, independent field that governs the SEPARATE - * "Gittensory Context" check, unrelated to this one. Reuses the EXISTING settings resolver rather than + * "LoopOver Context" check, unrelated to this one. Reuses the EXISTING settings resolver rather than * re-deriving gate presence from raw repo files. */ gatePublishesCheck: boolean; linkedIssuePolicy: "required" | "preferred" | "optional"; diff --git a/src/review/unified-comment-bridge.ts b/src/review/unified-comment-bridge.ts index b7ff238942..54859a31c1 100644 --- a/src/review/unified-comment-bridge.ts +++ b/src/review/unified-comment-bridge.ts @@ -1,11 +1,11 @@ -// Unified-comment bridge (reviewbot→gittensory convergence, Stage D). +// Unified-comment bridge (reviewbot→loopover convergence, Stage D). // -// A PURE, testable mapping from gittensory's live PR-review data (the gate `GateCheckEvaluation`, the AI +// A PURE, testable mapping from loopover's live PR-review data (the gate `GateCheckEvaluation`, the AI // `advisoryNotes` + consensus defect, the readiness signal rows + total, the footer) onto the ported // unified renderer (`renderUnifiedReviewComment`). Flag-gated and default-OFF in the processor; flag-OFF // keeps the legacy `buildPublicPrIntelligenceComment` path byte-identical. // -// gittensory's GATE stays authoritative: we pass the gate-derived `decision` into `buildUnifiedReviewInput` +// loopover's GATE stays authoritative: we pass the gate-derived `decision` into `buildUnifiedReviewInput` // so `deriveUnifiedStatus` lets it override the reviewer recommendations (the renderer already enforces // this). The output PREPENDS the exact panel marker the legacy body carries, so the existing in-place // upsert (`createOrUpdatePrIntelligenceComment`) updates the same comment instead of posting a duplicate. @@ -28,7 +28,7 @@ import { VISUAL_REGRESSION_FINDING_CODE } from "./visual/visual-findings"; // importers of `PR_PANEL_COMMENT_MARKER` from this module keep working. The unified body MUST prepend this // verbatim or `createOrUpdatePrIntelligenceComment` posts a DUPLICATE instead of updating in place. import { PR_PANEL_COMMENT_MARKER } from "../github/comments"; -import { GITTENSORY_GATE_CHECK_NAME } from "./check-names"; +import { LOOPOVER_GATE_CHECK_NAME } from "./check-names"; import { classifyChangedFile, type ReviewFileClass } from "./changed-files-classify"; import { githubPrFileDiffUrl } from "./changed-files-diff-link"; import { classifyFindingCategory, FINDING_CATEGORIES, type FindingCategory } from "./finding-category-classify"; @@ -54,7 +54,7 @@ export { splitAiReviewNits } from "./ai-notes"; // ── Public-safe defense-in-depth (privacy-critical) ────────────────────────────────────────────── // // Every field this bridge feeds into the renderer is ALREADY public-safe by construction on the live -// gittensory inputs (verified at convergence issue #1): +// loopover inputs (verified at convergence issue #1): // • panel rows (result/evidence) — built by buildPublicPrPanelSignalRows' panel helpers (public-safe); // • aiReview.notes — composed via composeAdvisoryNotes → toPublicSafe (drops anything unsafe); // • the consensus-defect title/detail — produced via toPublicSafe in consensusDefectOf. @@ -80,7 +80,7 @@ function publicSafeNit(line: string): string | null { return PRIVATE_DROP_TERMS.test(scrubbed) ? null : scrubbed; } -/** Map gittensory's gate conclusion to the renderer's authoritative `Verdict`. +/** Map loopover's gate conclusion to the renderer's authoritative `Verdict`. * success → merge · failure → close · action_required/neutral → manual · skipped → comment. */ export function gateConclusionToVerdict(conclusion: GateCheckConclusion): Verdict { switch (conclusion) { @@ -125,7 +125,7 @@ function rowResultText(resultCell: string): string { } /** Map the legacy panel signal rows → the unified table's rows (label/state/result/evidence). The - * unified renderer adds its own "Code review" row first; these follow it (gittensory's gate row included). */ + * unified renderer adds its own "Code review" row first; these follow it (loopover's gate row included). */ export function panelRowsToSignalRows(rows: PublicPrPanelSignalRow[]): UnifiedSignalRow[] { return rows.map((row) => { const [label, result, evidence] = row.cells; @@ -182,7 +182,7 @@ export function isBoilerplateNit(finding: AdvisoryFinding): boolean { ); } -/** Build the single AI reviewer note from gittensory's AI output: the composed advisory write-up (minus its nits) +/** Build the single AI reviewer note from loopover's AI output: the composed advisory write-up (minus its nits) * becomes the assessment; a consensus defect (recovered from the advisory findings) becomes a blocker; the AI's own * nits AND the gate's non-blocking warnings become the collapsible nits. Deterministic warnings alone must NOT * manufacture a reviewer note: a final public comment may only claim an AI review when there is a real AI @@ -267,7 +267,7 @@ export function buildDualReviewNotes(args: { blockers, nits, }; - return [{ model: args.reviewerModel ?? "Gittensory AI review", notes }]; + return [{ model: args.reviewerModel ?? "LoopOver AI review", notes }]; } /** Recover a consensus defect (the dual-model agreement the gate already folded into its findings) from @@ -308,7 +308,7 @@ function normalizeConcernLine(value: string): string { } export type UnifiedCommentBridgeArgs = { - /** gittensory's authoritative gate verdict (drives the unified status + the Gate row). */ + /** loopover's authoritative gate verdict (drives the unified status + the Gate row). */ gate: GateCheckEvaluation; /** The AI maintainer-review advisory notes (already public-safe), if any. */ aiReview?: { notes: string } | undefined; @@ -318,13 +318,13 @@ export type UnifiedCommentBridgeArgs = { panelRows: PublicPrPanelSignalRow[]; /** Which rows the maintainer kept visible (`.gittensory.yml review.fields`); a key set to `false` is hidden. */ reviewFields?: Partial> | undefined; - /** The gittensory readiness total (0–100) → the readiness chip. */ + /** The loopover readiness total (0–100) → the readiness chip. */ readinessTotal: number; /** Number of changed files reviewed. */ changedFiles: number; /** Number of independent AI reviewers synthesized (0 hides the reviewer chip/row evidence count). */ reviewerCount?: number | undefined; - /** CI + merge-state readiness, when the caller resolved it (gittensory's panel omits it today). */ + /** CI + merge-state readiness, when the caller resolved it (loopover's panel omits it today). */ mergeReadiness?: MergeReadiness | undefined; /** Whether the PR was auto-merged (only changes the ready-state verdict wording). */ merged?: boolean | undefined; @@ -336,7 +336,7 @@ export type UnifiedCommentBridgeArgs = { generateTestsLabel?: string | undefined; /** Extra collapsed sections (e.g. signal definitions / contributor next steps). */ extraCollapsibles?: UnifiedCollapsible[] | undefined; - /** Headline brand (default "Gittensory review"). */ + /** Headline brand (default "LoopOver review"). */ brand?: string | undefined; /** Visual before/after capture routes (visual-capture port). When present + non-empty, a "Visual preview" * collapsible (a markdown table of tags pointing at the public /gittensory/shot URLs) is appended. @@ -715,7 +715,7 @@ export function buildFindingCategoryCollapsible(findings: FindingCategoryInput[] } /** - * Build the unified PR-review comment body from gittensory's live data. Returns a string that STARTS with + * Build the unified PR-review comment body from loopover's live data. Returns a string that STARTS with * the panel marker (so the existing upsert updates in place) followed by the rendered unified comment. * The gate verdict is authoritative: it is passed as `decision` so the renderer's `deriveUnifiedStatus` * lets it override the reviewer recommendation. @@ -836,7 +836,7 @@ export function buildUnifiedCommentBody(args: UnifiedCommentBridgeArgs): string const extraCollapsibles = scrollCollapsible !== null ? [...(withVisual ?? []), scrollCollapsible] : withVisual; const body = renderUnifiedReviewComment(input, { - brand: args.brand ?? "Gittensory review", + brand: args.brand ?? "LoopOver review", readinessScore: args.readinessTotal, signals, footerMarkdown: args.footerMarkdown, @@ -869,7 +869,7 @@ export function buildClosedUnifiedCommentBody(args: { repoFullName: string; pull const skippedGate: GateCheckEvaluation = { enabled: true, conclusion: "skipped", - title: `${GITTENSORY_GATE_CHECK_NAME} skipped`, + title: `${LOOPOVER_GATE_CHECK_NAME} skipped`, summary: "PR closed before full evaluation. No late first comment was created.", blockers: [], warnings: [], diff --git a/src/review/unified-comment.ts b/src/review/unified-comment.ts index e080ddb5cf..c89221cfe3 100644 --- a/src/review/unified-comment.ts +++ b/src/review/unified-comment.ts @@ -1,22 +1,22 @@ // Unified PR review comment renderer (convergence — see docs/GITTENSORY_REVIEW_UNIFIED_COMMENT.md). // -// Produces ONE in-place comment in the gittensory SHAPE (colored alert sidebar + readiness +// Produces ONE in-place comment in the loopover SHAPE (colored alert sidebar + readiness // signal table + collapsibles + re-run + earning footer) with reviewbot's deep review folded // in (the verdict, the synthesized summary, a "Code review" signal row, nits/blockers), deduped. // // ADDITIVE + DORMANT: the live Worker keeps composeUnifiedReview() (advisory-render.ts). This -// renderer is exposed via engine.ts for the host (the gittensory app) to call at cutover — it is +// renderer is exposed via engine.ts for the host (the loopover app) to call at cutover — it is // a PURE function (no I/O, no redaction). The host applies its public-safe redaction AFTER, the // same way the runtime does today (makePublicRedactor / redactOutsideCodeFences). // -// The host provides gittensory's readiness signals + footer + collapsibles in UnifiedCommentContext; +// The host provides loopover's readiness signals + footer + collapsibles in UnifiedCommentContext; // reviewbot's review data comes in UnifiedReviewInput. The whole comment recolors by one unified // status so there is a single authoritative verdict, never two. // -// SELF-CONTAINED NATIVE PORT (reviewbot→gittensory convergence): every type + helper this module +// SELF-CONTAINED NATIVE PORT (reviewbot→loopover convergence): every type + helper this module // needs is defined HERE. No imports from reviewbot. The logic is byte-faithful to the reviewbot // source (src/core/unified-comment-render.ts + src/core/advisory-render.ts); the only deltas are -// mechanical guards for gittensory's stricter tsconfig (noUncheckedIndexedAccess + +// mechanical guards for loopover's stricter tsconfig (noUncheckedIndexedAccess + // exactOptionalPropertyTypes), which do not change behavior. // ── Inlined minimal types (ported from reviewbot src/core/{ai-review,types,checks-gate}.ts) ───── @@ -195,7 +195,7 @@ export interface UnifiedReviewInput { inlineFindings?: ReadonlyArray<{ category?: UnifiedFindingCategory | undefined }>; } -/** One row of the readiness signal table (gittensory side, host-provided; the engine adds Code review). */ +/** One row of the readiness signal table (loopover side, host-provided; the engine adds Code review). */ export interface UnifiedSignalRow { label: string; state: "ok" | "warn" | "fail"; @@ -205,7 +205,7 @@ export interface UnifiedSignalRow { evidence?: string; } -/** A collapsed section (gittensory side: signal definitions, contributor next steps, …). */ +/** A collapsed section (loopover side: signal definitions, contributor next steps, …). */ export interface UnifiedCollapsible { title: string; body: string; @@ -220,7 +220,7 @@ export interface UnifiedCollapsible { export interface AutoMergeSummarySignals { /** Every required CI check is green. */ ciGreen: boolean; - /** The Gittensory gate is passing (no hard blocker). */ + /** The LoopOver gate is passing (no hard blocker). */ gatePassing: boolean; /** GitHub reports the branch mergeable / clean (no conflict, not behind). */ mergeableClean: boolean; @@ -250,17 +250,17 @@ export function buildAutoMergeSummaryCollapsible(signals: AutoMergeSummarySignal return { title: "Auto-merge readiness (read-only)", body }; } -/** The host (gittensory) side: brand, readiness score, signals, sections, re-run, footer. */ +/** The host (loopover) side: brand, readiness score, signals, sections, re-run, footer. */ export interface UnifiedCommentContext { - /** Headline brand, default "Gittensory review". */ + /** Headline brand, default "LoopOver review". */ brand?: string; - /** gittensory readiness score 0–100 (omitted = no chip). */ + /** loopover readiness score 0–100 (omitted = no chip). */ readinessScore?: number; - /** gittensory readiness signal rows (rendered after the Code review row). */ + /** loopover readiness signal rows (rendered after the Code review row). */ signals?: UnifiedSignalRow[]; /** Extra collapsed sections (rendered after Nits). */ extraCollapsibles?: UnifiedCollapsible[]; - /** Re-run checkbox label, e.g. "Re-run Gittensory review" (omitted = no checkbox). */ + /** Re-run checkbox label, e.g. "Re-run LoopOver review" (omitted = no checkbox). */ reRunLabel?: string; /** #4589: generate-tests checkbox label, e.g. "Generate an AI Playwright test for this PR" (omitted = no * checkbox). Same top-level-outside-the-blockquote placement as reRunLabel, for the same reason (see @@ -334,8 +334,8 @@ export function deriveUnifiedStatus(input: UnifiedReviewInput, ctx: UnifiedComme if (input.readiness?.ciState === "failed") { return "blocked"; } - // Readiness is otherwise advisory for the Gittensory verdict. A PR is not "safe to merge" until CI is green, - // but pending/unverified CI should hold rather than create a red/blocked Gittensory decision by itself. + // Readiness is otherwise advisory for the LoopOver verdict. A PR is not "safe to merge" until CI is green, + // but pending/unverified CI should hold rather than create a red/blocked LoopOver decision by itself. if (status === "ready" && input.readiness && input.readiness.ciState !== "passed") { return "held"; } @@ -638,7 +638,7 @@ export function tallyFindingCategories( export function renderUnifiedReviewComment(input: UnifiedReviewInput, ctx: UnifiedCommentContext = {}): string { const status = deriveUnifiedStatus(input, ctx); const meta = STATUS_META[status]; - const brand = escapePublicHtmlAngles(ctx.brand ?? "Gittensory review"); + const brand = escapePublicHtmlAngles(ctx.brand ?? "LoopOver review"); const reviewTimestamp = formatReviewTimestamp(ctx.reviewedAt); // review.comment_verbosity (#2047): quiet drops every collapsible (Nits + extraCollapsibles) — blockers, // the gate result, and the signal table are never gated by verbosity, only decorative detail is. detailed @@ -743,7 +743,7 @@ export function renderUnifiedReviewComment(input: UnifiedReviewInput, ctx: Unifi /** * Build the renderer's input from reviewbot's actual review output, reusing the shared extraction * (extractReviewSummary) so the converged comment surfaces exactly the blockers / nits / summary / consensus - * reviewbot itself decided on — never a divergent second synthesis. The host then supplies its gittensory + * reviewbot itself decided on — never a divergent second synthesis. The host then supplies its loopover * signals/footer in UnifiedCommentContext and calls renderUnifiedReviewComment. */ export function buildUnifiedReviewInput(opts: { @@ -794,7 +794,7 @@ const REVIEWING_SQUARE = "🟪"; * before posting so the upsert updates the existing bot comment instead of creating a duplicate. * Pure and public-safe-by-construction (brand is angle-escaped; no raw caller text embedded). */ export function renderReviewingPlaceholder(ctx: { brand?: string } = {}): string { - const brand = escapePublicHtmlAngles(ctx.brand ?? "Gittensory"); + const brand = escapePublicHtmlAngles(ctx.brand ?? "LoopOver"); const inner = [ REVIEWING_SQUARE.repeat(12), `### 🔍 ${brand} is reviewing…`, diff --git a/src/rules/advisory.ts b/src/rules/advisory.ts index c6265a4306..c2c71bfd6a 100644 --- a/src/rules/advisory.ts +++ b/src/rules/advisory.ts @@ -16,7 +16,7 @@ import type { GuardrailPathMatch } from "../signals/change-guardrail"; import { isCodeFile } from "../signals/local-branch"; import { isTestPath } from "../signals/test-evidence"; import { nowIso } from "../utils/json"; -import { GITTENSORY_GATE_CHECK_NAME } from "../review/check-names"; +import { LOOPOVER_GATE_CHECK_NAME } from "../review/check-names"; import { CLA_CHECK_UNRESOLVED_CODE, CLA_CONSENT_MISSING_CODE } from "../review/cla-check"; import { REVIEW_THREAD_BLOCKER_CODE } from "../review/review-thread-findings"; import { labelMatchesPattern } from "../scoring/preview"; @@ -465,8 +465,8 @@ export function formatCheckRunOutput( detailLevel: "minimal" | "standard" = "minimal", annotationContext?: CheckRunAnnotationContext, ): CheckRunOutput { - const title = advisoryResult.conclusion === "success" ? "Gittensory context checked" : "Gittensory context posted"; - const summary = "Gittensory public check output is intentionally minimal. Detailed maintainer context is available only through private API/MCP surfaces."; + const title = advisoryResult.conclusion === "success" ? "LoopOver context checked" : "LoopOver context posted"; + const summary = "LoopOver public check output is intentionally minimal. Detailed maintainer context is available only through private API/MCP surfaces."; let text: string; if (detailLevel === "minimal") { @@ -560,15 +560,15 @@ export function evaluateGateCheck(advisoryResult: Advisory, policy: GateCheckPol function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy = {}): GateCheckEvaluation { const warnings = advisoryResult.findings.filter((finding) => finding.severity === "warning"); - // App/infra state (repo not synced yet, PR not cached): gittensory cannot evaluate this PR yet, so the + // App/infra state (repo not synced yet, PR not cached): loopover cannot evaluate this PR yet, so the // gate is NEUTRAL (non-blocking) and re-evaluates automatically on the next sync/webhook. Never block a // contributor on the app's OWN state. if (advisoryResult.findings.some((finding) => isEvaluationBlocker(finding.code, policy))) { return { enabled: true, conclusion: "neutral", - title: `${GITTENSORY_GATE_CHECK_NAME} — not evaluated yet`, - summary: "Gittensory has not finished syncing this repo/PR. The gate stays advisory and re-evaluates automatically; no action is needed.", + title: `${LOOPOVER_GATE_CHECK_NAME} — not evaluated yet`, + summary: "LoopOver has not finished syncing this repo/PR. The gate stays advisory and re-evaluates automatically; no action is needed.", blockers: [], warnings, }; @@ -598,7 +598,7 @@ function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy return { enabled: true, conclusion: "neutral", - title: `${GITTENSORY_GATE_CHECK_NAME} — held for human review`, + title: `${LOOPOVER_GATE_CHECK_NAME} — held for human review`, summary: "The AI review could not be completed for this change, so the gate is held for a human reviewer rather than passed automatically. It re-evaluates on the next update.", blockers: [], warnings: gateWarnings, @@ -616,7 +616,7 @@ function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy return { enabled: true, conclusion: "neutral", - title: `${GITTENSORY_GATE_CHECK_NAME} — held for manual review`, + title: `${LOOPOVER_GATE_CHECK_NAME} — held for manual review`, summary: holds.map((h) => sanitizeForCheckRun(h.title)).join("; "), blockers: [], warnings: [...gateWarnings, ...holds], @@ -625,7 +625,7 @@ function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy return { enabled: true, conclusion: "success", - title: `${GITTENSORY_GATE_CHECK_NAME} passed`, + title: `${LOOPOVER_GATE_CHECK_NAME} passed`, summary: "No configured hard blocker was found. Advisory findings, if any, stay advisory.", blockers, warnings: gateWarnings, @@ -637,7 +637,7 @@ function evaluateGateCheckCore(advisoryResult: Advisory, policy: GateCheckPolicy return { enabled: true, conclusion: "failure", - title: `${GITTENSORY_GATE_CHECK_NAME}: ${titleDetail}`, + title: `${LOOPOVER_GATE_CHECK_NAME}: ${titleDetail}`, summary: blockers .map((finding) => `${sanitizeForCheckRun(finding.title)}${finding.action ? ` — ${sanitizeForCheckRun(finding.action)}` : ""}`) .join("; "), @@ -650,7 +650,7 @@ export function formatGateCheckOutput(gate: GateCheckEvaluation): { title: strin if (gate.conclusion === "success") { return { title: gate.title, - summary: `${GITTENSORY_GATE_CHECK_NAME} is advisory-first. This PR has no configured hard blocker.`, + summary: `${LOOPOVER_GATE_CHECK_NAME} is advisory-first. This PR has no configured hard blocker.`, text: "No configured hard blocker was found. Advisory signals remain visible in the PR panel when comments are enabled.", }; } @@ -658,7 +658,7 @@ export function formatGateCheckOutput(gate: GateCheckEvaluation): { title: strin return { title: gate.title.slice(0, 255), summary: gate.summary, - text: "Gittensory did not create a contributor-facing failure for this event.", + text: "LoopOver did not create a contributor-facing failure for this event.", }; } const blockerLines = gate.blockers.slice(0, 8).map((finding) => { @@ -670,7 +670,7 @@ export function formatGateCheckOutput(gate: GateCheckEvaluation): { title: strin // An unbounded title (e.g. when failing-check names are appended) threw a 422 that aborted the ENTIRE // review before the comment, audit, and auto-action — so red-CI PRs were never reviewed or closed. title: gate.title.slice(0, 255), - summary: `${GITTENSORY_GATE_CHECK_NAME} found a repo-configured hard blocker.`, + summary: `${LOOPOVER_GATE_CHECK_NAME} found a repo-configured hard blocker.`, text: blockerLines.length > 0 ? blockerLines.join("\n") : "A configured hard blocker was found.", }; } @@ -859,7 +859,7 @@ function advisory( ): Advisory { const severity = highestSeverity(findings); const conclusion = conclusionForSeverity(severity, findings); - const title = conclusion === "success" ? "Gittensory advisory passed" : "Gittensory advisory available"; + const title = conclusion === "success" ? "LoopOver advisory passed" : "LoopOver advisory available"; return { id: crypto.randomUUID(), targetType, diff --git a/src/services/maintainer-activation.ts b/src/services/maintainer-activation.ts index 15b0bb6f1a..b9f4c4c1f1 100644 --- a/src/services/maintainer-activation.ts +++ b/src/services/maintainer-activation.ts @@ -103,9 +103,9 @@ export function buildMaintainerActivationPreview(args: { } function buildSummary(evaluated: number, withFindings: number, currentlyActive: boolean): string { - if (evaluated === 0) return "No recent pull requests are cached yet; Gittensory will start surfacing guidance as new PRs arrive."; - const base = `Gittensory reviewed your ${evaluated} most recent pull request(s) and would have surfaced guidance on ${withFindings} of them.`; - return currentlyActive ? `${base} The Gittensory gate is already enabled.` : `${base} Enable advisory mode to start surfacing this guidance automatically.`; + if (evaluated === 0) return "No recent pull requests are cached yet; LoopOver will start surfacing guidance as new PRs arrive."; + const base = `LoopOver reviewed your ${evaluated} most recent pull request(s) and would have surfaced guidance on ${withFindings} of them.`; + return currentlyActive ? `${base} The LoopOver gate is already enabled.` : `${base} Enable advisory mode to start surfacing this guidance automatically.`; } /** diff --git a/src/signals/engine.ts b/src/signals/engine.ts index 1b233adb57..1daa134eb9 100644 --- a/src/signals/engine.ts +++ b/src/signals/engine.ts @@ -34,7 +34,7 @@ import { isDuplicateClusterWinnerByClaim } from "./duplicate-winner"; import { PREFLIGHT_LIMITS } from "./preflight-limits"; import type { UnifiedCollapsible } from "../review/unified-comment"; import { splitAiReviewNits } from "../review/ai-notes"; -import { GITTENSORY_GATE_CHECK_NAME, shouldPublishReviewCheck } from "../review/check-names"; +import { LOOPOVER_GATE_CHECK_NAME, shouldPublishReviewCheck } from "../review/check-names"; import { isAgentConfigured } from "../settings/autonomy"; import { diffFilePriority } from "../review/review-diff"; import type { ImprovementBand, StructuralImprovementAssessment } from "./improvement"; @@ -4423,27 +4423,27 @@ export function buildPublicPrIntelligenceComment(args: { ? "WARNING" : "TIP"; const panelTitle = aiReviewHasBlockers - ? "Gittensory review found blockers" + ? "LoopOver review found blockers" : args.aiReview && !gateBlocking && !gateHeld - ? "Gittensory review approved this PR" + ? "LoopOver review approved this PR" : gateHeld - ? "Gittensory review needs maintainer review" + ? "LoopOver review needs maintainer review" : gateBlocking - ? `${GITTENSORY_GATE_CHECK_NAME} is blocking merge` + ? `${LOOPOVER_GATE_CHECK_NAME} is blocking merge` : hasPublicWarnings || hasRelatedWork - ? "Gittensory found maintainer review notes" - : "Gittensory PR readiness looks good"; + ? "LoopOver found maintainer review notes" + : "LoopOver PR readiness looks good"; const panelSummary = gateBlocking - ? args.gate?.summary ?? (gateConclusion === "action_required" ? "Gittensory cannot evaluate the repo state closely enough for the enabled gate." : "A repo-configured hard blocker was found.") + ? args.gate?.summary ?? (gateConclusion === "action_required" ? "LoopOver cannot evaluate the repo state closely enough for the enabled gate." : "A repo-configured hard blocker was found.") : gateHeld - ? args.gate?.summary ?? "Gittensory is holding this PR for maintainer review." + ? args.gate?.summary ?? "LoopOver is holding this PR for maintainer review." : visibleLinkedDuplicatePrs.length > 0 ? `Same-issue duplicate risk found against ${formatPrRefs(visibleLinkedDuplicatePrs)}. Maintainers should resolve the overlap before review continues.` : hasRelatedWork ? "Scoped related-work signals were found for this PR. They are advisory unless the gate reports a blocker." : genericOssMode ? "Public GitHub metadata was checked for review readiness. Gittensor-specific context appears only when confirmed." - : "Confirmed Gittensor contributor context was checked from public metadata and Gittensory cache."; + : "Confirmed Gittensor contributor context was checked from public metadata and LoopOver cache."; const readinessByKey = new Map(readiness.components.map((component) => [component.key, component])); const validationComponent = readinessByKey.get("validation")!; const changeScopeComponent = readinessByKey.get("change_scope")!; @@ -4553,7 +4553,7 @@ export function buildPublicPrIntelligenceComment(args: { "", "", "", - `- [ ] ${PR_PANEL_RETRIGGER_MARKER} Re-run Gittensory review`, + `- [ ] ${PR_PANEL_RETRIGGER_MARKER} Re-run LoopOver review`, "", "---", footer, diff --git a/src/signals/settings-preview.ts b/src/signals/settings-preview.ts index ccbd2022c9..70573960c8 100644 --- a/src/signals/settings-preview.ts +++ b/src/signals/settings-preview.ts @@ -17,7 +17,7 @@ import { import { buildExtensionPrStatus, type ExtensionPrStatus } from "./extension-contributor-context"; import { REQUIRED_INSTALLATION_PERMISSIONS } from "../github/backfill"; import type { GittensoryFooterEnv } from "../github/footer"; -import { GITTENSORY_GATE_CHECK_NAME, shouldPublishReviewCheck } from "../review/check-names"; +import { LOOPOVER_GATE_CHECK_NAME, shouldPublishReviewCheck } from "../review/check-names"; import { decideReviewEligibility } from "../review/review-eligibility"; import { requiredAgentActionPermissions } from "../settings/agent-execution"; @@ -361,7 +361,7 @@ export function buildRepoSettingsPreview(args: { decision, previewComment, appliedLabel: decision.willLabel ? settings.gittensorLabel : null, - checkRun: decision.willCheckRun ? { willCreate: true, title: "Gittensory Context", detailLevel: settings.checkRunDetailLevel } : null, + checkRun: decision.willCheckRun ? { willCreate: true, title: "LoopOver Context", detailLevel: settings.checkRunDetailLevel } : null, checkRunReadiness: buildSampleCheckRunReadiness({ repoFullName, repo, @@ -583,12 +583,12 @@ function permissionSummary(installation: InstallationHealthSummary | null, missi } function publicOutputsFor(decision: PublicSurfaceDecision, appliedLabel: string | null, settings: RepositorySettings): string[] { - const gateOutput = shouldPublishReviewCheck(settings.reviewCheckMode) ? [`Opt-in ${GITTENSORY_GATE_CHECK_NAME} check run.`] : []; + const gateOutput = shouldPublishReviewCheck(settings.reviewCheckMode) ? [`Opt-in ${LOOPOVER_GATE_CHECK_NAME} check run.`] : []; if (decision.skipped) return [`No comment or label for this sample: ${decision.summary}`, ...gateOutput]; const outputs = [ ...(decision.willComment ? ["One sanitized sticky PR comment."] : []), ...(decision.willLabel ? [`Configured label "${appliedLabel ?? "gittensor"}".`] : []), - ...(decision.willCheckRun ? ["Non-blocking Gittensory Context check run."] : []), + ...(decision.willCheckRun ? ["Non-blocking LoopOver Context check run."] : []), ...gateOutput, ]; return outputs.length > 0 ? outputs : ["No public comment, label, or check run for this sample."]; diff --git a/src/types.ts b/src/types.ts index 3160267582..24c320fa5c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -609,7 +609,7 @@ export type GateRuleMode = "off" | "advisory" | "block"; * value). See {@link RepositorySettings.copycatGateMode}'s doc comment for the currently-inert status. */ export type CopycatGateMode = "off" | "warn" | "label" | "block"; -/** Review-check publish surface (#2852). Controls ONLY whether/how the "Gittensory Orb Review Agent" check-run +/** Review-check publish surface (#2852). Controls ONLY whether/how the "LoopOver Orb Review Agent" check-run * is created/updated -- never the underlying gate evaluation, disposition, comments, labels, audit, or * autonomous merge/close, all of which run identically in every mode (the autonomous decision engine already * excludes the bot's own check-runs from the live CI aggregate it merges/closes against, see @@ -706,8 +706,8 @@ export type RepositorySettings = { commentMode: "off" | "detected_contributors_only" | "all_prs"; publicAudienceMode: "oss_maintainer" | "gittensor_only"; publicSignalLevel: "minimal" | "standard"; - /** Publishes the SEPARATE, always-advisory "Gittensory Context" check-run (#2691) -- entirely independent - * of {@link reviewCheckMode}, which governs the "Gittensory Orb Review Agent" gate check. Despite the + /** Publishes the SEPARATE, always-advisory "LoopOver Context" check-run (#2691) -- entirely independent + * of {@link reviewCheckMode}, which governs the "LoopOver Orb Review Agent" gate check. Despite the * similar name and shape, this is NOT a sibling/legacy-alias of reviewCheckMode; the two checks are * different check-runs with different controlling fields (a mismatch already caused real doc drift -- * see the disambiguation in README's "Check-run and comment surfaces" section). */ @@ -723,7 +723,7 @@ export type RepositorySettings = { * Selection-time only — real-time webhook-driven review is not gated by this and can process any PR at * any time regardless of the chosen order. */ regateSweepOrderMode: "staleness" | "oldest-first"; - /** The actual runtime authority for whether the "Gittensory Orb Review Agent" check-run publishes (#2852). + /** The actual runtime authority for whether the "LoopOver Orb Review Agent" check-run publishes (#2852). * See {@link ReviewCheckMode}. */ reviewCheckMode: ReviewCheckMode; /** Auto-project/milestone matching (#3183). See {@link ProjectMilestoneMatchMode}. Always populated by the DB @@ -950,8 +950,8 @@ export type RepositorySettings = { * settings.advisoryAiRouting` in shared/global or per-repo config. Defaults all-false so every advisory * capability stays on the shared frontier env.AI chain until an operator opts each one in. */ advisoryAiRouting?: AdvisoryAiRoutingConfig | undefined; - /** Governs ONLY the PR comment and label -- never the "Gittensory Context" check ({@link checkRunMode}) - * or the "Gittensory Orb Review Agent" gate check ({@link reviewCheckMode}), which are independent axes + /** Governs ONLY the PR comment and label -- never the "LoopOver Context" check ({@link checkRunMode}) + * or the "LoopOver Orb Review Agent" gate check ({@link reviewCheckMode}), which are independent axes * by design (#2852: the check-run must keep posting for branch-protection/auto-merge to keep working * even when a maintainer wants full public silence). Setting this to `"off"` does NOT silence either * check-run -- see README's "Check-run and comment surfaces, disambiguated" section. */ diff --git a/test/fixtures/engine-parity/predicted-gate/golden/ai-review-gate-mode-inert.json b/test/fixtures/engine-parity/predicted-gate/golden/ai-review-gate-mode-inert.json index 54fbcce8b6..cd2012d3ab 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/ai-review-gate-mode-inert.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/ai-review-gate-mode-inert.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "success", - "title": "Gittensory Orb Review Agent passed", + "title": "LoopOver Orb Review Agent passed", "summary": "No configured hard blocker was found. Advisory findings, if any, stay advisory.", "readinessScore": 95, "blockers": [], diff --git a/test/fixtures/engine-parity/predicted-gate/golden/cla-gate-mode-inert.json b/test/fixtures/engine-parity/predicted-gate/golden/cla-gate-mode-inert.json index 54fbcce8b6..cd2012d3ab 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/cla-gate-mode-inert.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/cla-gate-mode-inert.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "success", - "title": "Gittensory Orb Review Agent passed", + "title": "LoopOver Orb Review Agent passed", "summary": "No configured hard blocker was found. Advisory findings, if any, stay advisory.", "readinessScore": 95, "blockers": [], diff --git a/test/fixtures/engine-parity/predicted-gate/golden/clean-pass-gittensor.json b/test/fixtures/engine-parity/predicted-gate/golden/clean-pass-gittensor.json index 54fbcce8b6..cd2012d3ab 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/clean-pass-gittensor.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/clean-pass-gittensor.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "success", - "title": "Gittensory Orb Review Agent passed", + "title": "LoopOver Orb Review Agent passed", "summary": "No configured hard blocker was found. Advisory findings, if any, stay advisory.", "readinessScore": 95, "blockers": [], diff --git a/test/fixtures/engine-parity/predicted-gate/golden/clean-pass-oss-anti-slop.json b/test/fixtures/engine-parity/predicted-gate/golden/clean-pass-oss-anti-slop.json index 9784386e94..0320dbc466 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/clean-pass-oss-anti-slop.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/clean-pass-oss-anti-slop.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "oss-anti-slop", "conclusion": "success", - "title": "Gittensory Orb Review Agent passed", + "title": "LoopOver Orb Review Agent passed", "summary": "No configured hard blocker was found. Advisory findings, if any, stay advisory.", "readinessScore": 95, "blockers": [], diff --git a/test/fixtures/engine-parity/predicted-gate/golden/duplicate-pr-block.json b/test/fixtures/engine-parity/predicted-gate/golden/duplicate-pr-block.json index 3c265fd5e3..892de7a8eb 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/duplicate-pr-block.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/duplicate-pr-block.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "failure", - "title": "Gittensory Orb Review Agent: Linked issue overlaps another open PR", + "title": "LoopOver Orb Review Agent: Linked issue overlaps another open PR", "summary": "Linked issue overlaps another open PR — Review the related PRs before spending reviewer time on duplicate work.", "readinessScore": 69, "blockers": [ diff --git a/test/fixtures/engine-parity/predicted-gate/golden/first-time-grace-inert.json b/test/fixtures/engine-parity/predicted-gate/golden/first-time-grace-inert.json index 54fbcce8b6..cd2012d3ab 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/first-time-grace-inert.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/first-time-grace-inert.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "success", - "title": "Gittensory Orb Review Agent passed", + "title": "LoopOver Orb Review Agent passed", "summary": "No configured hard blocker was found. Advisory findings, if any, stay advisory.", "readinessScore": 95, "blockers": [], diff --git a/test/fixtures/engine-parity/predicted-gate/golden/guardrail-hold.json b/test/fixtures/engine-parity/predicted-gate/golden/guardrail-hold.json index d5659c375d..792e357b29 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/guardrail-hold.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/guardrail-hold.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "neutral", - "title": "Gittensory Orb Review Agent — held for manual review", + "title": "LoopOver Orb Review Agent — held for manual review", "summary": "Touches a guarded path — held for manual review", "readinessScore": 95, "blockers": [], diff --git a/test/fixtures/engine-parity/predicted-gate/golden/manifest-blocked-path.json b/test/fixtures/engine-parity/predicted-gate/golden/manifest-blocked-path.json index 64342a1f5f..a942a87060 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/manifest-blocked-path.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/manifest-blocked-path.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "success", - "title": "Gittensory Orb Review Agent passed", + "title": "LoopOver Orb Review Agent passed", "summary": "No configured hard blocker was found. Advisory findings, if any, stay advisory.", "readinessScore": 95, "blockers": [], diff --git a/test/fixtures/engine-parity/predicted-gate/golden/merge-readiness-composite-block.json b/test/fixtures/engine-parity/predicted-gate/golden/merge-readiness-composite-block.json index e855350471..6408c08684 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/merge-readiness-composite-block.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/merge-readiness-composite-block.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "failure", - "title": "Gittensory Orb Review Agent: No linked issue detected", + "title": "LoopOver Orb Review Agent: No linked issue detected", "summary": "No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.", "readinessScore": 80, "blockers": [ diff --git a/test/fixtures/engine-parity/predicted-gate/golden/missing-linked-issue-block.json b/test/fixtures/engine-parity/predicted-gate/golden/missing-linked-issue-block.json index e855350471..6408c08684 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/missing-linked-issue-block.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/missing-linked-issue-block.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "failure", - "title": "Gittensory Orb Review Agent: No linked issue detected", + "title": "LoopOver Orb Review Agent: No linked issue detected", "summary": "No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.", "readinessScore": 80, "blockers": [ diff --git a/test/fixtures/engine-parity/predicted-gate/golden/path-gated-check-with-paths.json b/test/fixtures/engine-parity/predicted-gate/golden/path-gated-check-with-paths.json index 55ac2417b6..08bd5fda32 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/path-gated-check-with-paths.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/path-gated-check-with-paths.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "failure", - "title": "Gittensory Orb Review Agent: Pre-merge check not satisfied: Tests for src", + "title": "LoopOver Orb Review Agent: Pre-merge check not satisfied: Tests for src", "summary": "Pre-merge check not satisfied: Tests for src — Update the PR to satisfy the check, then re-run the gate.", "readinessScore": 95, "blockers": [ diff --git a/test/fixtures/engine-parity/predicted-gate/golden/path-gated-check-without-paths.json b/test/fixtures/engine-parity/predicted-gate/golden/path-gated-check-without-paths.json index 54fbcce8b6..cd2012d3ab 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/path-gated-check-without-paths.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/path-gated-check-without-paths.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "success", - "title": "Gittensory Orb Review Agent passed", + "title": "LoopOver Orb Review Agent passed", "summary": "No configured hard blocker was found. Advisory findings, if any, stay advisory.", "readinessScore": 95, "blockers": [], diff --git a/test/fixtures/engine-parity/predicted-gate/golden/readiness-warning.json b/test/fixtures/engine-parity/predicted-gate/golden/readiness-warning.json index 794742826c..a2f2617459 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/readiness-warning.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/readiness-warning.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "success", - "title": "Gittensory Orb Review Agent passed", + "title": "LoopOver Orb Review Agent passed", "summary": "No configured hard blocker was found. Advisory findings, if any, stay advisory.", "readinessScore": 80, "blockers": [], diff --git a/test/fixtures/engine-parity/predicted-gate/golden/self-authored-linked-issue-block.json b/test/fixtures/engine-parity/predicted-gate/golden/self-authored-linked-issue-block.json index dfbbcd7eee..e13c0ee9da 100644 --- a/test/fixtures/engine-parity/predicted-gate/golden/self-authored-linked-issue-block.json +++ b/test/fixtures/engine-parity/predicted-gate/golden/self-authored-linked-issue-block.json @@ -3,7 +3,7 @@ "basis": "public_config", "pack": "gittensor", "conclusion": "failure", - "title": "Gittensory Orb Review Agent: PR author also opened the linked issue", + "title": "LoopOver Orb Review Agent: PR author also opened the linked issue", "summary": "PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.", "readinessScore": 95, "blockers": [ diff --git a/test/unit/ai-review-advisory.test.ts b/test/unit/ai-review-advisory.test.ts index d445d00c06..99a39db160 100644 --- a/test/unit/ai-review-advisory.test.ts +++ b/test/unit/ai-review-advisory.test.ts @@ -740,7 +740,7 @@ describe("runAiReviewForAdvisory", () => { cacheable: false, findings: [expect.objectContaining({ code: "ai_review_inconclusive" })], }); - expect(result?.notes).toContain("AI review is already running for this PR head in another Gittensory pass"); + expect(result?.notes).toContain("AI review is already running for this PR head in another LoopOver pass"); expect(adv.findings.map((f) => f.code)).toEqual(["ai_review_inconclusive"]); }); diff --git a/test/unit/backfill-2.test.ts b/test/unit/backfill-2.test.ts index 06291c7726..e315d59ed4 100644 --- a/test/unit/backfill-2.test.ts +++ b/test/unit/backfill-2.test.ts @@ -58,7 +58,7 @@ import { setGitHubResponseCache, type CachedGitHubResponse, } from "../../src/github/client"; -import { GITTENSORY_CONTEXT_CHECK_NAME, GITTENSORY_GATE_CHECK_NAME, GITTENSORY_LEGACY_GATE_CHECK_NAME } from "../../src/review/check-names"; +import { GITTENSORY_LEGACY_GATE_CHECK_NAME, LOOPOVER_CONTEXT_CHECK_NAME, LOOPOVER_GATE_CHECK_NAME } from "../../src/review/check-names"; import { normalizeRegistryPayload } from "../../src/registry/normalize"; import { persistRegistrySnapshot } from "../../src/registry/sync"; import { renderMetrics, resetMetrics } from "../../src/selfhost/metrics"; @@ -562,9 +562,9 @@ describe("GitHub backfill", () => { { name: "test", status: "completed", conclusion: "success" }, // BOTH bot-posted checks, still in_progress (posted but not yet concluded). Counting EITHER would // defer the very review that concludes it — the self-deadlock that froze green-CI PRs as "CI pending". - { name: "Gittensory Orb Review Agent", status: "in_progress", conclusion: null, app: { slug: "gittensory" } }, + { name: "LoopOver Orb Review Agent", status: "in_progress", conclusion: null, app: { slug: "gittensory" } }, { name: "Gittensory Gate", status: "in_progress", conclusion: null, app: { slug: "gittensory" } }, - { name: "Gittensory Context", status: "in_progress", conclusion: null, app: { slug: "gittensory" } }, + { name: "LoopOver Context", status: "in_progress", conclusion: null, app: { slug: "gittensory" } }, ], }); } @@ -573,7 +573,7 @@ describe("GitHub backfill", () => { }); // Both bot checks are excluded from the CI wait even if listed among the required contexts. - const aggregate = await fetchLiveCiAggregate(env, "JSONbored/metagraphed", "headsha", "public-token", new Set(["test", "Gittensory Orb Review Agent", "Gittensory Gate", "Gittensory Context"])); + const aggregate = await fetchLiveCiAggregate(env, "JSONbored/metagraphed", "headsha", "public-token", new Set(["test", "LoopOver Orb Review Agent", "Gittensory Gate", "LoopOver Context"])); expect(aggregate.ciState).toBe("passed"); // would be "pending" if either in_progress bot check were counted expect(aggregate.failingDetails).toEqual([]); @@ -587,7 +587,7 @@ describe("GitHub backfill", () => { return Response.json({ check_runs: [ { name: "test", status: "completed", conclusion: "success", app: { slug: "github-actions" } }, - { name: "Gittensory Orb Review Agent", status: "completed", conclusion: "failure", output: { title: "External gate failed" }, app: { slug: "external-ci" } }, + { name: "LoopOver Orb Review Agent", status: "completed", conclusion: "failure", output: { title: "External gate failed" }, app: { slug: "external-ci" } }, ], }); } @@ -595,10 +595,10 @@ describe("GitHub backfill", () => { return new Response("not found", { status: 404 }); }); - const aggregate = await fetchLiveCiAggregate(env, "JSONbored/gittensory", "abc123", "public-token", new Set(["test", "Gittensory Orb Review Agent"])); + const aggregate = await fetchLiveCiAggregate(env, "JSONbored/gittensory", "abc123", "public-token", new Set(["test", "LoopOver Orb Review Agent"])); expect(aggregate.ciState).toBe("failed"); - expect(aggregate.failingDetails).toEqual([expect.objectContaining({ name: "Gittensory Orb Review Agent", summary: "External gate failed" })]); + expect(aggregate.failingDetails).toEqual([expect.objectContaining({ name: "LoopOver Orb Review Agent", summary: "External gate failed" })]); }); it("does not skip a same-slug bot-owned-named check-run when GITHUB_APP_SLUG is unset (no self-hoster crash)", async () => { @@ -610,17 +610,17 @@ describe("GitHub backfill", () => { const url = input.toString(); if (url.includes("/check-runs?")) { return Response.json({ - check_runs: [{ name: "Gittensory Orb Review Agent", status: "completed", conclusion: "failure", output: { title: "Real gate failure" }, app: { slug: "gittensory" } }], + check_runs: [{ name: "LoopOver Orb Review Agent", status: "completed", conclusion: "failure", output: { title: "Real gate failure" }, app: { slug: "gittensory" } }], }); } if (url.includes("/status?")) return Response.json({ statuses: [] }); return new Response("not found", { status: 404 }); }); - const aggregate = await fetchLiveCiAggregate(env, "JSONbored/gittensory", "abc123", "public-token", new Set(["Gittensory Orb Review Agent"])); + const aggregate = await fetchLiveCiAggregate(env, "JSONbored/gittensory", "abc123", "public-token", new Set(["LoopOver Orb Review Agent"])); expect(aggregate.ciState).toBe("failed"); - expect(aggregate.failingDetails).toEqual([expect.objectContaining({ name: "Gittensory Orb Review Agent", summary: "Real gate failure" })]); + expect(aggregate.failingDetails).toEqual([expect.objectContaining({ name: "LoopOver Orb Review Agent", summary: "Real gate failure" })]); }); it("does not ignore classic statuses named like the Gate", async () => { @@ -628,14 +628,14 @@ describe("GitHub backfill", () => { vi.stubGlobal("fetch", async (input: RequestInfo | URL) => { const url = input.toString(); if (url.includes("/check-runs?")) return Response.json({ check_runs: [{ name: "test", status: "completed", conclusion: "success", app: { slug: "github-actions" } }] }); - if (url.includes("/status?")) return Response.json({ statuses: [{ context: "Gittensory Orb Review Agent", state: "failure", description: "External status failed" }] }); + if (url.includes("/status?")) return Response.json({ statuses: [{ context: "LoopOver Orb Review Agent", state: "failure", description: "External status failed" }] }); return new Response("not found", { status: 404 }); }); const aggregate = await fetchLiveCiAggregate(env, "JSONbored/gittensory", "abc123", "public-token", null); expect(aggregate.ciState).toBe("failed"); - expect(aggregate.failingDetails).toEqual([expect.objectContaining({ name: "Gittensory Orb Review Agent", summary: "External status failed" })]); + expect(aggregate.failingDetails).toEqual([expect.objectContaining({ name: "LoopOver Orb Review Agent", summary: "External status failed" })]); }); it("treats a required context that never ran (absent from results) as pending, not passed", async () => { @@ -675,7 +675,7 @@ describe("GitHub backfill", () => { return Response.json({ check_runs: [ { name: "validate", status: "completed", conclusion: "success", app: { slug: "github-actions" } }, - { name: "Gittensory Orb Review Agent", status: "in_progress", conclusion: null, app: { slug: "gittensory" } }, + { name: "LoopOver Orb Review Agent", status: "in_progress", conclusion: null, app: { slug: "gittensory" } }, ], }); } @@ -683,9 +683,9 @@ describe("GitHub backfill", () => { return new Response("not found", { status: 404 }); }); - const aggregate = await fetchLiveCiAggregate(env, "JSONbored/gittensory", "sha", "tok", new Set(["validate", "Gittensory Orb Review Agent"])); + const aggregate = await fetchLiveCiAggregate(env, "JSONbored/gittensory", "sha", "tok", new Set(["validate", "LoopOver Orb Review Agent"])); - // "Gittensory Orb Review Agent" is a bot check: present in results (so not absent), excluded from gate logic → passed + // "LoopOver Orb Review Agent" is a bot check: present in results (so not absent), excluded from gate logic → passed expect(aggregate.ciState).toBe("passed"); }); @@ -1076,9 +1076,9 @@ describe("GitHub backfill", () => { const requiredContexts = mergeRequiredCiContexts(null, [ "build", - GITTENSORY_GATE_CHECK_NAME, + LOOPOVER_GATE_CHECK_NAME, GITTENSORY_LEGACY_GATE_CHECK_NAME, - GITTENSORY_CONTEXT_CHECK_NAME, + LOOPOVER_CONTEXT_CHECK_NAME, ]); const aggregate = await fetchLiveCiAggregate(env, "JSONbored/gittensory", "abc123", "public-token", requiredContexts); diff --git a/test/unit/backfill.test.ts b/test/unit/backfill.test.ts index eafdd77dfb..4743cff473 100644 --- a/test/unit/backfill.test.ts +++ b/test/unit/backfill.test.ts @@ -59,7 +59,6 @@ import { setGitHubResponseCache, type CachedGitHubResponse, } from "../../src/github/client"; -import { GITTENSORY_CONTEXT_CHECK_NAME, GITTENSORY_GATE_CHECK_NAME, GITTENSORY_LEGACY_GATE_CHECK_NAME } from "../../src/review/check-names"; import { normalizeRegistryPayload } from "../../src/registry/normalize"; import { persistRegistrySnapshot } from "../../src/registry/sync"; import { renderMetrics, resetMetrics } from "../../src/selfhost/metrics"; @@ -1022,8 +1021,8 @@ describe("GitHub backfill", () => { }); it("REGRESSION (#5355): requires Checks write for a repo with only reviewCheckMode (the Orb Review Agent check) set, not checkRunMode", async () => { - // Before the fix, requiresChecks only looked at checkRunMode ("Gittensory Context" check) and missed - // the separate reviewCheckMode axis ("Gittensory Orb Review Agent" check) entirely -- so an installation + // Before the fix, requiresChecks only looked at checkRunMode ("LoopOver Context" check) and missed + // the separate reviewCheckMode axis ("LoopOver Orb Review Agent" check) entirely -- so an installation // whose repos only ever published the review-agent check (true for JSONbored's own 3 production repos, // none of which set checkRunMode) was never flagged as needing the Checks permission. const env = createTestEnv({ GITHUB_APP_PRIVATE_KEY: await generatePrivateKeyPem() }); diff --git a/test/unit/check-names.test.ts b/test/unit/check-names.test.ts index 0106576bde..944619088d 100644 --- a/test/unit/check-names.test.ts +++ b/test/unit/check-names.test.ts @@ -1,14 +1,22 @@ import { describe, expect, it } from "vitest"; import { - GITTENSORY_CONTEXT_CHECK_NAME, - GITTENSORY_GATE_CHECK_NAME, + GITTENSORY_LEGACY_CONTEXT_CHECK_NAME, GITTENSORY_LEGACY_GATE_CHECK_NAME, + GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME, + LOOPOVER_CONTEXT_CHECK_NAME, + LOOPOVER_GATE_CHECK_NAME, shouldPublishReviewCheck, } from "../../src/review/check-names"; -describe("Gittensory GitHub check names", () => { +describe("LoopOver GitHub check names", () => { it("exports stable, distinct check-run titles", () => { - const names = [GITTENSORY_CONTEXT_CHECK_NAME, GITTENSORY_GATE_CHECK_NAME, GITTENSORY_LEGACY_GATE_CHECK_NAME]; + const names = [ + LOOPOVER_CONTEXT_CHECK_NAME, + LOOPOVER_GATE_CHECK_NAME, + GITTENSORY_LEGACY_GATE_CHECK_NAME, + GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME, + GITTENSORY_LEGACY_CONTEXT_CHECK_NAME, + ]; expect(new Set(names).size).toBe(names.length); for (const name of names) { expect(name.trim()).toBe(name); @@ -17,9 +25,11 @@ describe("Gittensory GitHub check names", () => { }); it("keeps the orb review agent as the canonical gate check name", () => { - expect(GITTENSORY_GATE_CHECK_NAME).toBe("Gittensory Orb Review Agent"); + expect(LOOPOVER_GATE_CHECK_NAME).toBe("LoopOver Orb Review Agent"); + expect(LOOPOVER_CONTEXT_CHECK_NAME).toBe("LoopOver Context"); expect(GITTENSORY_LEGACY_GATE_CHECK_NAME).toBe("Gittensory Gate"); - expect(GITTENSORY_CONTEXT_CHECK_NAME).toBe("Gittensory Context"); + expect(GITTENSORY_LEGACY_ORB_GATE_CHECK_NAME).toBe("Gittensory Orb Review Agent"); + expect(GITTENSORY_LEGACY_CONTEXT_CHECK_NAME).toBe("Gittensory Context"); }); }); diff --git a/test/unit/content-lane-wire.test.ts b/test/unit/content-lane-wire.test.ts index aafd9d1620..1748e7e344 100644 --- a/test/unit/content-lane-wire.test.ts +++ b/test/unit/content-lane-wire.test.ts @@ -76,7 +76,7 @@ describe("applySurfaceGate", () => { }; const genericHold = gate({ conclusion: "neutral", - title: "Gittensory Orb Review Agent — held for manual review", + title: "LoopOver Orb Review Agent — held for manual review", summary: "Large change — held for manual review", blockers: [], warnings: [oversized], diff --git a/test/unit/e2e-test-gen-render.test.ts b/test/unit/e2e-test-gen-render.test.ts index 60656b4fe4..c17e880035 100644 --- a/test/unit/e2e-test-gen-render.test.ts +++ b/test/unit/e2e-test-gen-render.test.ts @@ -91,12 +91,12 @@ describe("buildE2eTestGenCommentBody", () => { // pointing at GITTENSORY_SITE_URL. it("#4613: honors env.PUBLIC_SITE_ORIGIN in the footer attribution link", () => { const selfHosted = buildE2eTestGenCommentBody({ env: { PUBLIC_SITE_ORIGIN: "https://gittensory.example.org" }, actor: "maintainer", testSource: "test('x', () => {});" }); - expect(selfHosted).toContain("Checked by [Gittensory](https://gittensory.example.org)"); + expect(selfHosted).toContain("Checked by [LoopOver](https://gittensory.example.org)"); expect(selfHosted).not.toContain(GITTENSORY_SITE_URL); }); it("#4613: falls back to GITTENSORY_SITE_URL when PUBLIC_SITE_ORIGIN is unset", () => { const defaultHosted = buildE2eTestGenCommentBody({ env: {}, actor: "maintainer", testSource: "test('x', () => {});" }); - expect(defaultHosted).toContain(`Checked by [Gittensory](${GITTENSORY_SITE_URL})`); + expect(defaultHosted).toContain(`Checked by [LoopOver](${GITTENSORY_SITE_URL})`); }); }); diff --git a/test/unit/focus-manifest-loader.test.ts b/test/unit/focus-manifest-loader.test.ts index ae62c85c56..907371dcfe 100644 --- a/test/unit/focus-manifest-loader.test.ts +++ b/test/unit/focus-manifest-loader.test.ts @@ -540,6 +540,6 @@ describe("focus-manifest loader — container-private config (self-host)", () => const manifest = await loadRepoFocusManifest(env, "owner/private"); expect(manifest.gate.enabled).toBe(true); expect(manifest.gate.checkMode).toBeNull(); - expect(manifest.warnings.some((w) => /gate\.enabled.*only controls whether the Gittensory Orb Review Agent check-run publishes/.test(w))).toBe(true); + expect(manifest.warnings.some((w) => /gate\.enabled.*only controls whether the LoopOver Orb Review Agent check-run publishes/.test(w))).toBe(true); }); }); diff --git a/test/unit/focus-manifest.test.ts b/test/unit/focus-manifest.test.ts index 61907a5a27..6712c580c7 100644 --- a/test/unit/focus-manifest.test.ts +++ b/test/unit/focus-manifest.test.ts @@ -1177,11 +1177,11 @@ describe("parseFocusManifest gate config", () => { // comment, label, or close behavior. Caused two real incidents under this exact ambiguity. it("warns that gate.enabled is ambiguous when set without an explicit gate.checkMode, regardless of value (#5355)", () => { const enabledTrue = parseFocusManifest({ gate: { enabled: true } }); - expect(enabledTrue.warnings.some((w) => /gate\.enabled.*only controls whether the Gittensory Orb Review Agent check-run publishes/.test(w))).toBe(true); + expect(enabledTrue.warnings.some((w) => /gate\.enabled.*only controls whether the LoopOver Orb Review Agent check-run publishes/.test(w))).toBe(true); // Unlike firstTimeContributorGrace, both true AND false are equally ambiguous here -- both map through // the same silent enabled -> reviewCheckMode alias, so an explicit false is just as worth flagging. const enabledFalse = parseFocusManifest({ gate: { enabled: false } }); - expect(enabledFalse.warnings.some((w) => /gate\.enabled.*only controls whether the Gittensory Orb Review Agent check-run publishes/.test(w))).toBe(true); + expect(enabledFalse.warnings.some((w) => /gate\.enabled.*only controls whether the LoopOver Orb Review Agent check-run publishes/.test(w))).toBe(true); }); it("does not warn about gate.enabled when checkMode is also set explicitly (the documented, encouraged pairing)", () => { diff --git a/test/unit/footer.test.ts b/test/unit/footer.test.ts index 0fe71d1c51..5205095ac6 100644 --- a/test/unit/footer.test.ts +++ b/test/unit/footer.test.ts @@ -56,18 +56,18 @@ describe("gittensory public-comment footer", () => { // and the Gittensor register link (a separate, shared network) is never rebranded. it("#4613: uses PUBLIC_SITE_ORIGIN in the attribution link when configured", () => { const footer = gittensoryFooter({ PUBLIC_SITE_ORIGIN: "https://gittensory.example.org" }); - expect(footer).toContain("Checked by [Gittensory](https://gittensory.example.org)"); + expect(footer).toContain("Checked by [LoopOver](https://gittensory.example.org)"); expect(footer).not.toContain(GITTENSORY_SITE_URL); expect(footer).toContain(GITTENSOR_HOME_URL); // the network link is never rebranded }); it("#4613: falls back to GITTENSORY_SITE_URL when PUBLIC_SITE_ORIGIN is unset", () => { - expect(gittensoryFooter({})).toContain(`Checked by [Gittensory](${GITTENSORY_SITE_URL})`); + expect(gittensoryFooter({})).toContain(`Checked by [LoopOver](${GITTENSORY_SITE_URL})`); }); it("#4613: uses PUBLIC_SITE_ORIGIN in the attribution link on the customText branch too", () => { const footer = gittensoryFooter({ PUBLIC_SITE_ORIGIN: "https://gittensory.example.org" }, { customText: "Thanks for contributing!" }); - expect(footer).toContain("Checked by [Gittensory](https://gittensory.example.org)"); + expect(footer).toContain("Checked by [LoopOver](https://gittensory.example.org)"); expect(footer).not.toContain(GITTENSORY_SITE_URL); }); }); diff --git a/test/unit/github-app.test.ts b/test/unit/github-app.test.ts index 22d22b03a5..70e2fca371 100644 --- a/test/unit/github-app.test.ts +++ b/test/unit/github-app.test.ts @@ -59,9 +59,9 @@ describe("GitHub check runs", () => { conclusion: string; output: { title: string; text: string }; }; - expect(body.name).toBe("Gittensory Context"); + expect(body.name).toBe("LoopOver Context"); expect(body.conclusion).toBe("neutral"); - expect(body.output.title).toBe("Gittensory context posted"); + expect(body.output.title).toBe("LoopOver context posted"); expect(body.output.text).not.toMatch( /linked issue|reviewability|reward|farming|wallet|hotkey|trust score/i, ); @@ -84,7 +84,7 @@ describe("GitHub check runs", () => { headSha: "abc123", conclusion: "neutral", severity: "warning", - title: "Gittensory advisory available", + title: "LoopOver advisory available", summary: "1 advisory finding generated.", findings: [ { @@ -1064,9 +1064,9 @@ describe("GitHub check runs", () => { conclusion: string; output: { title: string; text: string }; }; - expect(body.name).toBe("Gittensory Context"); + expect(body.name).toBe("LoopOver Context"); expect(body.conclusion).toBe("success"); - expect(body.output.title).toBe("Gittensory context checked"); + expect(body.output.title).toBe("LoopOver context checked"); expect(body.output.text).not.toMatch( /reviewability|reward|farming|wallet|hotkey|trust score/i, ); @@ -1089,7 +1089,7 @@ describe("GitHub check runs", () => { headSha: "abc123", conclusion: "success", severity: "info", - title: "Gittensory advisory passed", + title: "LoopOver advisory passed", summary: "Pull request advisory generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -1136,7 +1136,7 @@ describe("GitHub check runs", () => { headSha: "def456", conclusion: "neutral", severity: "warning", - title: "Gittensory advisory available", + title: "LoopOver advisory available", summary: "1 advisory finding generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -1209,7 +1209,7 @@ describe("GitHub check runs", () => { headSha: "crossapp123", conclusion: "neutral", severity: "info", - title: "Gittensory advisory", + title: "LoopOver advisory", summary: "ok", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -1252,7 +1252,7 @@ describe("GitHub check runs", () => { expect(isCrossAppCheckRunError(null)).toBe(false); // non-object }); - it("creates a failing opt-in Gittensory Orb Review Agent check for merge blockers", async () => { + it("creates a failing opt-in LoopOver Orb Review Agent check for merge blockers", async () => { const privateKey = await generatePrivateKeyPem(); let capturedBody: { name?: string; @@ -1291,7 +1291,7 @@ describe("GitHub check runs", () => { headSha: "gate123", conclusion: "neutral", severity: "warning", - title: "Gittensory advisory available", + title: "LoopOver advisory available", summary: "1 advisory finding generated.", findings: [ { @@ -1309,9 +1309,9 @@ describe("GitHub check runs", () => { expect(result).toMatchObject({ kind: "published", id: 88 }); expect(capturedBody).toMatchObject({ - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", conclusion: "failure", - output: { title: "Gittensory Orb Review Agent: No linked issue detected" }, + output: { title: "LoopOver Orb Review Agent: No linked issue detected" }, }); expect(capturedBody.output?.text).toContain("Link the issue before merge."); expect(capturedBody.output?.text).not.toMatch( @@ -1353,9 +1353,9 @@ describe("GitHub check runs", () => { expect(result).toMatchObject({ kind: "published", id: 89 }); expect(capturedBody).toMatchObject({ - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "in_progress", - output: { title: "Gittensory Orb Review Agent is evaluating" }, + output: { title: "LoopOver Orb Review Agent is evaluating" }, }); expect(capturedBody).not.toHaveProperty("conclusion"); // The Gate blocks every author the same on a configured blocker (confirmed status no longer gates the verdict). @@ -1384,7 +1384,7 @@ describe("GitHub check runs", () => { return Response.json({ token: "installation-token" }); if (url.includes("/commits/legacy-pending/check-runs")) { const checkName = new URL(url).searchParams.get("check_name"); - if (checkName === "Gittensory Orb Review Agent") + if (checkName === "LoopOver Orb Review Agent") return Response.json({ total_count: 0, check_runs: [] }); if (checkName === "Gittensory Gate") return Response.json({ @@ -1415,7 +1415,7 @@ describe("GitHub check runs", () => { expect(result).toMatchObject({ kind: "published", id: 89 }); expect(newCheckBody).toMatchObject({ - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "in_progress", }); expect(newCheckBody).not.toHaveProperty("conclusion"); @@ -1425,11 +1425,11 @@ describe("GitHub check runs", () => { conclusion: "neutral", output: { title: - "Gittensory Orb Review Agent superseded this legacy check", + "LoopOver Orb Review Agent superseded this legacy check", }, }); expect(legacyPatchBody.output?.text).toContain( - "Use Gittensory Orb Review Agent", + "Use LoopOver Orb Review Agent", ); }); @@ -1447,7 +1447,7 @@ describe("GitHub check runs", () => { return Response.json({ token: "installation-token" }); if (url.includes("/commits/legacy-completed/check-runs")) { const checkName = new URL(url).searchParams.get("check_name"); - if (checkName === "Gittensory Orb Review Agent") + if (checkName === "LoopOver Orb Review Agent") return Response.json({ total_count: 0, check_runs: [] }); if (checkName === "Gittensory Gate") return Response.json({ @@ -1476,7 +1476,7 @@ describe("GitHub check runs", () => { expect(result).toMatchObject({ kind: "published", id: 91 }); expect(newCheckBody).toMatchObject({ - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "in_progress", }); expect(calls.some((call) => call.includes("/check-runs/323"))).toBe(false); @@ -1495,7 +1495,7 @@ describe("GitHub check runs", () => { return Response.json({ token: "installation-token" }); if (url.includes("/commits/legacy-cleanup-fails/check-runs")) { const checkName = new URL(url).searchParams.get("check_name"); - if (checkName === "Gittensory Orb Review Agent") + if (checkName === "LoopOver Orb Review Agent") return Response.json({ total_count: 0, check_runs: [] }); if (checkName === "Gittensory Gate") return Response.json({ @@ -1525,7 +1525,7 @@ describe("GitHub check runs", () => { expect(result).toMatchObject({ kind: "published", id: 90 }); expect(newCheckBody).toMatchObject({ - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "in_progress", }); expect(warn.mock.calls.some((call) => String(call[0]).includes("legacy_gate_check_finalize_failed"))).toBe(true); @@ -1604,10 +1604,10 @@ describe("GitHub check runs", () => { calls.some((call) => call.includes("/commits/final123/check-runs")), ).toBe(false); expect(capturedBody).toMatchObject({ - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", - output: { title: "Gittensory Orb Review Agent passed" }, + output: { title: "LoopOver Orb Review Agent passed" }, }); }); @@ -1677,7 +1677,7 @@ describe("GitHub check runs", () => { if (url.includes("/commits/pending-existing/check-runs")) { return Response.json({ total_count: 1, - check_runs: [{ id: 333, name: "Gittensory Orb Review Agent", status: "in_progress" }], + check_runs: [{ id: 333, name: "LoopOver Orb Review Agent", status: "in_progress" }], }); } if (url.includes("/check-runs/333")) { @@ -1725,7 +1725,7 @@ describe("GitHub check runs", () => { check_runs: [ { id: 444, - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "completed", conclusion: "failure", }, @@ -1760,7 +1760,7 @@ describe("GitHub check runs", () => { expect(calls.some((call) => call.includes("/check-runs/444"))).toBe(false); expect(capturedBody).toMatchObject({ status: "in_progress", - output: { title: "Gittensory Orb Review Agent is evaluating" }, + output: { title: "LoopOver Orb Review Agent is evaluating" }, }); expect(capturedBody).not.toHaveProperty("conclusion"); }); @@ -1804,7 +1804,7 @@ describe("GitHub check runs", () => { status: "completed", conclusion: "skipped", output: { - title: "Gittensory Orb Review Agent skipped", + title: "LoopOver Orb Review Agent skipped", summary: "Merged before Gittensory finished.", }, }); @@ -1888,10 +1888,10 @@ describe("GitHub check runs", () => { name?: string; output?: { annotations?: Array<{ path: string; title: string }> }; }; - if (body.name === "Gittensory Context") contextBody = body; - if (body.name === "Gittensory Orb Review Agent") gateBody = body; + if (body.name === "LoopOver Context") contextBody = body; + if (body.name === "LoopOver Orb Review Agent") gateBody = body; return Response.json( - { id: body.name === "Gittensory Orb Review Agent" ? 90 : 77 }, + { id: body.name === "LoopOver Orb Review Agent" ? 90 : 77 }, { status: 201 }, ); } @@ -1909,7 +1909,7 @@ describe("GitHub check runs", () => { headSha: "bbb999", conclusion: "neutral", severity: "warning", - title: "Gittensory advisory available", + title: "LoopOver advisory available", summary: "1 advisory finding generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -1973,7 +1973,7 @@ describe("GitHub check runs", () => { if (url.includes("/commits/")) return Response.json({ total_count: 1, - check_runs: [{ id: 77, name: "Gittensory Context" }], + check_runs: [{ id: 77, name: "LoopOver Context" }], }); if (url.includes("/check-runs/77")) { patchedBody = JSON.parse(String(init?.body)) as { @@ -1998,7 +1998,7 @@ describe("GitHub check runs", () => { headSha: "bbb999", conclusion: "neutral", severity: "warning", - title: "Gittensory advisory available", + title: "LoopOver advisory available", summary: "1 advisory finding generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -2072,7 +2072,7 @@ describe("GitHub check runs", () => { headSha: "bbb999", conclusion: "neutral", severity: "warning", - title: "Gittensory advisory available", + title: "LoopOver advisory available", summary: "1 advisory finding generated.", findings: [ { @@ -2130,7 +2130,7 @@ describe("GitHub check runs", () => { headSha: "fff111", conclusion: "neutral", severity: "warning", - title: "Gittensory advisory available", + title: "LoopOver advisory available", summary: "1 advisory finding generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -2168,7 +2168,7 @@ describe("GitHub check runs", () => { headSha: "aaa000", conclusion: "neutral", severity: "warning", - title: "Gittensory advisory available", + title: "LoopOver advisory available", summary: "1 advisory finding generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -2201,7 +2201,7 @@ describe("GitHub check runs", () => { headSha: "string-error", conclusion: "neutral", severity: "warning", - title: "Gittensory advisory available", + title: "LoopOver advisory available", summary: "1 advisory finding generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -2225,7 +2225,7 @@ describe("GitHub check runs", () => { pullNumber: 1, conclusion: "success", severity: "info", - title: "Gittensory advisory passed", + title: "LoopOver advisory passed", summary: "Pull request advisory generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -2246,7 +2246,7 @@ describe("GitHub check runs", () => { headSha: "abc123", conclusion: "success", severity: "info", - title: "Gittensory advisory passed", + title: "LoopOver advisory passed", summary: "Pull request advisory generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", @@ -2401,7 +2401,7 @@ function gateAdvisory(headSha: string): Advisory { headSha, conclusion: "success", severity: "info", - title: "Gittensory advisory passed", + title: "LoopOver advisory passed", summary: "Pull request advisory generated.", findings: [], generatedAt: "2026-05-22T00:00:00.000Z", diff --git a/test/unit/predicted-gate.test.ts b/test/unit/predicted-gate.test.ts index d995e09cb0..d0598213bf 100644 --- a/test/unit/predicted-gate.test.ts +++ b/test/unit/predicted-gate.test.ts @@ -73,7 +73,7 @@ describe("buildPredictedGateVerdict", () => { expect(result.conclusion).toBe("failure"); expect(result.blockers.some((b) => b.code === "duplicate_pr_risk")).toBe(true); // Public-safe: blocker text carries a fix and no raw internal markers. - expect(result.title.toLowerCase()).toContain("gittensory orb review agent"); + expect(result.title.toLowerCase()).toContain("loopover orb review agent"); }); it("does NOT raise duplicate_pr_risk for an open PR in a different repo sharing the same issue number (repo-scoped parity)", () => { diff --git a/test/unit/queue-2.test.ts b/test/unit/queue-2.test.ts index 734339b17b..48b2935e52 100644 --- a/test/unit/queue-2.test.ts +++ b/test/unit/queue-2.test.ts @@ -1297,7 +1297,7 @@ describe("queue processors", () => { expect(commentBodies.length).toBeGreaterThanOrEqual(2); expect(commentBodies[0]).toContain("is reviewing"); const finalComment = commentBodies.find((body) => !body.includes("is reviewing")); - expect(finalComment).toContain("Gittensory review needs maintainer review"); + expect(finalComment).toContain("LoopOver review needs maintainer review"); expect(finalComment).toContain("AI review could not be completed for this PR head"); expect(finalComment).not.toContain("The AI reviewer returned public review text but not the expected structured verdict"); // #regate-churn: the "AI review could not be completed" outcome is now PERSISTED (so a repeated scheduled @@ -1395,8 +1395,8 @@ describe("queue processors", () => { // The losing pass never called the AI a second time — it deferred to the lock instead of double-spending. expect(aiCalls).toBe(0); const finalComment = commentBodies.find((body) => !body.includes("is reviewing")); - expect(finalComment).toContain("Gittensory review needs maintainer review"); - expect(finalComment).toContain("AI review is already running for this PR head in another Gittensory pass"); + expect(finalComment).toContain("LoopOver review needs maintainer review"); + expect(finalComment).toContain("AI review is already running for this PR head in another LoopOver pass"); // A lock-contention placeholder must never be persisted at all (not even non-durably, #regate-churn) — the // concurrent pass it deferred to writes the REAL result within seconds, and replaying this placeholder for // the rest of a bounded-cooldown window would mask that real result long after the race resolved. @@ -1563,7 +1563,7 @@ describe("queue processors", () => { repoFullName: "owner/agent-repo", pullNumber: number, headSha, - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {}, @@ -1719,7 +1719,7 @@ describe("queue processors", () => { repoFullName: "owner/agent-repo", pullNumber: number, headSha, - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {}, @@ -1751,7 +1751,7 @@ describe("queue processors", () => { repoFullName: "owner/agent-repo", pullNumber: 2, headSha: "ordinary-2", - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {}, @@ -2283,7 +2283,7 @@ describe("queue processors", () => { repoFullName: "owner/agent-repo", pullNumber: 7, headSha: "a7", - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {}, @@ -2749,7 +2749,7 @@ describe("queue processors", () => { repoFullName: "owner/agent-repo", pullNumber: 7, headSha: "a7", - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {}, @@ -3190,7 +3190,7 @@ describe("queue processors", () => { if (url.includes("/commits/gate123/check-runs")) return Response.json({ total_count: 0, check_runs: [] }); if (url.includes("/check-runs") && (init?.method ?? "GET") === "POST") { const body = JSON.parse(String(init?.body ?? "{}")) as { name?: string; status?: string; conclusion?: string; output?: { title?: string } }; - expect(body).toMatchObject({ name: "Gittensory Orb Review Agent", status: "in_progress", output: { title: "Gittensory Orb Review Agent is evaluating" } }); + expect(body).toMatchObject({ name: "LoopOver Orb Review Agent", status: "in_progress", output: { title: "LoopOver Orb Review Agent is evaluating" } }); expect(body.conclusion).toBeUndefined(); calls.gateChecks += 1; return Response.json({ id: 900 }, { status: 201 }); @@ -3198,7 +3198,7 @@ describe("queue processors", () => { if (url.includes("/check-runs/900") && (init?.method ?? "GET") === "PATCH") { const body = JSON.parse(String(init?.body ?? "{}")) as { name?: string; status?: string; conclusion?: string; output?: { title?: string } }; // Non-confirmed author + linked-issue block + no issue → gated normally → failure (#gate-nonconfirmed). - expect(body).toMatchObject({ name: "Gittensory Orb Review Agent", status: "completed", conclusion: "failure", output: { title: "Gittensory Orb Review Agent: No linked issue detected" } }); + expect(body).toMatchObject({ name: "LoopOver Orb Review Agent", status: "completed", conclusion: "failure", output: { title: "LoopOver Orb Review Agent: No linked issue detected" } }); calls.gateChecks += 1; return Response.json({ id: 900, html_url: "https://github.com/checks/900" }); } @@ -3230,7 +3230,7 @@ describe("queue processors", () => { .bind("JSONbored/gittensory", 42, "gate123") .first<{ name: string; status: string; conclusion: string }>(); expect(summary).toMatchObject({ - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "completed", conclusion: "failure", }); @@ -3323,7 +3323,7 @@ describe("queue processors", () => { if (url.includes("/check-runs") && (init?.method ?? "GET") === "POST") return Response.json({ id: 902 }, { status: 201 }); if (url.includes("/check-runs/902") && (init?.method ?? "GET") === "PATCH") { const body = JSON.parse(String(init?.body ?? "{}")) as { conclusion?: string; output?: { title?: string } }; - expect(body.output?.title).not.toBe("Gittensory Orb Review Agent: No linked issue detected"); + expect(body.output?.title).not.toBe("LoopOver Orb Review Agent: No linked issue detected"); return Response.json({ id: 902, html_url: "https://github.com/checks/902" }); } return new Response("not found", { status: 404 }); @@ -4492,12 +4492,12 @@ describe("queue processors", () => { expect(livePullReads).toBe(0); expect(fetchPullRequestFreshness).toHaveBeenCalledWith(env, expect.objectContaining({ expectedHeadSha: "oldsha" })); expect(checkBodies).toHaveLength(2); - expect(checkBodies[0]).toMatchObject({ status: "in_progress", output: { title: "Gittensory Orb Review Agent is evaluating" } }); + expect(checkBodies[0]).toMatchObject({ status: "in_progress", output: { title: "LoopOver Orb Review Agent is evaluating" } }); expect(checkBodies[1]).toMatchObject({ status: "completed", conclusion: "skipped", output: { - title: "Gittensory Orb Review Agent skipped", + title: "LoopOver Orb Review Agent skipped", summary: "PR head changed from oldsha to newsha", }, }); @@ -4831,7 +4831,7 @@ describe("queue processors", () => { let gateConclusion: string | undefined; let gateText = ""; const captureGate = (body: { name?: string; conclusion?: string; output?: { title?: string; summary?: string } }) => { - if ((body.name ?? "").includes("Gittensory Orb Review Agent") && body.conclusion) { + if ((body.name ?? "").includes("LoopOver Orb Review Agent") && body.conclusion) { gateConclusion = body.conclusion; gateText = `${body.output?.title ?? ""} ${body.output?.summary ?? ""}`; } @@ -4909,7 +4909,7 @@ describe("queue processors", () => { let gateConclusion: string | undefined; let gateText = ""; const captureGate = (body: { name?: string; conclusion?: string; output?: { title?: string; summary?: string } }) => { - if ((body.name ?? "").includes("Gittensory Orb Review Agent") && body.conclusion) { + if ((body.name ?? "").includes("LoopOver Orb Review Agent") && body.conclusion) { gateConclusion = body.conclusion; gateText = `${body.output?.title ?? ""} ${body.output?.summary ?? ""}`; } @@ -4994,7 +4994,7 @@ describe("queue processors", () => { if (url.includes("/check-runs")) { if (init?.body) { const body = JSON.parse(init.body.toString()) as { name?: string; conclusion?: string }; - if ((body.name ?? "").includes("Gittensory Orb Review Agent") && body.conclusion) gateConclusion = body.conclusion; + if ((body.name ?? "").includes("LoopOver Orb Review Agent") && body.conclusion) gateConclusion = body.conclusion; } return Response.json({ id: 902 }, { status: 201 }); } @@ -5067,7 +5067,7 @@ describe("queue processors", () => { if (url.includes("/check-runs")) { if (init?.body) { const body = JSON.parse(init.body.toString()) as { name?: string; conclusion?: string; output?: { title?: string; summary?: string } }; - if ((body.name ?? "").includes("Gittensory Orb Review Agent") && body.conclusion) { + if ((body.name ?? "").includes("LoopOver Orb Review Agent") && body.conclusion) { gateConclusion = body.conclusion; gateText = `${body.output?.title ?? ""} ${body.output?.summary ?? ""}`; } @@ -5147,7 +5147,7 @@ describe("queue processors", () => { if (url.includes("/check-runs")) { if (init?.body) { const body = JSON.parse(init.body.toString()) as { name?: string; conclusion?: string }; - if ((body.name ?? "").includes("Gittensory Orb Review Agent") && body.conclusion) gateConclusion = body.conclusion; + if ((body.name ?? "").includes("LoopOver Orb Review Agent") && body.conclusion) gateConclusion = body.conclusion; } return Response.json({ id: 904 }, { status: 201 }); } @@ -5223,7 +5223,7 @@ describe("queue processors", () => { if (url.includes("/check-runs")) { if (init?.body) { const body = JSON.parse(init.body.toString()) as { name?: string; conclusion?: string; output?: { title?: string; summary?: string } }; - if ((body.name ?? "").includes("Gittensory Orb Review Agent") && body.conclusion) { + if ((body.name ?? "").includes("LoopOver Orb Review Agent") && body.conclusion) { gateConclusion = body.conclusion; gateText = `${body.output?.title ?? ""} ${body.output?.summary ?? ""}`; } @@ -5308,7 +5308,7 @@ describe("queue processors", () => { if (url.includes("/check-runs")) { if (init?.body) { const body = JSON.parse(init.body.toString()) as { name?: string; conclusion?: string; output?: { title?: string; summary?: string } }; - if ((body.name ?? "").includes("Gittensory Orb Review Agent") && body.conclusion) { + if ((body.name ?? "").includes("LoopOver Orb Review Agent") && body.conclusion) { gateConclusion = body.conclusion; gateText = `${body.output?.title ?? ""} ${body.output?.summary ?? ""}`; } diff --git a/test/unit/queue-4.test.ts b/test/unit/queue-4.test.ts index 379f461de5..3484dd57ca 100644 --- a/test/unit/queue-4.test.ts +++ b/test/unit/queue-4.test.ts @@ -606,7 +606,7 @@ describe("queue processors", () => { } if (url.includes("/check-runs") && method === "POST") { const body = JSON.parse(String(init?.body ?? "{}")) as { status?: string; conclusion?: string; output?: { title?: string } }; - expect(body).toMatchObject({ status: "in_progress", output: { title: "Gittensory Orb Review Agent is evaluating" } }); + expect(body).toMatchObject({ status: "in_progress", output: { title: "LoopOver Orb Review Agent is evaluating" } }); expect(body.conclusion).toBeUndefined(); calls.gateChecks += 1; return Response.json({ id: 910 }, { status: 201 }); @@ -614,7 +614,7 @@ describe("queue processors", () => { if (url.includes("/check-runs/910") && method === "PATCH") { const body = JSON.parse(String(init?.body ?? "{}")) as { status?: string; conclusion?: string; output?: { title?: string } }; // The bot author is gated normally now (no confirmation gate); linked-issue block + no issue → failure (#gate-nonconfirmed). - expect(body).toMatchObject({ status: "completed", conclusion: "failure", output: { title: "Gittensory Orb Review Agent: No linked issue detected" } }); + expect(body).toMatchObject({ status: "completed", conclusion: "failure", output: { title: "LoopOver Orb Review Agent: No linked issue detected" } }); calls.gateChecks += 1; return Response.json({ id: 910 }); } @@ -677,7 +677,7 @@ describe("queue processors", () => { } if (url.includes("/check-runs") && method === "POST") { const body = JSON.parse(String(init?.body ?? "{}")) as { status?: string; conclusion?: string; output?: { title?: string } }; - expect(body).toMatchObject({ status: "in_progress", output: { title: "Gittensory Orb Review Agent is evaluating" } }); + expect(body).toMatchObject({ status: "in_progress", output: { title: "LoopOver Orb Review Agent is evaluating" } }); expect(body.conclusion).toBeUndefined(); calls.gateChecks += 1; return Response.json({ id: 930 }, { status: 201 }); @@ -687,7 +687,7 @@ describe("queue processors", () => { expect(body).toMatchObject({ status: "completed", conclusion: "failure", - output: { title: "Gittensory Orb Review Agent: No linked issue detected" }, + output: { title: "LoopOver Orb Review Agent: No linked issue detected" }, }); calls.gateChecks += 1; return Response.json({ id: 930 }); @@ -854,7 +854,7 @@ describe("queue processors", () => { } if (url.includes("/check-runs") && method === "POST") { const body = JSON.parse(String(init?.body ?? "{}")) as { status?: string; conclusion?: string; output?: { title?: string } }; - expect(body).toMatchObject({ status: "in_progress", output: { title: "Gittensory Orb Review Agent is evaluating" } }); + expect(body).toMatchObject({ status: "in_progress", output: { title: "LoopOver Orb Review Agent is evaluating" } }); expect(body.conclusion).toBeUndefined(); calls.gateChecks += 1; return Response.json({ id: 920 }, { status: 201 }); @@ -862,7 +862,7 @@ describe("queue processors", () => { if (url.includes("/check-runs/920") && method === "PATCH") { const body = JSON.parse(String(init?.body ?? "{}")) as { status?: string; conclusion?: string; output?: { title?: string } }; // The unconfirmed miner is gated normally now; linked-issue block + no issue → failure (#gate-nonconfirmed). - expect(body).toMatchObject({ status: "completed", conclusion: "failure", output: { title: "Gittensory Orb Review Agent: No linked issue detected" } }); + expect(body).toMatchObject({ status: "completed", conclusion: "failure", output: { title: "LoopOver Orb Review Agent: No linked issue detected" } }); calls.gateChecks += 1; return Response.json({ id: 920 }); } @@ -1026,7 +1026,7 @@ describe("queue processors", () => { expect(calls.minerList).toBe(1); expect(calls.gateChecks).toBe(2); expect(gatePatchBody.conclusion).toBe("failure"); - expect(gatePatchBody.output?.title).toBe("Gittensory Orb Review Agent: No linked issue detected"); + expect(gatePatchBody.output?.title).toBe("LoopOver Orb Review Agent: No linked issue detected"); }); it("hard-blocks a confirmed contributor on a dual-model AI consensus defect when aiReview: block is opted in", async () => { @@ -1187,7 +1187,7 @@ describe("queue processors", () => { const finalize = patchBodies[1]; expect(finalize?.status).toBe("completed"); expect(finalize?.conclusion).toBe("neutral"); - expect(finalize?.output?.title).toBe("Gittensory Orb Review Agent — could not finish evaluating"); + expect(finalize?.output?.title).toBe("LoopOver Orb Review Agent — could not finish evaluating"); const audit = await env.DB.prepare("select outcome from audit_events where event_type = ? and target_key = ?") .bind("github_app.gate_check_failed_nonfatal", "JSONbored/gittensory#80") .first<{ outcome: string }>(); @@ -1636,7 +1636,7 @@ describe("queue processors", () => { if (url.includes("/commits/closed123/check-runs")) return Response.json({ total_count: 0, check_runs: [] }); if (url.includes("/check-runs") && method === "POST") { const body = JSON.parse(String(init?.body ?? "{}")) as { name?: string; status?: string; conclusion?: string; output?: { title?: string } }; - expect(body).toMatchObject({ name: "Gittensory Orb Review Agent", status: "completed", conclusion: "skipped", output: { title: "Gittensory Orb Review Agent skipped" } }); + expect(body).toMatchObject({ name: "LoopOver Orb Review Agent", status: "completed", conclusion: "skipped", output: { title: "LoopOver Orb Review Agent skipped" } }); calls.gateWrites += 1; return Response.json({ id: 901 }, { status: 201 }); } @@ -1753,7 +1753,7 @@ describe("queue processors", () => { const checkedPanel = [ "", "", - "- [x] Re-run Gittensory review", + "- [x] Re-run LoopOver review", ].join("\n"); const calls = { token: 0, permission: 0, minerList: 0, commentGets: 0, commentPatches: 0, checkRuns: 0 }; let patchedBody = ""; @@ -1818,7 +1818,7 @@ describe("queue processors", () => { expect(calls).toEqual({ token: 1, permission: 1, minerList: 1, commentGets: 2, commentPatches: 2, checkRuns: 0 }); expect(patchedBody).toContain(""); expect(patchedBody).toContain("Readiness score:"); - expect(patchedBody).toContain("- [ ] Re-run Gittensory review"); + expect(patchedBody).toContain("- [ ] Re-run LoopOver review"); expect(patchedBody).not.toContain("- [x] "); const audit = await env.DB.prepare("select event_type, actor, target_key, outcome from audit_events where event_type = ?") .bind("github_app.pr_panel_retriggered") @@ -1861,7 +1861,7 @@ describe("queue processors", () => { const checkedPanel = [ "", "", - "- [x] Re-run Gittensory review", + "- [x] Re-run LoopOver review", ].join("\n"); env.SELFHOST_TRANSIENT_CACHE = { get: async () => { @@ -1947,7 +1947,7 @@ describe("queue processors", () => { labels: [], body: "Validation: npm test", }); - const checkedPanel = ["", "", "- [x] Re-run Gittensory review"].join("\n"); + const checkedPanel = ["", "", "- [x] Re-run LoopOver review"].join("\n"); const calls = { pullsFiles: 0 }; vi.stubGlobal("fetch", async (input: RequestInfo | URL, init?: RequestInit) => { const url = input.toString(); @@ -2020,7 +2020,7 @@ describe("queue processors", () => { labels: [], body: "Validation: npm test", }); - const checkedPanel = ["", "", "- [x] Re-run Gittensory review"].join("\n"); + const checkedPanel = ["", "", "- [x] Re-run LoopOver review"].join("\n"); const calls = { minerList: 0, permission: 0, commentPatches: 0 }; vi.stubGlobal("fetch", async (input: RequestInfo | URL, init?: RequestInit) => { const url = input.toString(); @@ -2089,7 +2089,7 @@ describe("queue processors", () => { const checkedPanel = [ "", "", - "- [x] Re-run Gittensory review", + "- [x] Re-run LoopOver review", ].join("\n"); const calls = { token: 0, permission: 0, commentGets: 0, commentPatches: 0 }; vi.stubGlobal("fetch", async (input: RequestInfo | URL) => { @@ -2166,7 +2166,7 @@ describe("queue processors", () => { const checkedPanel = [ "", "", - "- [x] Re-run Gittensory review", + "- [x] Re-run LoopOver review", ].join("\n"); const calls = { token: 0, permission: 0, minerList: 0, commentGets: 0, commentPatches: 0 }; vi.stubGlobal("fetch", async (input: RequestInfo | URL, init?: RequestInit) => { @@ -2233,7 +2233,7 @@ describe("queue processors", () => { const checkedPanel = [ "", "", - "- [x] Re-run Gittensory review", + "- [x] Re-run LoopOver review", ].join("\n"); vi.stubGlobal("fetch", async () => new Response("unexpected fetch", { status: 500 })); @@ -2265,7 +2265,7 @@ describe("queue processors", () => { const checkedPanel = [ "", "", - "- [x] Re-run Gittensory review", + "- [x] Re-run LoopOver review", ].join("\n"); const uncheckedPanel = checkedPanel.replace("- [x]", "- [ ]"); let fetchCalls = 0; @@ -2326,7 +2326,7 @@ describe("queue processors", () => { payload: { action: "edited", ...basePayload, - comment: { id: 806, body: "- [x] Re-run Gittensory review", user: { login: "gittensory[bot]", type: "Bot" } }, + comment: { id: 806, body: "- [x] Re-run LoopOver review", user: { login: "gittensory[bot]", type: "Bot" } }, sender: { login: "maintainer", type: "User" }, }, }); @@ -2337,7 +2337,7 @@ describe("queue processors", () => { payload: { action: "edited", ...basePayload, - comment: { id: 807, body: "\n\n- [x] Re-run Gittensory review", user: { login: "gittensory[bot]", type: "Bot" } }, + comment: { id: 807, body: "\n\n- [x] Re-run LoopOver review", user: { login: "gittensory[bot]", type: "Bot" } }, sender: { login: "maintainer", type: "User" }, }, }); diff --git a/test/unit/queue-5.test.ts b/test/unit/queue-5.test.ts index a79de8b833..9161f78c6b 100644 --- a/test/unit/queue-5.test.ts +++ b/test/unit/queue-5.test.ts @@ -2800,7 +2800,7 @@ describe("queue processors", () => { } if (url.includes("/commits/override-sha/check-runs") && method === "GET") { calls.checkGets += 1; - return Response.json({ total_count: 1, check_runs: [{ id: 555, name: "Gittensory Orb Review Agent" }] }); + return Response.json({ total_count: 1, check_runs: [{ id: 555, name: "LoopOver Orb Review Agent" }] }); } if (url.includes("/check-runs/555") && method === "PATCH") { calls.checkPatches += 1; @@ -2839,9 +2839,9 @@ describe("queue processors", () => { const finalize = patchBodies[0]; expect(finalize?.status).toBe("completed"); expect(finalize?.conclusion).toBe("neutral"); - expect(finalize?.output?.title).toBe("Gittensory Orb Review Agent — overridden by @maintainer"); + expect(finalize?.output?.title).toBe("LoopOver Orb Review Agent — overridden by @maintainer"); expect(finalize?.output?.text).toContain("Overridden by @maintainer: known flaky duplicate check, shipping"); - expect(confirmationBody).toContain("Gittensory Orb Review Agent overridden by @maintainer"); + expect(confirmationBody).toContain("LoopOver Orb Review Agent overridden by @maintainer"); const audit = await env.DB.prepare("select event_type, actor, target_key, outcome, detail from audit_events where event_type = ?") .bind("github_app.gate_overridden") .first<{ event_type: string; actor: string; target_key: string; outcome: string; detail: string }>(); @@ -2885,7 +2885,7 @@ describe("queue processors", () => { if (url.includes("/access_tokens")) return Response.json({ token: "installation-token" }); if (url.includes("/collaborators/maintainer/permission")) return Response.json({ permission: "admin" }); if (url.includes("/commits/override-sha-telemetry/check-runs") && method === "GET") { - return Response.json({ total_count: 1, check_runs: [{ id: 559, name: "Gittensory Orb Review Agent" }] }); + return Response.json({ total_count: 1, check_runs: [{ id: 559, name: "LoopOver Orb Review Agent" }] }); } if (url.includes("/check-runs/559") && method === "PATCH") return Response.json({ id: 559 }); if (url.includes("/issues/94/comments") && method === "GET") return Response.json([]); @@ -2946,7 +2946,7 @@ describe("queue processors", () => { if (url.includes("/access_tokens")) return Response.json({ token: "installation-token" }); if (url.includes("/collaborators/maintainer/permission")) return Response.json({ permission: "admin" }); if (url.includes("/commits/paused-override-sha/check-runs") && method === "GET") { - return Response.json({ total_count: 1, check_runs: [{ id: 556, name: "Gittensory Orb Review Agent" }] }); + return Response.json({ total_count: 1, check_runs: [{ id: 556, name: "LoopOver Orb Review Agent" }] }); } if (url.includes("/check-runs/556") && method === "PATCH") { calls.checkPatches += 1; @@ -3096,12 +3096,12 @@ describe("queue processors", () => { } if (url.includes("/commits/live-sha/check-runs") && method === "GET") { const checkName = new URL(url).searchParams.get("check_name"); - if (checkName === "Gittensory Gate") { + if (checkName === "Gittensory Gate" || checkName === "Gittensory Orb Review Agent") { seen.liveLegacyCheckGets += 1; return Response.json({ total_count: 0, check_runs: [] }); } seen.liveCheckGets += 1; - return Response.json({ total_count: 1, check_runs: [{ id: 556, name: "Gittensory Orb Review Agent" }] }); + return Response.json({ total_count: 1, check_runs: [{ id: 556, name: "LoopOver Orb Review Agent" }] }); } if (url.includes("/check-runs/556") && method === "PATCH") { patchBodies.push(JSON.parse(String(init?.body ?? "{}")) as { conclusion?: string }); @@ -3128,7 +3128,7 @@ describe("queue processors", () => { // The neutral PATCH targeted the LIVE head's Gate run (id 556), and the stale SHA was never touched. expect(seen.liveCheckGets).toBe(1); - expect(seen.liveLegacyCheckGets).toBe(1); + expect(seen.liveLegacyCheckGets).toBe(2); // both legacy names (Gittensory Gate + Gittensory Orb Review Agent) are checked expect(seen.staleCheckGets).toBe(0); expect(patchBodies[0]?.conclusion).toBe("neutral"); const audit = await env.DB.prepare("select metadata_json from audit_events where event_type = ?") @@ -3232,7 +3232,7 @@ describe("queue processors", () => { } if (url.includes("/check-runs")) { calls.checkRuns += 1; - return Response.json({ total_count: 1, check_runs: [{ id: 556, name: "Gittensory Orb Review Agent" }] }); + return Response.json({ total_count: 1, check_runs: [{ id: 556, name: "LoopOver Orb Review Agent" }] }); } if (url.includes("/comments")) { calls.comments += 1; @@ -5399,7 +5399,7 @@ describe("queue processors", () => { const otherPanel = [ "", "", - "- [x] Re-run Gittensory review", + "- [x] Re-run LoopOver review", "- [ ] Generate an AI Playwright test for this PR", ].join("\n"); diff --git a/test/unit/queue.test.ts b/test/unit/queue.test.ts index 92b8dd6ffd..4c9475b52d 100644 --- a/test/unit/queue.test.ts +++ b/test/unit/queue.test.ts @@ -4695,7 +4695,7 @@ describe("queue processors", () => { ).resolves.toBeUndefined(); expect(aiCalls).toBe(0); expect(gateConclusion).toBe("neutral"); - expect(gateSummary).toContain("Gittensory public check output is intentionally minimal"); + expect(gateSummary).toContain("LoopOver public check output is intentionally minimal"); const summary = await env.DB.prepare("select conclusion from check_summaries where repo_full_name = ? and pull_number = ?") .bind("JSONbored/gittensory", 82) .first<{ conclusion: string }>(); @@ -5176,7 +5176,7 @@ describe("queue processors", () => { repoFullName: "JSONbored/gittensory", pullNumber: 62, headSha: "a62", - name: "Gittensory Orb Review Agent", + name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {}, @@ -5244,7 +5244,7 @@ describe("queue processors", () => { }), }, }); - await upsertCheckSummary(env, { id: "gate-72", repoFullName: "JSONbored/gittensory", pullNumber: 72, headSha: "a72", name: "Gittensory Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); + await upsertCheckSummary(env, { id: "gate-72", repoFullName: "JSONbored/gittensory", pullNumber: 72, headSha: "a72", name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); await repositoriesModule.markPullRequestSurfacePublished(env, "JSONbored/gittensory", 72, "a72"); vi.stubGlobal("fetch", async (input: RequestInfo | URL, init?: RequestInit) => { const url = input.toString(); @@ -5301,7 +5301,7 @@ describe("queue processors", () => { }), }, }); - await upsertCheckSummary(env, { id: "gate-73", repoFullName: "JSONbored/gittensory", pullNumber: 73, headSha: "a73", name: "Gittensory Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); + await upsertCheckSummary(env, { id: "gate-73", repoFullName: "JSONbored/gittensory", pullNumber: 73, headSha: "a73", name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); await repositoriesModule.markPullRequestSurfacePublished(env, "JSONbored/gittensory", 73, "a73"); vi.stubGlobal("fetch", async (input: RequestInfo | URL, init?: RequestInit) => { const url = input.toString(); @@ -5357,7 +5357,7 @@ describe("queue processors", () => { }), }, }); - await upsertCheckSummary(env, { id: "gate-74", repoFullName: "JSONbored/gittensory", pullNumber: 74, headSha: "a74", name: "Gittensory Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); + await upsertCheckSummary(env, { id: "gate-74", repoFullName: "JSONbored/gittensory", pullNumber: 74, headSha: "a74", name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); await repositoriesModule.markPullRequestSurfacePublished(env, "JSONbored/gittensory", 74, "a74"); vi.stubGlobal("fetch", async (input: RequestInfo | URL, init?: RequestInit) => { const url = input.toString(); @@ -5410,7 +5410,7 @@ describe("queue processors", () => { }), }, }); - await upsertCheckSummary(env, { id: "gate-70", repoFullName: "JSONbored/gittensory", pullNumber: 70, headSha: "a70", name: "Gittensory Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); + await upsertCheckSummary(env, { id: "gate-70", repoFullName: "JSONbored/gittensory", pullNumber: 70, headSha: "a70", name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); await repositoriesModule.markPullRequestSurfacePublished(env, "JSONbored/gittensory", 70, "a70"); vi.stubGlobal("fetch", async (input: RequestInfo | URL) => { const url = input.toString(); @@ -5511,7 +5511,7 @@ describe("queue processors", () => { }), }, }); - await upsertCheckSummary(env, { id: "gate-71", repoFullName: "JSONbored/gittensory", pullNumber: 71, headSha: "a71", name: "Gittensory Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); + await upsertCheckSummary(env, { id: "gate-71", repoFullName: "JSONbored/gittensory", pullNumber: 71, headSha: "a71", name: "LoopOver Orb Review Agent", status: "completed", conclusion: "success", payload: {} }); await repositoriesModule.markPullRequestSurfacePublished(env, "JSONbored/gittensory", 71, "a71"); let checkRunCreated = false; vi.stubGlobal("fetch", async (input: RequestInfo | URL, init?: RequestInit) => { @@ -6104,7 +6104,7 @@ describe("queue processors", () => { const checkedPanel = [ "", "", - "- [x] Re-run Gittensory review", + "- [x] Re-run LoopOver review", ].join("\n"); vi.stubGlobal("fetch", async (input: RequestInfo | URL, init?: RequestInit) => { const url = input.toString(); @@ -6131,7 +6131,7 @@ describe("queue processors", () => { await processJob(env, { type: "agent-regate-pr", deliveryId: "repeat", repoFullName: "JSONbored/gittensory", prNumber: 90, installationId: 123 }); expect(aiCalls).toBe(baselineCalls); - // Checking the panel's "Re-run Gittensory review" checkbox must force a FRESH AI opinion, not silently + // Checking the panel's "Re-run LoopOver review" checkbox must force a FRESH AI opinion, not silently // replay the cached one -- this is the exact #3702 bug: the checkbox did nothing without forceAiReview. await processJob(env, { type: "github-webhook", diff --git a/test/unit/rules.test.ts b/test/unit/rules.test.ts index 39fcce4ac0..3918b48775 100644 --- a/test/unit/rules.test.ts +++ b/test/unit/rules.test.ts @@ -293,7 +293,7 @@ describe("advisory rules", () => { expect(gate.conclusion).toBe("success"); expect(gate.blockers).toEqual([]); expect(gate.warnings.map((finding) => finding.code)).not.toContain("busy_pr_queue"); - expect(output.title).toBe("Gittensory Orb Review Agent passed"); + expect(output.title).toBe("LoopOver Orb Review Agent passed"); expect(output.text).toContain("No configured hard blocker"); }); @@ -307,9 +307,9 @@ describe("advisory rules", () => { expect(advisory.findings.map((finding) => finding.code)).toEqual(expect.arrayContaining(["repo_not_registered", "pr_not_cached"])); expect(gate.conclusion).toBe("neutral"); expect(gate.blockers).toEqual([]); - expect(output.title).toBe("Gittensory Orb Review Agent — not evaluated yet"); + expect(output.title).toBe("LoopOver Orb Review Agent — not evaluated yet"); expect(output.summary).toContain("re-evaluates automatically"); - expect(output.text).toBe("Gittensory did not create a contributor-facing failure for this event."); + expect(output.text).toBe("LoopOver did not create a contributor-facing failure for this event."); }); it("formats and sanitizes gate blockers without leaking private scoring terms", () => { @@ -457,7 +457,7 @@ describe("advisory rules", () => { const failure = (findings: import("../../src/types").AdvisoryFinding[]): import("../../src/rules/advisory").GateCheckEvaluation => ({ enabled: true, conclusion: "failure", - title: "Gittensory Orb Review Agent: blocked", + title: "LoopOver Orb Review Agent: blocked", summary: "A hard blocker was found.", blockers: findings, warnings: [], @@ -567,7 +567,7 @@ describe("advisory rules", () => { expect(gate.conclusion).toBe("failure"); // Title names the blocker count; summary enumerates every active blocker with its fix. - expect(gate.title).toBe("Gittensory Orb Review Agent: 2 blockers"); + expect(gate.title).toBe("LoopOver Orb Review Agent: 2 blockers"); expect(gate.summary).toContain("No linked issue detected"); expect(gate.summary).toContain("Linked issue overlaps another open PR"); expect(gate.summary).not.toContain("Readiness score is below the configured threshold"); @@ -585,7 +585,7 @@ describe("advisory rules", () => { // neutral/held state. Confirmed-status affects only on-chain scoring, never the gate verdict. (#gate-nonconfirmed) const nonConfirmed = evaluateGateCheck(blockingAdvisory, { duplicatePrGateMode: "block", confirmedContributor: false }); expect(nonConfirmed.conclusion).toBe("failure"); - expect(nonConfirmed.title).toBe("Gittensory Orb Review Agent: Linked issue overlaps another open PR"); + expect(nonConfirmed.title).toBe("LoopOver Orb Review Agent: Linked issue overlaps another open PR"); expect(nonConfirmed.blockers.map((finding) => finding.code)).toEqual(["duplicate_pr_risk"]); // Confirmed author with the same blocker: identical verdict. @@ -603,14 +603,14 @@ describe("advisory rules", () => { const output = formatGateCheckOutput({ enabled: true, conclusion, - title: conclusion === "skipped" ? "Gittensory Orb Review Agent skipped" : "Gittensory Orb Review Agent neutral", + title: conclusion === "skipped" ? "LoopOver Orb Review Agent skipped" : "LoopOver Orb Review Agent neutral", summary: "PR closed before full evaluation.", blockers: [], warnings: [], }); expect(output.summary).toBe("PR closed before full evaluation."); - expect(output.text).toBe("Gittensory did not create a contributor-facing failure for this event."); + expect(output.text).toBe("LoopOver did not create a contributor-facing failure for this event."); } }); @@ -618,7 +618,7 @@ describe("advisory rules", () => { const output = formatGateCheckOutput({ enabled: true, conclusion: "failure", - title: "Gittensory Orb Review Agent is blocking merge", + title: "LoopOver Orb Review Agent is blocking merge", summary: "A configured merge-blocking issue was found.", blockers: [], warnings: [], @@ -646,7 +646,7 @@ describe("advisory rules", () => { expect(advisory.findings.map((finding) => finding.code)).not.toContain("private_reviewability_context"); expect(output.text).not.toMatch(/reviewability|likely_duplicate|needs_author|reward|farming|wallet|hotkey/i); - expect(output.title).toBe("Gittensory context checked"); + expect(output.title).toBe("LoopOver context checked"); }); it("covers repository config lane advisories", () => { @@ -843,7 +843,7 @@ describe("advisory rules", () => { findings: [{ code: "critical_test", title: "Critical finding", severity: "critical" as const, detail: "Something broke." }], }; const output = formatCheckRunOutput(withCritical, "standard"); - expect(output.title).toBe("Gittensory context posted"); + expect(output.title).toBe("LoopOver context posted"); expect(output.text).toContain("No detailed findings are published"); expect(output.text).not.toContain("Critical finding"); }); @@ -1472,7 +1472,7 @@ describe("green-CI compatibility reconciliation of the public comment gate", () const failure = (codes: string[]): import("../../src/rules/advisory").GateCheckEvaluation => ({ enabled: true, conclusion: "failure", - title: "Gittensory Orb Review Agent: blocked", + title: "LoopOver Orb Review Agent: blocked", summary: "A hard blocker was found.", blockers: codes.map(finding), warnings: [], diff --git a/test/unit/settings-preview.test.ts b/test/unit/settings-preview.test.ts index 9386eeced0..ee6d4c2712 100644 --- a/test/unit/settings-preview.test.ts +++ b/test/unit/settings-preview.test.ts @@ -145,7 +145,7 @@ describe("buildRepoSettingsPreview", () => { expect(preview.settings.blacklistLabel).toBe("slop"); expect(() => RepoSettingsPreviewSchema.parse(preview)).not.toThrow(); expect(preview.previewComment).toContain(""); - expect(preview.previewComment).toContain("Gittensory"); + expect(preview.previewComment).toContain("LoopOver"); expect(preview.previewComment).toContain("Confirmed Gittensor contributor"); expect(preview.warnings).toHaveLength(0); expect(preview.installPreview).toMatchObject({ @@ -349,7 +349,7 @@ describe("buildRepoSettingsPreview", () => { expect(preview.decision).toMatchObject({ skipped: false, actions: ["none"] }); expect(preview.warnings.some((warning) => /Review-agent checks are enabled.*Checks: write/.test(warning))).toBe(true); expect(preview.installPreview.permissions).toMatchObject({ status: "needs_attention", missing: ["checks"] }); - expect(preview.installPreview.publicOutputs).toEqual(expect.arrayContaining(["Opt-in Gittensory Orb Review Agent check run."])); + expect(preview.installPreview.publicOutputs).toEqual(expect.arrayContaining(["Opt-in LoopOver Orb Review Agent check run."])); }); it("shows a quiet skip for a non-miner author with no rendered comment", () => { diff --git a/test/unit/signals-coverage.test.ts b/test/unit/signals-coverage.test.ts index 2f22e630d7..058712c5e3 100644 --- a/test/unit/signals-coverage.test.ts +++ b/test/unit/signals-coverage.test.ts @@ -871,7 +871,7 @@ describe("signal coverage edge cases", () => { expect(gateRow.cells[3]).not.toBe("No action."); const comment = buildPublicPrIntelligenceComment(baseArgs); - expect(comment).toContain("Gittensory Orb Review Agent is blocking merge"); + expect(comment).toContain("LoopOver Orb Review Agent is blocking merge"); expect(comment).toContain("> [!CAUTION]"); // Sanity check: the SAME disabled-check-run repo WITHOUT autonomy configured correctly stays advisory-only @@ -1174,13 +1174,13 @@ describe("signal coverage edge cases", () => { // The comment builder must agree by construction: ON winner is NOT a blocking-merge panel; ON loser is. const winnerComment = buildPublicPrIntelligenceComment({ ...baseFor(winnerPr), duplicateWinnerEnabled: true }); const loserComment = buildPublicPrIntelligenceComment({ ...baseFor(loserPr), duplicateWinnerEnabled: true }); - expect(winnerComment).not.toContain("Gittensory Orb Review Agent is blocking merge"); + expect(winnerComment).not.toContain("LoopOver Orb Review Agent is blocking merge"); expect(winnerComment).not.toContain("#88"); expect(buildPublicPrPanelSignalRows({ ...baseFor(winnerPr), duplicateWinnerEnabled: true }).rows.find((r) => r.key === "relatedWork")!.cells[1]).toContain("No active overlap"); - expect(loserComment).toContain("Gittensory Orb Review Agent is blocking merge"); + expect(loserComment).toContain("LoopOver Orb Review Agent is blocking merge"); // Flag OFF on the winner is byte-identical to a blocking panel (today's behavior). const offWinnerComment = buildPublicPrIntelligenceComment(baseFor(winnerPr)); - expect(offWinnerComment).toContain("Gittensory Orb Review Agent is blocking merge"); + expect(offWinnerComment).toContain("LoopOver Orb Review Agent is blocking merge"); }); it("#dup-winner: hides duplicate-only same-issue evidence while preserving mixed scoped overlap context", () => { @@ -1414,7 +1414,7 @@ describe("signal coverage edge cases", () => { aiReview: { notes: "The change is currently unsafe to merge.\n\n**Blockers**\n- `src/a.ts` has a syntax error.\n\n**Nits (1)**\n- Add a regression test." }, }); expect(aiBlockedComment).toContain("> [!CAUTION]"); - expect(aiBlockedComment).toContain("Gittensory review found blockers"); + expect(aiBlockedComment).toContain("LoopOver review found blockers"); expect(aiBlockedComment).toContain("`src/a.ts` has a syntax error."); expect(aiBlockedComment.indexOf("**Review summary**")).toBeLessThan(aiBlockedComment.indexOf("**Readiness score:")); @@ -1431,7 +1431,7 @@ describe("signal coverage edge cases", () => { }); expect(aiExplicitNoBlockersComment).toContain("> [!TIP]"); expect(aiExplicitNoBlockersComment).not.toContain( - "Gittensory review found blockers", + "LoopOver review found blockers", ); const advisoryOnlyComment = buildPublicPrIntelligenceComment({env: {}, @@ -1454,7 +1454,7 @@ describe("signal coverage edge cases", () => { }); expect(advisoryOnlyComment).toContain("> [!WARNING]"); - expect(advisoryOnlyComment).toContain("Gittensory found maintainer review notes"); + expect(advisoryOnlyComment).toContain("LoopOver found maintainer review notes"); expect(advisoryOnlyComment).toContain("Validation note missing"); expect(advisoryOnlyComment).toContain("> | Gate result | ⚠️ Advisory only | Advisory only. | No action. |"); @@ -1754,7 +1754,7 @@ describe("signal coverage edge cases", () => { expect(comment).toContain("[JSONbored](https://github.com/JSONbored)"); expect(comment).toContain("[Gittensor profile](https://gittensor.io/miners/details?githubId=49853598)"); expect(comment).toContain("Official Gittensor activity: 29 PR(s), 6 issue(s)."); - expect(comment).toContain("- [ ] Re-run Gittensory review"); + expect(comment).toContain("- [ ] Re-run LoopOver review"); expect(comment).not.toContain("- [x] "); expect(comment).not.toMatch(/wallet|hotkey|payout|trust score|private score/i); }); @@ -2106,7 +2106,7 @@ describe("signal coverage edge cases", () => { settings: { ...repoSettings(directRepo.fullName), linkedIssueGateMode: "off" }, }); - expect(comment).toContain("Gittensory PR readiness looks good"); + expect(comment).toContain("LoopOver PR readiness looks good"); expect(comment).toContain("- No public-safe advisory findings were generated from cached metadata."); expect(comment).toContain("- Keep the PR focused and include validation evidence before maintainer review."); expect(comment).not.toMatch(/No linked issue detected|reward|wallet/i); diff --git a/test/unit/unified-comment.test.ts b/test/unit/unified-comment.test.ts index cce6b82520..17468ac966 100644 --- a/test/unit/unified-comment.test.ts +++ b/test/unit/unified-comment.test.ts @@ -124,8 +124,8 @@ describe("renderUnifiedReviewComment", () => { { label: "Contributor", state: "ok", result: "Confirmed", evidence: "galuis116 · 168 PRs" }, ], extraCollapsibles: [{ title: "Signal definitions", body: "Readiness signals describe public-metadata readiness." }], - reRunLabel: "Re-run Gittensory review", - footerMarkdown: "Checked by Gittensory.", + reRunLabel: "Re-run LoopOver review", + footerMarkdown: "Checked by LoopOver.", }; it("renders the ready/auto-merged state in the gittensory shape", () => { @@ -135,7 +135,7 @@ describe("renderUnifiedReviewComment", () => { ); expect(md).toContain("> [!TIP]"); expect(md).toContain("🟩"); - expect(md).toContain("Gittensory review result - approve/merge recommended · auto-merged"); + expect(md).toContain("LoopOver review result - approve/merge recommended · auto-merged"); expect(md).toContain("Suggested Action - Approve/Merge"); expect(md).toContain("- auto-merged"); expect(md).toContain("`2 files`"); @@ -151,8 +151,8 @@ describe("renderUnifiedReviewComment", () => { expect(md.indexOf("**Review summary**")).toBeLessThan(md.indexOf("
Nits")); expect(md.indexOf("
Nits")).toBeLessThan(md.indexOf("| Signal | Result | Evidence |")); expect(md).toContain("
Signal definitions"); - expect(md).toContain("- [ ] Re-run Gittensory review"); - expect(md).toContain("Checked by Gittensory."); + expect(md).toContain("- [ ] Re-run LoopOver review"); + expect(md).toContain("Checked by LoopOver."); }); it("does not describe a single reviewer as synthesized", () => { @@ -165,7 +165,7 @@ describe("renderUnifiedReviewComment", () => { it("wraps the review body in the colored blockquote but renders the re-run checkbox OUTSIDE it (interactive)", () => { const md = renderUnifiedReviewComment({ ...base, decision: "merge" }, ctx); const lines = md.split("\n"); - const checkboxLine = lines.find((l) => l.includes("Re-run Gittensory review")); + const checkboxLine = lines.find((l) => l.includes("Re-run LoopOver review")); expect(checkboxLine).toBeDefined(); // GitHub disables task-list checkboxes inside a blockquote, so the re-run box must be at top level // (otherwise it can never be ticked → no issue_comment.edited → the on-demand re-run never fires). @@ -183,7 +183,7 @@ describe("renderUnifiedReviewComment", () => { { ...ctx, generateTestsLabel: "Generate an AI Playwright test for this PR" }, ); const lines = md.split("\n"); - const reRunLine = lines.find((l) => l.includes("Re-run Gittensory review")); + const reRunLine = lines.find((l) => l.includes("Re-run LoopOver review")); const generateTestsLine = lines.find((l) => l.includes("Generate an AI Playwright test for this PR")); expect(reRunLine).toBeDefined(); expect(generateTestsLine).toBeDefined(); @@ -200,7 +200,7 @@ describe("renderUnifiedReviewComment", () => { { ...base, decision: "merge" }, { ...ctxWithoutReRun, generateTestsLabel: "Generate an AI Playwright test for this PR" }, ); - expect(md).not.toContain("Re-run Gittensory review"); + expect(md).not.toContain("Re-run LoopOver review"); expect(md).toContain("- [ ] Generate an AI Playwright test for this PR"); }); @@ -260,7 +260,7 @@ describe("renderUnifiedReviewComment", () => { { reviewedAt: "2026-06-29T08:05:59.852Z" }, ); expect(md).toContain("Review updated: 2026-06-29 08:05:59 UTC"); - expect(md.indexOf("Gittensory review result")).toBeLessThan(md.indexOf("Review updated:")); + expect(md.indexOf("LoopOver review result")).toBeLessThan(md.indexOf("Review updated:")); expect(md.indexOf("Review updated:")).toBeLessThan(md.indexOf("`2 files`")); expect(renderUnifiedReviewComment({ ...base, decision: "merge" }, { reviewedAt: "not-a-date" })).not.toContain("Review updated:"); }); @@ -290,7 +290,7 @@ describe("renderUnifiedReviewComment", () => { it("a blocked status from reviewer recs (no close decision) reads 'blocked', not 'closed'", () => { const md = renderUnifiedReviewComment({ ...base, recommendations: ["close"], blockers: ["Leaks a token."], consensusBlocker: true }, {}); expect(md).toContain("> [!CAUTION]"); - expect(md).toContain("Gittensory review result - fixes required"); // headlineLabel(): decision !== "close" + expect(md).toContain("LoopOver review result - fixes required"); // headlineLabel(): decision !== "close" expect(md).toContain("**🛑 Suggested Action - Fix Blockers**"); // verdictLine(): decision !== "close" expect(md).not.toContain("Suggested Action - Reject/Close"); }); @@ -298,7 +298,7 @@ describe("renderUnifiedReviewComment", () => { it("renders CI-failing / CI-pending chips and the merge-state label", () => { const failing = renderUnifiedReviewComment({ ...base, readiness: { ciState: "failed", mergeStateLabel: "behind" } }, {}); expect(failing).toContain("> [!CAUTION]"); - expect(failing).toContain("Gittensory review result - fixes required"); + expect(failing).toContain("LoopOver review result - fixes required"); expect(failing).toContain("Suggested Action - Fix Blockers"); expect(failing).toContain("`CI failing`"); expect(failing).toContain("`behind`"); @@ -475,7 +475,7 @@ describe("renderUnifiedReviewComment", () => { it("renders non-closable failed-CI reviews as red manual-review actions, not reject/close", () => { const md = renderUnifiedReviewComment({ ...base, decision: "close", readiness: { ciState: "failed" } }, { neverClosed: true }); expect(md).toContain("> [!CAUTION]"); - expect(md).toContain("Gittensory review result - fixes required"); + expect(md).toContain("LoopOver review result - fixes required"); expect(md).toContain("Suggested Action - Manual Review"); expect(md).toContain("`CI failing`"); expect(md).not.toContain("Suggested Action - Reject/Close"); @@ -712,7 +712,7 @@ describe("renderReviewingPlaceholder", () => { }); it("uses the default brand when none is provided", () => { - expect(renderReviewingPlaceholder()).toContain("Gittensory is reviewing"); + expect(renderReviewingPlaceholder()).toContain("LoopOver is reviewing"); }); it("respects a custom brand override", () => {