From 46c901de3bdbb18a18cb93ddd88c786debb4f795 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Sun, 12 Jul 2026 14:31:04 -0700 Subject: [PATCH] refactor(rebrand): rename bot-posted check-run names and PR-comment branding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hard cutover (maintainer decision: no dual-emit window) of the two active check-run names ("Gittensory Context" -> "LoopOver Context", "Gittensory Orb Review Agent" -> "LoopOver Orb Review Agent") and the matching PR- comment brand strings: the unified-comment headline/reviewing-placeholder defaults, the "Re-run ... review" checkbox label, the "Checked by [...]" footer attribution, and the legacy panel's title/summary text. The existing supersedeLegacyNames mechanism (src/github/app.ts's finalizeLegacyPendingCheckRuns) is extended with a new legacy-name constant for each renamed check so a self-hoster's already-pending check-run under the old name still gets finalized to neutral instead of hanging in_progress forever across the deploy boundary — the same belt-and-suspenders treatment the pre-existing "Gittensory Gate" legacy name already got from an earlier rename. @jsonbored/gittensory-engine (the separate, hand-duplicated predicted-gate package) mirrors this exact rename in its own copy of the same evaluateGateCheckCore logic, with the golden parity fixtures and the engine-parity drift-check regenerated/verified to match. README's check-run disambiguation section and the OpenAPI settings descriptions are updated to match. Deliberately left untouched (each tracked by its own separate rebrand issue or genuinely out of scope for this one): gittensor (the permanent SN74 subnet brand), the repo's own name, the @gittensory bot-mention command prefix, .gittensory.yml/.gittensory-ams.yml config filenames, GITTENSORY_*-prefixed env vars, npm package identifiers, the bot's check-run-adjacent GitHub App slug, and the broader deterministic rule-finding message strings elsewhere in src/rules/advisory.ts. Closes #5327 --- README.md | 4 +- apps/gittensory-ui/public/openapi.json | 8 +- .../src/advisory/gate-advisory.ts | 16 ++-- .../gittensory-engine/src/focus-manifest.ts | 8 +- .../src/review/check-names.ts | 2 +- .../src/types/manifest-deps-types.ts | 2 +- src/github/app.ts | 54 ++++++------ src/github/backfill.ts | 12 ++- src/github/footer.ts | 14 ++-- src/openapi/schemas.ts | 8 +- src/queue/ai-review-orchestration.ts | 4 +- src/queue/gate-checks.ts | 4 +- src/queue/processors.ts | 12 +-- src/review/check-names.ts | 30 +++++-- src/review/content-lane-wire.ts | 8 +- src/review/repo-profile.ts | 4 +- src/review/unified-comment-bridge.ts | 32 ++++---- src/review/unified-comment.ts | 36 ++++---- src/rules/advisory.ts | 28 +++---- src/services/maintainer-activation.ts | 6 +- src/signals/engine.ts | 22 ++--- src/signals/settings-preview.ts | 8 +- src/types.ts | 12 +-- .../golden/ai-review-gate-mode-inert.json | 2 +- .../golden/cla-gate-mode-inert.json | 2 +- .../golden/clean-pass-gittensor.json | 2 +- .../golden/clean-pass-oss-anti-slop.json | 2 +- .../golden/duplicate-pr-block.json | 2 +- .../golden/first-time-grace-inert.json | 2 +- .../predicted-gate/golden/guardrail-hold.json | 2 +- .../golden/manifest-blocked-path.json | 2 +- .../merge-readiness-composite-block.json | 2 +- .../golden/missing-linked-issue-block.json | 2 +- .../golden/path-gated-check-with-paths.json | 2 +- .../path-gated-check-without-paths.json | 2 +- .../golden/readiness-warning.json | 2 +- .../self-authored-linked-issue-block.json | 2 +- test/unit/ai-review-advisory.test.ts | 2 +- test/unit/backfill-2.test.ts | 34 ++++---- test/unit/backfill.test.ts | 5 +- test/unit/check-names.test.ts | 22 +++-- test/unit/content-lane-wire.test.ts | 2 +- test/unit/e2e-test-gen-render.test.ts | 4 +- test/unit/focus-manifest-loader.test.ts | 2 +- test/unit/focus-manifest.test.ts | 4 +- test/unit/footer.test.ts | 6 +- test/unit/github-app.test.ts | 82 +++++++++---------- test/unit/predicted-gate.test.ts | 2 +- test/unit/queue-2.test.ts | 42 +++++----- test/unit/queue-4.test.ts | 40 ++++----- test/unit/queue-5.test.ts | 20 ++--- test/unit/queue.test.ts | 18 ++-- test/unit/rules.test.ts | 24 +++--- test/unit/settings-preview.test.ts | 4 +- test/unit/signals-coverage.test.ts | 18 ++-- test/unit/unified-comment.test.ts | 26 +++--- 56 files changed, 374 insertions(+), 345 deletions(-) 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", () => {