From 2b91e8ef88e1fc5e84348bd81221071789676f0c Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Tue, 7 Jul 2026 04:36:26 -0700 Subject: [PATCH 1/3] chore(review): remove dead labeling-rules, queue-burden-breakdown, workboard, and settings-drift modules These four modules (resolveLabelingRules, explainQueueBurden, buildWorkboard, computeSettingsDrift/computeSettingsDriftForRepo) have zero production call sites anywhere in the repo despite full unit test coverage. Removing them along with their dedicated test files. --- src/api/workboard.ts | 40 ---- src/review/labeling-rules.ts | 43 ---- src/services/queue-burden-breakdown.ts | 284 ----------------------- src/settings/settings-drift.ts | 65 ------ test/unit/queue-burden-breakdown.test.ts | 183 --------------- test/unit/review-labeling-rules.test.ts | 117 ---------- test/unit/settings-drift.test.ts | 114 --------- 7 files changed, 846 deletions(-) delete mode 100644 src/api/workboard.ts delete mode 100644 src/review/labeling-rules.ts delete mode 100644 src/services/queue-burden-breakdown.ts delete mode 100644 src/settings/settings-drift.ts delete mode 100644 test/unit/queue-burden-breakdown.test.ts delete mode 100644 test/unit/review-labeling-rules.test.ts delete mode 100644 test/unit/settings-drift.test.ts diff --git a/src/api/workboard.ts b/src/api/workboard.ts deleted file mode 100644 index 542d55bed9..0000000000 --- a/src/api/workboard.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { IssueRecord, RepositoryRecord } from "../types"; - -export type WorkboardItem = { - repoFullName: string; - issueNumber: number; - title: string; - state: string; - htmlUrl?: string | null | undefined; - fit: "good" | "caution" | "hold"; - reasons: string[]; -}; - -export function buildWorkboard(repo: RepositoryRecord | null, issues: IssueRecord[]): WorkboardItem[] { - if (!repo) return []; - return issues.map((issue) => { - const reasons: string[] = []; - let fit: WorkboardItem["fit"] = "good"; - if (!repo.isRegistered) { - fit = "hold"; - reasons.push("Repository is not present in the latest registry snapshot."); - } - if (issue.linkedPrs.length > 0) { - fit = fit === "hold" ? "hold" : "caution"; - reasons.push("Issue already has linked pull requests."); - } - if (issue.authorAssociation && ["OWNER", "MEMBER", "COLLABORATOR"].includes(issue.authorAssociation)) { - reasons.push("Issue was opened by a maintainer-associated account."); - } - if (reasons.length === 0) reasons.push("Open issue with no linked pull request detected by Gittensory."); - return { - repoFullName: repo.fullName, - issueNumber: issue.number, - title: issue.title, - state: issue.state, - htmlUrl: issue.htmlUrl, - fit, - reasons, - }; - }); -} diff --git a/src/review/labeling-rules.ts b/src/review/labeling-rules.ts deleted file mode 100644 index 69de2678f8..0000000000 --- a/src/review/labeling-rules.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { matchesManifestPath, type LabelingRule } from "../signals/focus-manifest"; - -// Deterministic evaluation of `review.labeling_rules` (#2045, part of #1959). Given a repo's parsed rules and a PR's -// facts, decide which non-scoring labels the rules SUGGEST — and, when the repo's `autoLabelEnabled` is set, which to -// auto-apply. Pure (no IO), mirroring the pure `resolvePrTypeLabel` decider in src/settings/pr-type-label.ts: the -// actual GitHub apply is a separate processor concern, kept out of here so this stays deterministic and unit-testable. - -/** The PR facts a labeling rule matches against. */ -export type LabelingRuleFacts = { - changedPaths: readonly string[]; - title: string; - description: string; -}; - -/** `suggest`: every firing rule's label (advisory, deduped, in rule order). `apply`: the subset to actually write — - * the same list when `autoLabelEnabled`, otherwise empty (suggestions only). */ -export type LabelingDecision = { suggest: string[]; apply: string[] }; - -/** A rule fires when ALL of its specified criteria match: at least one changed path matches a `whenPaths` glob (when - * any is set), the title contains `titleContains` (case-insensitive), and the description contains - * `descriptionContains`. Unset criteria don't constrain. A rule always has ≥1 criterion (enforced at parse). Pure. */ -function ruleMatches(rule: LabelingRule, facts: LabelingRuleFacts): boolean { - if (rule.whenPaths.length > 0 && !facts.changedPaths.some((path) => rule.whenPaths.some((glob) => matchesManifestPath(path, glob)))) { - return false; - } - if (rule.titleContains !== null && !facts.title.toLowerCase().includes(rule.titleContains.toLowerCase())) return false; - if (rule.descriptionContains !== null && !facts.description.toLowerCase().includes(rule.descriptionContains.toLowerCase())) return false; - return true; -} - -/** Resolve the labels suggested (and, when auto-labeling is on, to apply) for a PR. Deterministic: preserves rule - * order, dedupes, and never mutates its inputs. Pure. */ -export function resolveLabelingRules(input: { - rules: readonly LabelingRule[]; - facts: LabelingRuleFacts; - autoLabelEnabled: boolean; -}): LabelingDecision { - const suggest: string[] = []; - for (const rule of input.rules) { - if (ruleMatches(rule, input.facts) && !suggest.includes(rule.label)) suggest.push(rule.label); - } - return { suggest, apply: input.autoLabelEnabled ? [...suggest] : [] }; -} diff --git a/src/services/queue-burden-breakdown.ts b/src/services/queue-burden-breakdown.ts deleted file mode 100644 index e0c6111425..0000000000 --- a/src/services/queue-burden-breakdown.ts +++ /dev/null @@ -1,284 +0,0 @@ -import { sanitizePublicComment } from "../github/commands"; -import type { QueueHealth } from "../signals/engine"; - -// ─── Queue burden breakdown (explanation family) ───────────────────────────────────────────────── -// A pure projection over a computed {@link QueueHealth} that decomposes the otherwise-opaque -// `burdenScore` into its weighted, observable contributors and names the single highest-leverage lever -// a maintainer can pull to bring queue pressure down fastest. Sibling of `score-breakdown.ts`, -// `miner-dashboard-recommendations.ts`, and `agent-action-explanation-card.ts`: deterministic, no I/O, -// no GitHub fetch. Public-safe by construction — it reports observable counts, relative shares, and -// bands only, and routes every rendered string through `sanitizePublicComment`. - -export type QueueBurdenBand = "credit" | "none" | "low" | "moderate" | "high"; - -export type QueueBurdenComponent = { - /** The QueueHealth signal this contribution is derived from. */ - component: string; - /** Observable signal count (open PRs, unlinked PRs, collision clusters, …). */ - count: number; - /** Signed per-unit weight this signal carries in the burden formula (the reviewable credit is negative). */ - weightPerUnit: number; - /** `count * weightPerUnit` — positive for a penalty, negative for the reviewable credit. */ - contribution: number; - /** Share of total positive penalty (0–100). For the credit it is the percentage of penalty it offsets. */ - sharePercent: number; - band: QueueBurdenBand; - summary: string; - lever: string; - /** 0–100 ranking weight used to pick the single highest-leverage improvement lever. */ - leverageScore: number; -}; - -export type QueueBurdenBreakdown = { - repoFullName: string; - generatedAt: string; - /** The authoritative (already clamped) burden score carried on the QueueHealth. */ - burdenScore: number; - level: QueueHealth["level"]; - /** Pre-clamp signed sum of every contribution (penalties minus the reviewable credit). */ - rawBurden: number; - /** True when the raw sum fell outside the 0–100 band and the engine clamped it. */ - clamped: boolean; - /** Sum of the positive penalty contributions. */ - totalPenalty: number; - /** Absolute size of the reviewable credit that offsets the penalties. */ - totalCredit: number; - components: QueueBurdenComponent[]; - highestLeverageLever: { component: string; lever: string; reason: string }; - summary: string; -}; - -// These per-unit weights MIRROR buildQueueHealth() in src/signals/engine.ts. A drift-guard test rebuilds a -// QueueHealth through buildQueueHealth and asserts this module recomposes the same burdenScore, so any change -// to the engine weights fails the suite instead of silently producing a wrong breakdown. -const PENALTY_DESCRIPTORS: ReadonlyArray<{ - component: string; - weightPerUnit: number; - count: (health: QueueHealth) => number; - describe: (count: number) => { summary: string; lever: string }; -}> = [ - { - component: "unlinkedPullRequests", - weightPerUnit: 8, - count: (health) => health.signals.unlinkedPullRequests, - describe: (count) => - count > 0 - ? { - summary: `${count} open pull request(s) lack a linked issue, the heaviest per-PR burden factor.`, - lever: "Ask contributors to link a closing issue or state explicit no-issue intent so unlinked PRs stop driving burden.", - } - : { - summary: "Every open pull request carries linked-issue context, so this factor adds no burden.", - lever: "Keep requiring a linked issue or a clear no-issue rationale so this factor stays at zero.", - }, - }, - { - component: "collisionClusters", - weightPerUnit: 10, - count: (health) => health.signals.collisionClusters, - describe: (count) => - count > 0 - ? { - summary: `${count} duplicate or overlapping work cluster(s) carry the highest per-unit burden weight.`, - lever: "Resolve overlapping submissions before spending detailed review time to cut collision burden fastest.", - } - : { - summary: "No duplicate or overlapping work clusters were detected, so this factor adds no burden.", - lever: "Keep deduplicating incoming work early so collision burden stays at zero.", - }, - }, - { - component: "openPullRequests", - weightPerUnit: 6, - count: (health) => health.signals.openPullRequests, - describe: (count) => - count > 0 - ? { - summary: `${count} open pull request(s) contribute baseline review load.`, - lever: "Land or close open pull requests to reduce the baseline queue load.", - } - : { - summary: "There are no open pull requests adding baseline load.", - lever: "No action needed; baseline pull-request load is already at zero.", - }, - }, - { - component: "stalePullRequests", - weightPerUnit: 6, - count: (health) => health.signals.stalePullRequests, - describe: (count) => - count > 0 - ? { - summary: `${count} open pull request(s) have stalled without an update for at least 14 days.`, - lever: "Review, nudge, or close stale pull requests so they stop accruing burden.", - } - : { - summary: "No open pull requests have stalled past the 14-day staleness threshold.", - lever: "Keep pull requests moving so none cross the staleness threshold.", - }, - }, - { - component: "over30DayPullRequests", - weightPerUnit: 4, - count: (health) => health.signals.ageBuckets.over30Days, - describe: (count) => - count > 0 - ? { - summary: `${count} open pull request(s) have aged past 30 days.`, - lever: "Resolve the long-aged pull requests to clear the oldest backlog in the queue.", - } - : { - summary: "No open pull requests have aged past 30 days.", - lever: "Keep clearing aged work so none crosses the 30-day mark.", - }, - }, - { - component: "openIssues", - weightPerUnit: 1, - count: (health) => health.signals.openIssues, - describe: (count) => - count > 0 - ? { - summary: `${count} open issue(s) add minor triage load.`, - lever: "Triage or close resolved open issues to trim residual queue load.", - } - : { - summary: "There are no open issues adding triage load.", - lever: "No action needed; open-issue triage load is already at zero.", - }, - }, -]; - -const REVIEWABLE_CREDIT_PER_UNIT = -2; - -function penaltyBand(count: number, sharePercent: number): QueueBurdenBand { - if (count <= 0) return "none"; - if (sharePercent >= 40) return "high"; - if (sharePercent >= 15) return "moderate"; - return "low"; -} - -function shareOf(contribution: number, totalPenalty: number): number { - if (totalPenalty <= 0) return 0; - return Math.round((Math.abs(contribution) / totalPenalty) * 100); -} - -function creditComponent(health: QueueHealth, totalPenalty: number): QueueBurdenComponent { - const count = health.signals.likelyReviewablePullRequests; - const contribution = count * REVIEWABLE_CREDIT_PER_UNIT; - const sharePercent = shareOf(contribution, totalPenalty); - return { - component: "likelyReviewablePullRequests", - count, - weightPerUnit: REVIEWABLE_CREDIT_PER_UNIT, - contribution, - sharePercent, - band: "credit", - summary: - count > 0 - ? `${count} open pull request(s) look readily reviewable and reduce net queue burden.` - : "No open pull requests are currently counted as readily reviewable, so nothing is offsetting burden.", - lever: - count > 0 - ? "Keep pull requests linked and fresh so they stay readily reviewable and keep offsetting burden." - : "Help open pull requests become linked and fresh so they start offsetting queue burden.", - // The credit is already helping; it is never the lever a maintainer pulls to REDUCE burden, so it stays - // out of the highest-leverage ranking. - leverageScore: 0, - }; -} - -function pickHighestLeverage(components: QueueBurdenComponent[]): QueueBurdenBreakdown["highestLeverageLever"] { - // Rank by share of burden, then break ties toward the heavier per-unit weight (reducing one high-weight item - // removes more burden per action, so it is the better lever), and finally by name purely for determinism. - const ranked = [...components].sort( - (left, right) => - right.leverageScore - left.leverageScore || - right.weightPerUnit - left.weightPerUnit || - left.component.localeCompare(right.component), - ); - const top = ranked[0]!; - // When no penalty is active (every leverageScore is 0), the sort tie-break would otherwise surface an - // arbitrary alphabetically-first component as "the lever" — which is misleading because there is nothing to - // reduce. Return an explicit no-op lever instead so the breakdown stays honest for a healthy queue. - if (top.leverageScore <= 0) { - return { - component: "none", - lever: sanitizePublicComment("No queue-burden lever needs attention; there are no active contributors to reduce."), - reason: sanitizePublicComment("Queue burden has no active penalty contributors right now, so there is no pressing lever to pull."), - }; - } - const reason = - top.band === "high" - ? `${top.component} is the dominant queue-burden contributor right now.` - : `${top.component} is the largest remaining queue-burden contributor.`; - return { - component: top.component, - lever: top.lever, - reason: sanitizePublicComment(reason), - }; -} - -/** - * Pure projection over a {@link QueueHealth} that explains how the queue `burdenScore` breaks down into its - * weighted, observable contributors and names the single highest-leverage lever to reduce queue pressure. - */ -export function explainQueueBurden(health: QueueHealth): QueueBurdenBreakdown { - const penalties = PENALTY_DESCRIPTORS.map((descriptor) => { - const count = descriptor.count(health); - const contribution = count * descriptor.weightPerUnit; - return { descriptor, count, contribution }; - }); - const totalPenalty = penalties.reduce((sum, entry) => sum + entry.contribution, 0); - - const penaltyComponents: QueueBurdenComponent[] = penalties.map(({ descriptor, count, contribution }) => { - const sharePercent = shareOf(contribution, totalPenalty); - const copy = descriptor.describe(count); - return { - component: descriptor.component, - count, - weightPerUnit: descriptor.weightPerUnit, - contribution, - sharePercent, - band: penaltyBand(count, sharePercent), - summary: copy.summary, - lever: copy.lever, - // A penalty's leverage is exactly its share of the burden — the biggest contributor is the best lever. - leverageScore: sharePercent, - }; - }); - - const credit = creditComponent(health, totalPenalty); - const totalCredit = Math.abs(credit.contribution); - const rawBurden = totalPenalty + credit.contribution; - // The engine clamps burden to 0–100. The lower bound is unreachable in practice: every open PR adds 6 to the - // penalty while its reviewable credit only subtracts 2 (and reviewable PRs never exceed open PRs), so the - // penalties always dominate the credit. Only the upper clamp is observable here. - const clamped = rawBurden > 100; - - const components = [...penaltyComponents, credit].map((entry) => ({ - ...entry, - summary: sanitizePublicComment(entry.summary), - lever: sanitizePublicComment(entry.lever), - })); - - const highestLeverageLever = pickHighestLeverage(components); - const summary = - highestLeverageLever.component === "none" - ? `Queue burden is ${health.level} with no active contributors to address.` - : `Queue burden is ${health.level}; ${highestLeverageLever.component} is the leading factor to address.`; - - return { - repoFullName: health.repoFullName, - generatedAt: health.generatedAt, - burdenScore: health.burdenScore, - level: health.level, - rawBurden, - clamped, - totalPenalty, - totalCredit, - components, - highestLeverageLever, - summary: sanitizePublicComment(summary), - }; -} diff --git a/src/settings/settings-drift.ts b/src/settings/settings-drift.ts deleted file mode 100644 index 482d3e9635..0000000000 --- a/src/settings/settings-drift.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { getGlobalContributorBlacklist, getRepositorySettings } from "../db/repositories"; -import { parseFocusManifest, resolveEffectiveSettings, type FocusManifest } from "../signals/focus-manifest"; -import { loadRepoFocusManifest } from "../signals/focus-manifest-loader"; -import type { RepositorySettings } from "../types"; - -// The "no manifest at all" baseline (parseFocusManifest(null) is this codebase's existing idiom for it, e.g. -// test/unit/focus-manifest.test.ts). Comparing against THIS instead of the raw dbSettings row isolates drift -// caused specifically by the manifest -- resolveEffectiveSettings also applies manifest-INDEPENDENT -// normalization (the shared contributor-blacklist merge below the gate block, and the requireLinkedIssue-implies- -// block downgrade), which would otherwise misreport as "shadowed by private config" for every repo with a -// global blacklist entry, even one with no manifest at all. -const NO_MANIFEST = parseFocusManifest(null); - -export type SettingsDriftEntry = { - field: keyof RepositorySettings; - dbValue: unknown; - effectiveValue: unknown; -}; - -// Local copy of the stableStringify helper already duplicated in review/ai-review-cache-input.ts and -// upstream/ruleset.ts for the same order-independent-equality purpose -- matches this codebase's existing -// pattern of a small per-module copy rather than a shared utility for a ~6-line function. -function stableStringify(value: unknown): string { - if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`; - if (value !== null && typeof value === "object") { - return `{${Object.entries(value as Record) - .sort(([left], [right]) => left.localeCompare(right)) - .map(([key, nested]) => `${JSON.stringify(key)}:${stableStringify(nested)}`) - .join(",")}}`; - } - return JSON.stringify(value); -} - -/** - * Diagnostic-only, read-only diff between a repo's DB-stored `repository_settings` row and the LIVE effective - * settings `resolveEffectiveSettings` would actually apply for it (config-as-code `.gittensory.yml` merged over - * the DB row). Every entry here is a DB-stored field whose value is silently shadowed by a manifest override -- - * useful for a self-host operator who changed something via the dashboard and can't tell why it isn't taking - * effect. PURE and never called from the live review/gate path itself (see resolveEffectiveSettings, - * settings/repository-settings.ts's resolveRepositorySettings) -- this can never affect what settings a PR - * review actually resolves to, only report on it after the fact. - */ -export function computeSettingsDrift( - dbSettings: RepositorySettings, - manifest: FocusManifest, - sharedContributorBlacklist: RepositorySettings["contributorBlacklist"] = [], -): SettingsDriftEntry[] { - const baseline = resolveEffectiveSettings(dbSettings, NO_MANIFEST, sharedContributorBlacklist); - const effective = resolveEffectiveSettings(dbSettings, manifest, sharedContributorBlacklist); - return (Object.keys(dbSettings) as (keyof RepositorySettings)[]) - .filter((field) => stableStringify(baseline[field]) !== stableStringify(effective[field])) - .map((field) => ({ field, dbValue: dbSettings[field], effectiveValue: effective[field] })); -} - -/** Same diff, but fetching the DB row, manifest, and shared contributor blacklist live for one repo -- the - * same three reads settings/repository-settings.ts's resolveRepositorySettings already makes, so this never - * introduces a new data-fetch path, only a read-only diagnostic view over the existing one. */ -export async function computeSettingsDriftForRepo(env: Env, repoFullName: string): Promise { - const [dbSettings, manifest, sharedContributorBlacklist] = await Promise.all([ - getRepositorySettings(env, repoFullName), - loadRepoFocusManifest(env, repoFullName), - getGlobalContributorBlacklist(env).catch(() => []), - ]); - return computeSettingsDrift(dbSettings, manifest, sharedContributorBlacklist); -} diff --git a/test/unit/queue-burden-breakdown.test.ts b/test/unit/queue-burden-breakdown.test.ts deleted file mode 100644 index 5599dddb8f..0000000000 --- a/test/unit/queue-burden-breakdown.test.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { explainQueueBurden } from "../../src/services/queue-burden-breakdown"; -import { buildQueueHealth, type CollisionReport, type QueueHealth } from "../../src/signals/engine"; -import type { PullRequestRecord, RepositoryRecord } from "../../src/types"; - -const FORBIDDEN = /\b(wallet|hotkey|coldkey|mnemonic|payout|reward|raw[-_\s]?trust|credibility|farming)\b/i; - -const clamp = (value: number): number => Math.max(0, Math.min(100, value)); - -function makeHealth(input: { - openPullRequests?: number; - openIssues?: number; - unlinkedPullRequests?: number; - stalePullRequests?: number; - over30Days?: number; - collisionClusters?: number; - likelyReviewablePullRequests?: number; - burdenScore?: number; - level?: QueueHealth["level"]; - repoFullName?: string; - generatedAt?: string; -}): QueueHealth { - return { - repoFullName: input.repoFullName ?? "owner/repo", - generatedAt: input.generatedAt ?? "2026-06-30T00:00:00.000Z", - burdenScore: input.burdenScore ?? 0, - level: input.level ?? "low", - summary: "fixture", - signals: { - openIssues: input.openIssues ?? 0, - openPullRequests: input.openPullRequests ?? 0, - unlinkedPullRequests: input.unlinkedPullRequests ?? 0, - stalePullRequests: input.stalePullRequests ?? 0, - draftPullRequests: 0, - maintainerAuthoredPullRequests: 0, - collisionClusters: input.collisionClusters ?? 0, - ageBuckets: { under7Days: 0, days7To30: 0, over30Days: input.over30Days ?? 0 }, - likelyReviewablePullRequests: input.likelyReviewablePullRequests ?? 0, - }, - findings: [], - }; -} - -const componentByName = (breakdown: ReturnType, name: string) => - breakdown.components.find((entry) => entry.component === name)!; - -describe("queue burden breakdown", () => { - it("reports all-zero burden with no active levers and a complete component set", () => { - const breakdown = explainQueueBurden(makeHealth({})); - expect(breakdown.totalPenalty).toBe(0); - expect(breakdown.totalCredit).toBe(0); - expect(breakdown.rawBurden).toBe(0); - expect(breakdown.clamped).toBe(false); - // Six penalty signals plus the reviewable credit. - expect(breakdown.components).toHaveLength(7); - for (const entry of breakdown.components.filter((c) => c.component !== "likelyReviewablePullRequests")) { - expect(entry.band).toBe("none"); - expect(entry.sharePercent).toBe(0); - expect(entry.leverageScore).toBe(0); - } - const credit = componentByName(breakdown, "likelyReviewablePullRequests"); - expect(credit.band).toBe("credit"); - expect(credit.leverageScore).toBe(0); - // No active penalty → an honest no-op lever, never an arbitrary alphabetically-first component. - expect(breakdown.highestLeverageLever.component).toBe("none"); - expect(breakdown.highestLeverageLever.reason).toMatch(/no active penalty/i); - expect(breakdown.summary).toMatch(/no active contributors/i); - }); - - it("breaks an equal-share tie toward the heavier-weighted contributor, not alphabetical order", () => { - // unlinked (weight 8) and stale (weight 6) both reach a 24-point contribution → equal share; the heavier - // per-unit weight (unlinked) is the better lever even though "stalePullRequests" sorts later alphabetically. - const breakdown = explainQueueBurden(makeHealth({ unlinkedPullRequests: 3, stalePullRequests: 4, burdenScore: 48 })); - expect(componentByName(breakdown, "unlinkedPullRequests").sharePercent).toBe(50); - expect(componentByName(breakdown, "stalePullRequests").sharePercent).toBe(50); - expect(breakdown.highestLeverageLever.component).toBe("unlinkedPullRequests"); - }); - - it("names a real penalty lever even when the reviewable credit is offsetting burden", () => { - // Realistic: 3 open PRs (18 penalty), 3 reviewable (-6 credit) → still an open-PR lever to pull. - const breakdown = explainQueueBurden(makeHealth({ openPullRequests: 3, likelyReviewablePullRequests: 3 })); - expect(breakdown.highestLeverageLever.component).toBe("openPullRequests"); - expect(breakdown.highestLeverageLever.component).not.toBe("none"); - }); - - it("flags the dominant contributor as high band and the top lever", () => { - // collisionClusters carries weight 10 → 50 of a 64 total penalty (≈78% share, high band). - const breakdown = explainQueueBurden( - makeHealth({ collisionClusters: 5, unlinkedPullRequests: 1, openPullRequests: 1, burdenScore: 64, level: "high" }), - ); - const collisions = componentByName(breakdown, "collisionClusters"); - expect(collisions.contribution).toBe(50); - expect(collisions.sharePercent).toBe(78); - expect(collisions.band).toBe("high"); - expect(breakdown.totalPenalty).toBe(64); - expect(breakdown.rawBurden).toBe(64); - expect(breakdown.clamped).toBe(false); - expect(breakdown.highestLeverageLever.component).toBe("collisionClusters"); - expect(breakdown.highestLeverageLever.reason).toMatch(/dominant/i); - // unlinked at 8/64 ≈ 13% is below the moderate threshold → low band. - expect(componentByName(breakdown, "unlinkedPullRequests").band).toBe("low"); - }); - - it("classifies a moderate top contributor and names the largest-remaining lever", () => { - // Three equal 12-point contributors → 36 total, 33% each (moderate); name tie-break picks openPullRequests. - const breakdown = explainQueueBurden( - makeHealth({ openPullRequests: 2, stalePullRequests: 2, over30Days: 3, burdenScore: 36, level: "medium" }), - ); - const openPr = componentByName(breakdown, "openPullRequests"); - expect(openPr.sharePercent).toBe(33); - expect(openPr.band).toBe("moderate"); - expect(breakdown.highestLeverageLever.component).toBe("openPullRequests"); - expect(breakdown.highestLeverageLever.reason).toMatch(/largest remaining/i); - }); - - it("marks the breakdown clamped when raw penalties exceed 100", () => { - const breakdown = explainQueueBurden(makeHealth({ collisionClusters: 11, burdenScore: 100, level: "critical" })); - expect(breakdown.rawBurden).toBe(110); - expect(breakdown.clamped).toBe(true); - expect(breakdown.burdenScore).toBe(100); - }); - - it("applies the reviewable credit as an offset without ever driving burden negative", () => { - // Realistic: reviewable PRs cannot exceed open PRs. 4 open (24 penalty) with 4 reviewable (-8 credit). - const breakdown = explainQueueBurden(makeHealth({ openPullRequests: 4, likelyReviewablePullRequests: 4 })); - expect(breakdown.totalPenalty).toBe(24); - expect(breakdown.totalCredit).toBe(8); - expect(breakdown.rawBurden).toBe(16); - expect(breakdown.clamped).toBe(false); - const credit = componentByName(breakdown, "likelyReviewablePullRequests"); - expect(credit.contribution).toBe(-8); - expect(credit.band).toBe("credit"); - expect(credit.leverageScore).toBe(0); - expect(credit.summary).toMatch(/readily reviewable/i); - }); - - it("passes through repo identity, level, and generatedAt", () => { - const breakdown = explainQueueBurden( - makeHealth({ repoFullName: "acme/widgets", generatedAt: "2026-01-02T03:04:05.000Z", level: "high", burdenScore: 60, collisionClusters: 6 }), - ); - expect(breakdown.repoFullName).toBe("acme/widgets"); - expect(breakdown.generatedAt).toBe("2026-01-02T03:04:05.000Z"); - expect(breakdown.level).toBe("high"); - expect(breakdown.summary).toMatch(/queue burden is high/i); - }); - - it("never leaks private or reward terminology in any rendered string", () => { - const breakdown = explainQueueBurden( - makeHealth({ openPullRequests: 4, openIssues: 3, unlinkedPullRequests: 2, stalePullRequests: 2, over30Days: 1, collisionClusters: 2, likelyReviewablePullRequests: 1 }), - ); - for (const entry of breakdown.components) { - expect(entry.summary).not.toMatch(FORBIDDEN); - expect(entry.lever).not.toMatch(FORBIDDEN); - } - expect(breakdown.highestLeverageLever.reason).not.toMatch(FORBIDDEN); - expect(breakdown.summary).not.toMatch(FORBIDDEN); - }); - - it("recomposes the exact burdenScore the engine computes (weight drift guard)", () => { - const repo = { fullName: "owner/repo", isRegistered: true } as unknown as RepositoryRecord; - const fresh = new Date().toISOString(); - const pullRequests: PullRequestRecord[] = [ - // Linked + fresh → readily reviewable credit, not unlinked, not stale. - { repoFullName: "owner/repo", number: 1, title: "linked fresh", state: "open", labels: [], linkedIssues: [10], updatedAt: fresh }, - // Unlinked + aged → unlinked + stale + over-30. - { repoFullName: "owner/repo", number: 2, title: "aged unlinked", state: "open", labels: [], linkedIssues: [], updatedAt: "2020-01-01T00:00:00.000Z" }, - // Unlinked + aged draft → unlinked + stale + over-30. - { repoFullName: "owner/repo", number: 3, title: "aged draft", state: "open", labels: [], linkedIssues: [], updatedAt: "2020-01-01T00:00:00.000Z", isDraft: true }, - ]; - const issues = [{ repoFullName: "owner/repo", number: 10, title: "open issue", state: "open", labels: [], linkedPrs: [], body: null }]; - const collisions = { repoFullName: "owner/repo", summary: { clusterCount: 2, highRiskCount: 0 } } as unknown as CollisionReport; - - const health = buildQueueHealth(repo, issues, pullRequests, collisions); - const breakdown = explainQueueBurden(health); - - // openPRs 3×6 + openIssues 1×1 + unlinked 2×8 + stale 2×6 + over30 2×4 + clusters 2×10 − reviewable 1×2 = 73. - expect(health.burdenScore).toBe(73); - expect(breakdown.rawBurden).toBe(73); - expect(clamp(breakdown.rawBurden)).toBe(health.burdenScore); - expect(componentByName(breakdown, "unlinkedPullRequests").count).toBe(2); - expect(componentByName(breakdown, "likelyReviewablePullRequests").count).toBe(1); - }); -}); diff --git a/test/unit/review-labeling-rules.test.ts b/test/unit/review-labeling-rules.test.ts deleted file mode 100644 index 622ce2673e..0000000000 --- a/test/unit/review-labeling-rules.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { parseFocusManifest, reviewConfigToJson } from "../../src/signals/focus-manifest"; -import { resolveLabelingRules } from "../../src/review/labeling-rules"; - -const rulesOf = (labeling_rules: unknown) => parseFocusManifest({ review: { labeling_rules } }); -const facts = (over: Partial<{ changedPaths: string[]; title: string; description: string }> = {}) => ({ - changedPaths: [], - title: "", - description: "", - ...over, -}); - -describe("review.labeling_rules parse + round-trip (#2045)", () => { - it("absent ⇒ empty and OMITTED on serialize (byte-identical)", () => { - const review = parseFocusManifest({ review: { note: "x" } }).review; - expect(review.labelingRules).toEqual([]); - expect("labeling_rules" in (reviewConfigToJson(review) as Record)).toBe(false); - }); - - it("a full rule round-trips parse → serialize → parse identically", () => { - const review = rulesOf([ - { label: "area:docs", when_paths: ["docs/**"], title_contains: "doc", description_contains: "readme" }, - ]).review; - expect(review.labelingRules).toEqual([ - { label: "area:docs", whenPaths: ["docs/**"], titleContains: "doc", descriptionContains: "readme" }, - ]); - const json = reviewConfigToJson(review) as Record; - expect(json.labeling_rules).toEqual([ - { label: "area:docs", when_paths: ["docs/**"], title_contains: "doc", description_contains: "readme" }, - ]); - expect(parseFocusManifest({ review: json }).review.labelingRules).toEqual(review.labelingRules); - }); - - it("serializes only the criteria that are set (a path-only rule omits title/description keys)", () => { - const review = rulesOf([{ label: "area:ci", when_paths: [".github/**"] }]).review; - expect((reviewConfigToJson(review) as Record).labeling_rules).toEqual([ - { label: "area:ci", when_paths: [".github/**"] }, - ]); - }); - - it("refuses a reserved gittensor: label and warns", () => { - const m = rulesOf([{ label: "gittensor:feature", when_paths: ["src/**"] }]); - expect(m.review.labelingRules).toEqual([]); - expect(m.warnings.some((w) => /reserved "gittensor:" namespace/.test(w))).toBe(true); - }); - - it("drops a rule with no when-criterion, a rule with no label, and a non-mapping entry (each warns)", () => { - const m = rulesOf([{ label: "area:x" }, { when_paths: ["a/**"] }, "nope"]); - expect(m.review.labelingRules).toEqual([]); - expect(m.warnings.some((w) => /needs at least one of when_paths/.test(w))).toBe(true); - expect(m.warnings.some((w) => /\.label" is required/.test(w))).toBe(true); - expect(m.warnings.some((w) => /\[2\]" must be a mapping/.test(w))).toBe(true); - }); - - it("a present-but-invalid (non-string) label is dropped and warned by the text validator (not 'required')", () => { - const m = rulesOf([{ label: 123, when_paths: ["src/**"] }]); - expect(m.review.labelingRules).toEqual([]); - expect(m.warnings.some((w) => /labeling_rules\[0\]\.label/.test(w))).toBe(true); - }); - - it("a title-only rule round-trips with when_paths omitted", () => { - const review = rulesOf([{ label: "type:wip", title_contains: "WIP" }]).review; - expect(review.labelingRules).toEqual([ - { label: "type:wip", whenPaths: [], titleContains: "WIP", descriptionContains: null }, - ]); - expect((reviewConfigToJson(review) as Record).labeling_rules).toEqual([ - { label: "type:wip", title_contains: "WIP" }, - ]); - }); - - it("a non-list labeling_rules warns and is ignored", () => { - const m = rulesOf("nope"); - expect(m.review.labelingRules).toEqual([]); - expect(m.warnings.some((w) => /"review\.labeling_rules" must be a list/.test(w))).toBe(true); - }); - - it("caps at 50 rules", () => { - const many = Array.from({ length: 60 }, (_, i) => ({ label: `area:${i}`, when_paths: ["src/**"] })); - const m = rulesOf(many); - expect(m.review.labelingRules.length).toBe(50); - expect(m.warnings.some((w) => /capped at 50/.test(w))).toBe(true); - }); -}); - -describe("resolveLabelingRules deterministic evaluation (#2045)", () => { - const rules = [ - { label: "area:docs", whenPaths: ["docs/**"], titleContains: null, descriptionContains: null }, - { label: "type:wip", whenPaths: [], titleContains: "WIP", descriptionContains: null }, - { label: "needs:migration", whenPaths: ["migrations/**"], titleContains: null, descriptionContains: "schema" }, - ]; - - it("fires a path rule only when a changed path matches", () => { - expect(resolveLabelingRules({ rules, facts: facts({ changedPaths: ["docs/readme.md"] }), autoLabelEnabled: false }).suggest).toEqual(["area:docs"]); - expect(resolveLabelingRules({ rules, facts: facts({ changedPaths: ["src/a.ts"] }), autoLabelEnabled: false }).suggest).toEqual([]); - }); - - it("title match is case-insensitive; a multi-criterion rule needs ALL criteria", () => { - expect(resolveLabelingRules({ rules, facts: facts({ title: "wip: draft" }), autoLabelEnabled: false }).suggest).toEqual(["type:wip"]); - // needs:migration requires BOTH a migrations/** path AND "schema" in the description - expect(resolveLabelingRules({ rules, facts: facts({ changedPaths: ["migrations/001.sql"] }), autoLabelEnabled: false }).suggest).toEqual([]); - expect(resolveLabelingRules({ rules, facts: facts({ changedPaths: ["migrations/001.sql"], description: "adds a schema column" }), autoLabelEnabled: false }).suggest).toEqual(["needs:migration"]); - }); - - it("apply is empty unless autoLabelEnabled, then mirrors suggest", () => { - const f = facts({ changedPaths: ["docs/x.md"], title: "WIP" }); - expect(resolveLabelingRules({ rules, facts: f, autoLabelEnabled: false })).toEqual({ suggest: ["area:docs", "type:wip"], apply: [] }); - expect(resolveLabelingRules({ rules, facts: f, autoLabelEnabled: true })).toEqual({ suggest: ["area:docs", "type:wip"], apply: ["area:docs", "type:wip"] }); - }); - - it("dedupes a label shared by two firing rules, preserving first-seen order", () => { - const dup = [ - { label: "area:x", whenPaths: ["a/**"], titleContains: null, descriptionContains: null }, - { label: "area:x", whenPaths: ["b/**"], titleContains: null, descriptionContains: null }, - ]; - expect(resolveLabelingRules({ rules: dup, facts: facts({ changedPaths: ["a/1", "b/2"] }), autoLabelEnabled: true }).suggest).toEqual(["area:x"]); - }); -}); diff --git a/test/unit/settings-drift.test.ts b/test/unit/settings-drift.test.ts deleted file mode 100644 index 675476cb19..0000000000 --- a/test/unit/settings-drift.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { describe, expect, it, vi } from "vitest"; -import * as repositories from "../../src/db/repositories"; -import { parseFocusManifest } from "../../src/signals/focus-manifest"; -import { upsertRepoFocusManifest } from "../../src/signals/focus-manifest-loader"; -import { computeSettingsDrift, computeSettingsDriftForRepo } from "../../src/settings/settings-drift"; -import type { RepositorySettings } from "../../src/types"; -import { createTestEnv } from "../helpers/d1"; - -function fields(entries: ReturnType): string[] { - return entries.map((entry) => entry.field).sort(); -} - -describe("computeSettingsDrift (#config-drift-audit)", () => { - it("reports no drift for an empty manifest", () => { - const dbSettings = { gittensorLabel: "gittensor", qualityGateMinScore: 50 } as RepositorySettings; - expect(computeSettingsDrift(dbSettings, parseFocusManifest(null))).toEqual([]); - }); - - it("reports a settings: override that differs from the DB value", () => { - const dbSettings = { gittensorLabel: "gittensor" } as RepositorySettings; - const manifest = parseFocusManifest({ settings: { gittensorLabel: "custom-label" } }); - const drift = computeSettingsDrift(dbSettings, manifest); - expect(drift).toEqual([{ field: "gittensorLabel", dbValue: "gittensor", effectiveValue: "custom-label" }]); - }); - - it("does NOT report drift when the manifest sets the SAME value already in the DB", () => { - const dbSettings = { gittensorLabel: "gittensor" } as RepositorySettings; - const manifest = parseFocusManifest({ settings: { gittensorLabel: "gittensor" } }); - expect(computeSettingsDrift(dbSettings, manifest)).toEqual([]); - }); - - it("reports a gate: override the same way as an equivalent settings: override", () => { - const dbSettings = { gateCheckMode: "off" } as RepositorySettings; - const manifest = parseFocusManifest({ gate: { enabled: true } }); - const drift = computeSettingsDrift(dbSettings, manifest); - expect(drift).toEqual([{ field: "gateCheckMode", dbValue: "off", effectiveValue: "enabled" }]); - }); - - it("detects array-valued drift (hardGuardrailGlobs) by content, not by reference", () => { - const dbSettings = { hardGuardrailGlobs: ["src/scoring/**"] } as RepositorySettings; - const sameContent = parseFocusManifest({ settings: { hardGuardrailGlobs: ["src/scoring/**"] } }); - expect(computeSettingsDrift(dbSettings, sameContent)).toEqual([]); - - const different = parseFocusManifest({ settings: { hardGuardrailGlobs: ["src/settings/**"] } }); - const drift = computeSettingsDrift(dbSettings, different); - expect(drift).toEqual([{ field: "hardGuardrailGlobs", dbValue: ["src/scoring/**"], effectiveValue: ["src/settings/**"] }]); - }); - - it("detects object-valued drift (typeLabels) from a sparse per-category manifest override", () => { - const dbSettings = { typeLabels: { bug: "bug", feature: "enhancement" } } as unknown as RepositorySettings; - const manifest = parseFocusManifest({ settings: { typeLabels: { bug: "defect" } } }); - const drift = computeSettingsDrift(dbSettings, manifest); - expect(drift).toEqual([ - { field: "typeLabels", dbValue: { bug: "bug", feature: "enhancement" }, effectiveValue: { bug: "defect", feature: "enhancement" } }, - ]); - }); - - it("does not report contributorBlacklist drift from the shared/global blacklist merge alone (manifest-independent normalization, not manifest shadowing)", () => { - const dbSettings = { contributorBlacklist: [] } as unknown as RepositorySettings; - // No manifest override at all, but a non-empty shared/global blacklist -- resolveEffectiveSettings ALWAYS - // merges this in regardless of manifest presence, so it must not be misreported as manifest-driven drift. - const drift = computeSettingsDrift(dbSettings, parseFocusManifest(null), [{ login: "GlobalBad", reason: "global" }]); - expect(drift.some((entry) => entry.field === "contributorBlacklist")).toBe(false); - }); - - it("still reports a MANIFEST-driven contributorBlacklist entry on top of an unrelated shared blacklist", () => { - const dbSettings = { contributorBlacklist: [] } as unknown as RepositorySettings; - const manifest = parseFocusManifest({ settings: { contributorBlacklist: [{ login: "ManifestBad" }] } }); - const drift = computeSettingsDrift(dbSettings, manifest, [{ login: "GlobalBad", reason: "global" }]); - const entry = drift.find((e) => e.field === "contributorBlacklist"); - expect(entry?.effectiveValue).toEqual(expect.arrayContaining([expect.objectContaining({ login: "ManifestBad" }), expect.objectContaining({ login: "GlobalBad" })])); - }); - - it("does not report drift for a DB field the manifest never touches, even when other fields drift", () => { - const dbSettings = { gittensorLabel: "gittensor", checkRunMode: "enabled" } as RepositorySettings; - const manifest = parseFocusManifest({ settings: { gittensorLabel: "custom-label" } }); - expect(fields(computeSettingsDrift(dbSettings, manifest))).toEqual(["gittensorLabel"]); - }); -}); - -describe("computeSettingsDriftForRepo — live DB + manifest fetch (#config-drift-audit)", () => { - it("reports no drift for a repo with DB settings only, no manifest", async () => { - const env = createTestEnv(); - const repo = "acme/no-manifest"; - await env.DB.prepare("INSERT INTO repositories (full_name, owner, name, is_installed, is_registered) VALUES (?, 'acme', 'no-manifest', 1, 1)").bind(repo).run(); - await repositories.upsertRepositorySettings(env, { repoFullName: repo, gittensorLabel: "gittensor" }); - expect(await computeSettingsDriftForRepo(env, repo)).toEqual([]); - }); - - it("reports drift for a repo whose manifest shadows a DB-stored field", async () => { - const env = createTestEnv(); - const repo = "acme/shadowed"; - await env.DB.prepare("INSERT INTO repositories (full_name, owner, name, is_installed, is_registered) VALUES (?, 'acme', 'shadowed', 1, 1)").bind(repo).run(); - await Promise.all([ - repositories.upsertRepositorySettings(env, { repoFullName: repo, gittensorLabel: "gittensor" }), - upsertRepoFocusManifest(env, repo, { settings: { gittensorLabel: "manifest-label" } }, "api_record"), - ]); - const drift = await computeSettingsDriftForRepo(env, repo); - expect(drift).toEqual([{ field: "gittensorLabel", dbValue: "gittensor", effectiveValue: "manifest-label" }]); - }); - - it("falls back to an empty shared blacklist (never throws) when the global blacklist read rejects", async () => { - const env = createTestEnv(); - const repo = "acme/blacklist-read-fails"; - await env.DB.prepare("INSERT INTO repositories (full_name, owner, name, is_installed, is_registered) VALUES (?, 'acme', 'blacklist-read-fails', 1, 1)").bind(repo).run(); - await repositories.upsertRepositorySettings(env, { repoFullName: repo, gittensorLabel: "gittensor" }); - const getGlobalSpy = vi.spyOn(repositories, "getGlobalContributorBlacklist").mockRejectedValue(new Error("transient DB issue")); - try { - await expect(computeSettingsDriftForRepo(env, repo)).resolves.toEqual([]); - } finally { - getGlobalSpy.mockRestore(); - } - }); -}); From 99818285aab40a3d8ad2d54f28c0e330025ac078 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Tue, 7 Jul 2026 04:37:07 -0700 Subject: [PATCH 2/3] docs(review): mark buildIssueRagQuery as intentionally pre-built (#2320) Removed its only test caller (the deleted workboard test) from adapters.test.ts and left the module and its dedicated test suite untouched -- this is forward groundwork for a not-yet-built miner-side issue-analysis feature, not dead code. --- src/review/issue-rag-wire.ts | 1 + test/unit/adapters.test.ts | 42 ------------------------------------ 2 files changed, 1 insertion(+), 42 deletions(-) diff --git a/src/review/issue-rag-wire.ts b/src/review/issue-rag-wire.ts index 394ac01528..ca044ff7ca 100644 --- a/src/review/issue-rag-wire.ts +++ b/src/review/issue-rag-wire.ts @@ -20,6 +20,7 @@ function cleanLabels(labels: string[] | undefined): string[] { .slice(0, MAX_ISSUE_LABELS); } +// Intentionally pre-built and currently unreached: no miner-side issue-analysis caller exists yet (#2320). export function buildIssueRagQuery(input: IssueRagQueryInput): { queryText: string } { const sections: string[] = []; const title = input.title.trim(); diff --git a/test/unit/adapters.test.ts b/test/unit/adapters.test.ts index 83229e0793..e246f96b5e 100644 --- a/test/unit/adapters.test.ts +++ b/test/unit/adapters.test.ts @@ -1,9 +1,7 @@ import { afterEach, describe, expect, it, vi } from "vitest"; -import { buildWorkboard } from "../../src/api/workboard"; import { normalizeGittBountySnapshot } from "../../src/bounties/ingest"; import { fetchPublicContributorProfile } from "../../src/github/public"; import { jsonString, normalizeRepoFullName, parseJson, repoParts } from "../../src/utils/json"; -import type { IssueRecord, RepositoryRecord } from "../../src/types"; describe("small adapters and normalizers", () => { afterEach(() => { @@ -61,46 +59,6 @@ describe("small adapters and normalizers", () => { expect(records[2]?.payload).not.toHaveProperty("active"); }); - it("builds workboard holds and maintainer-authored context", () => { - const repo: RepositoryRecord = { - fullName: "JSONbored/gittensory", - owner: "JSONbored", - name: "gittensory", - isInstalled: true, - isRegistered: false, - isPrivate: true, - }; - const issues: IssueRecord[] = [ - { - repoFullName: repo.fullName, - number: 1, - title: "Add queue health endpoint", - state: "open", - authorLogin: "maintainer", - authorAssociation: "OWNER", - labels: [], - linkedPrs: [7], - }, - ]; - - expect(buildWorkboard(null, issues)).toEqual([]); - const item = buildWorkboard(repo, issues)[0]; - expect(item).toMatchObject({ fit: "hold", issueNumber: 1 }); - expect(item?.reasons).toEqual(expect.arrayContaining(["Repository is not present in the latest registry snapshot.", "Issue already has linked pull requests.", "Issue was opened by a maintainer-associated account."])); - - const registeredRepo = { ...repo, isRegistered: true, isPrivate: false }; - const baseIssue = issues[0]!; - expect( - buildWorkboard(registeredRepo, [ - { ...baseIssue, number: 2, linkedPrs: [], authorAssociation: "CONTRIBUTOR" }, - { ...baseIssue, number: 3, linkedPrs: [9], authorAssociation: "CONTRIBUTOR" }, - ]), - ).toEqual([ - expect.objectContaining({ fit: "good", reasons: ["Open issue with no linked pull request detected by Gittensory."] }), - expect.objectContaining({ fit: "caution", reasons: ["Issue already has linked pull requests."] }), - ]); - }); - it("fetches public contributor profile languages and handles unavailable GitHub responses", async () => { vi.stubGlobal("fetch", async (input: RequestInfo | URL) => { const url = input.toString(); From 098edbe30eff63647f7c08b6982802f05a4c6b4a Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Tue, 7 Jul 2026 06:22:04 -0700 Subject: [PATCH 3/3] chore(db): drop the never-read privateTrustEnabled setting (#4012) settings.privateTrustEnabled was persisted and exposed via the maintainer API but read by zero conditional logic anywhere in src/ -- only ever assigned and passed through. Its doc comment described gating "private trust signals in scoring", but this repo's house rules explicitly forbid wiring in raw trust scores, so removal is the correct disposition rather than implementing the described behavior. Removes the field from the Drizzle schema, RepositorySettings type, both repository accessors, the two API route schemas, the OpenAPI schema, the focus-manifest parser and its mirrored type in the standalone gittensory-engine package, the two .yml config examples, the settings docs page, and every test fixture that plumbed the field through. Adds migration 0122 to drop the now-unused private_trust_enabled column. --- .gittensory.yml.example | 3 --- apps/gittensory-ui/public/openapi.json | 4 ---- apps/gittensory-ui/src/routes/docs.tuning.tsx | 7 +++---- config/examples/gittensory.full.yml | 3 --- migrations/0122_drop_private_trust_enabled.sql | 6 ++++++ packages/gittensory-engine/src/focus-manifest.ts | 3 +-- .../gittensory-engine/src/types/manifest-deps-types.ts | 1 - src/api/routes.ts | 8 +++----- src/db/repositories.ts | 7 +------ src/db/schema.ts | 1 - src/openapi/schemas.ts | 1 - src/types.ts | 1 - test/integration/routes-errors.test.ts | 3 +-- test/unit/backfill.test.ts | 3 --- test/unit/focus-manifest.test.ts | 3 --- test/unit/maintainer-activation.test.ts | 1 - test/unit/policy-sanitizer.test.ts | 1 - test/unit/queue.test.ts | 10 ---------- test/unit/registration-readiness.test.ts | 1 - test/unit/repo-policy-readiness.test.ts | 1 - test/unit/repository-settings-enforcement.test.ts | 1 - test/unit/self-dogfood-registration-pack.test.ts | 1 - test/unit/settings-preview.test.ts | 1 - test/unit/signals-coverage.test.ts | 1 - test/unit/signals-v2.test.ts | 1 - test/unit/signals.test.ts | 6 ------ test/unit/unified-comment-parity.test.ts | 1 - 27 files changed, 15 insertions(+), 65 deletions(-) create mode 100644 migrations/0122_drop_private_trust_enabled.sql diff --git a/.gittensory.yml.example b/.gittensory.yml.example index 08c4ffa618..f5a955b7f9 100644 --- a/.gittensory.yml.example +++ b/.gittensory.yml.example @@ -607,9 +607,6 @@ settings: # Bool. Default: true. backfillEnabled: true - # Use private trust signals in scoring. Bool. Default: true. - privateTrustEnabled: true - # Render a README status badge for the repo. Bool. Default: false. badgeEnabled: false diff --git a/apps/gittensory-ui/public/openapi.json b/apps/gittensory-ui/public/openapi.json index 34d2a92fc7..7eeb1e007a 100644 --- a/apps/gittensory-ui/public/openapi.json +++ b/apps/gittensory-ui/public/openapi.json @@ -8895,9 +8895,6 @@ "backfillEnabled": { "type": "boolean" }, - "privateTrustEnabled": { - "type": "boolean" - }, "badgeEnabled": { "type": "boolean" }, @@ -9336,7 +9333,6 @@ "includeMaintainerAuthors", "requireLinkedIssue", "backfillEnabled", - "privateTrustEnabled", "commandAuthorization" ] }, diff --git a/apps/gittensory-ui/src/routes/docs.tuning.tsx b/apps/gittensory-ui/src/routes/docs.tuning.tsx index 46bac21749..13e6f61052 100644 --- a/apps/gittensory-ui/src/routes/docs.tuning.tsx +++ b/apps/gittensory-ui/src/routes/docs.tuning.tsx @@ -464,10 +464,9 @@ function Tuning() {
  • includeMaintainerAuthors (default false),{" "} requireLinkedIssue (default false), backfillEnabled{" "} - (default true), privateTrustEnabled (default true), - and badgeEnabled (README status badge, default false), and{" "} - publicQualityMetrics (public review-quality page, default false - ). + (default true), and badgeEnabled (README status badge, default{" "} + false), and publicQualityMetrics (public review-quality page, + default false).
  • agentPaused (per-repo kill-switch, default false) and{" "} diff --git a/config/examples/gittensory.full.yml b/config/examples/gittensory.full.yml index a5b2fd8e9a..124d96d809 100644 --- a/config/examples/gittensory.full.yml +++ b/config/examples/gittensory.full.yml @@ -620,9 +620,6 @@ settings: # Bool. Default: true. backfillEnabled: true - # Use private trust signals in scoring. Bool. Default: true. - privateTrustEnabled: true - # Render a README status badge for the repo. Bool. Default: false. badgeEnabled: false diff --git a/migrations/0122_drop_private_trust_enabled.sql b/migrations/0122_drop_private_trust_enabled.sql new file mode 100644 index 0000000000..b65d90d3b2 --- /dev/null +++ b/migrations/0122_drop_private_trust_enabled.sql @@ -0,0 +1,6 @@ +-- Dead-code cleanup (#4012). private_trust_enabled was persisted and exposed via the maintainer settings +-- API but read by zero conditional logic anywhere in src/ -- only ever assigned and passed through. Its doc +-- comment described gating "private trust signals in scoring", which this repo's house rules explicitly +-- forbid wiring in (no trust scores / reward values anywhere), so the correct disposition is removal, not +-- implementation. SQLite 3.35+ / D1 supports DROP COLUMN directly. +ALTER TABLE repository_settings DROP COLUMN private_trust_enabled; diff --git a/packages/gittensory-engine/src/focus-manifest.ts b/packages/gittensory-engine/src/focus-manifest.ts index 5e58199b49..9afc2bf03f 100644 --- a/packages/gittensory-engine/src/focus-manifest.ts +++ b/packages/gittensory-engine/src/focus-manifest.ts @@ -278,7 +278,6 @@ export type FocusManifestSettings = Partial< | "includeMaintainerAuthors" | "requireLinkedIssue" | "backfillEnabled" - | "privateTrustEnabled" | "autonomy" | "autoMaintain" | "agentPaused" @@ -1535,7 +1534,7 @@ function parseSettingsOverride(value: JsonValue | undefined, warnings: string[]) } const publicSurface = normalizeOptionalEnum(r.publicSurface, "settings.publicSurface", ["off", "comment_and_label", "comment_only", "label_only"] as const, warnings); if (publicSurface !== null) out.publicSurface = publicSurface; - for (const key of ["aiReviewByok", "aiReviewAllAuthors", "closeOwnerAuthors", "autoLabelEnabled", "typeLabelsEnabled", "badgeEnabled", "publicQualityMetrics", "createMissingLabel", "includeMaintainerAuthors", "requireLinkedIssue", "backfillEnabled", "privateTrustEnabled", "agentPaused", "agentDryRun"] as const) { + for (const key of ["aiReviewByok", "aiReviewAllAuthors", "closeOwnerAuthors", "autoLabelEnabled", "typeLabelsEnabled", "badgeEnabled", "publicQualityMetrics", "createMissingLabel", "includeMaintainerAuthors", "requireLinkedIssue", "backfillEnabled", "agentPaused", "agentDryRun"] as const) { const flag = normalizeOptionalBoolean(r[key], `settings.${key}`, warnings); if (flag !== null) out[key] = flag; } diff --git a/packages/gittensory-engine/src/types/manifest-deps-types.ts b/packages/gittensory-engine/src/types/manifest-deps-types.ts index c6736de040..ba64bddd55 100644 --- a/packages/gittensory-engine/src/types/manifest-deps-types.ts +++ b/packages/gittensory-engine/src/types/manifest-deps-types.ts @@ -309,7 +309,6 @@ export type RepositorySettings = { includeMaintainerAuthors: boolean; requireLinkedIssue: boolean; backfillEnabled: boolean; - privateTrustEnabled: boolean; /** Opt-in for the public, unauthenticated README status badge (#541). Always populated by the DB layer * (default false); optional so existing settings fixtures/callers need not be touched. */ badgeEnabled?: boolean | undefined; diff --git a/src/api/routes.ts b/src/api/routes.ts index dbd3c3ca6e..2949e9e9aa 100644 --- a/src/api/routes.ts +++ b/src/api/routes.ts @@ -681,7 +681,6 @@ const repositorySettingsSchema = z.object({ includeMaintainerAuthors: z.boolean().default(false), requireLinkedIssue: z.boolean().default(false), backfillEnabled: z.boolean().default(true), - privateTrustEnabled: z.boolean().default(true), badgeEnabled: z.boolean().default(false), publicQualityMetrics: z.boolean().default(false), commandAuthorization: z @@ -700,9 +699,9 @@ const repositorySettingsSchema = z.object({ // #130 maintainer self-serve settings editor. A PATCH-style subset: every field optional so the maintainer // dashboard can save just the group it changed. Excludes the secret-bearing aiReview* group (set via the -// dedicated /ai-review + /ai-key routes) and the operator-only scoring internals (backfillEnabled, -// privateTrustEnabled). The handler loads current settings and merges, since upsertRepositorySettings -// defaults any absent field rather than preserving it. +// dedicated /ai-review + /ai-key routes) and the operator-only scoring internal (backfillEnabled). The +// handler loads current settings and merges, since upsertRepositorySettings defaults any absent field +// rather than preserving it. const maintainerSettingsSchema = z .object({ commentMode: z.enum(["off", "detected_contributors_only", "all_prs"]), @@ -3823,7 +3822,6 @@ export function createApp() { includeMaintainerAuthors: parsed.data.includeMaintainerAuthors, requireLinkedIssue: parsed.data.requireLinkedIssue, backfillEnabled: parsed.data.backfillEnabled, - privateTrustEnabled: parsed.data.privateTrustEnabled, badgeEnabled: parsed.data.badgeEnabled, publicQualityMetrics: parsed.data.publicQualityMetrics, commandAuthorization: normalizeCommandAuthorizationPolicy(parsed.data.commandAuthorization).policy, diff --git a/src/db/repositories.ts b/src/db/repositories.ts index fcd0e2dfea..0e3a6e096a 100644 --- a/src/db/repositories.ts +++ b/src/db/repositories.ts @@ -534,7 +534,6 @@ export async function getRepositorySettings(env: Env, fullName: string): Promise includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, badgeEnabled: false, publicQualityMetrics: false, agentPaused: false, @@ -612,7 +611,6 @@ export async function getRepositorySettings(env: Env, fullName: string): Promise includeMaintainerAuthors: row.includeMaintainerAuthors, requireLinkedIssue: row.requireLinkedIssue, backfillEnabled: row.backfillEnabled, - privateTrustEnabled: row.privateTrustEnabled, badgeEnabled: row.badgeEnabled, publicQualityMetrics: row.publicQualityMetrics, agentPaused: row.agentPaused, @@ -733,7 +731,6 @@ export async function upsertRepositorySettings(env: Env, settings: Partial { publicSignalLevel: "minimal", checkRunDetailLevel: "deep", backfillEnabled: false, - privateTrustEnabled: false, }), }, env, ); expect(updated.status).toBe(200); - await expect(updated.json()).resolves.toMatchObject({ commentMode: "all_prs", checkRunDetailLevel: "deep", backfillEnabled: false, privateTrustEnabled: false }); + await expect(updated.json()).resolves.toMatchObject({ commentMode: "all_prs", checkRunDetailLevel: "deep", backfillEnabled: false }); }); }); diff --git a/test/unit/backfill.test.ts b/test/unit/backfill.test.ts index fb25cf3711..3666963751 100644 --- a/test/unit/backfill.test.ts +++ b/test/unit/backfill.test.ts @@ -1155,7 +1155,6 @@ describe("GitHub backfill", () => { checkRunMode: "enabled", checkRunDetailLevel: "standard", backfillEnabled: false, - privateTrustEnabled: true, }); const result = await backfillRegisteredRepositories(env); @@ -3017,7 +3016,6 @@ describe("GitHub backfill", () => { checkRunMode: "enabled", checkRunDetailLevel: "standard", backfillEnabled: false, - privateTrustEnabled: true, }); await expect(enqueueRepositoryOpenDataBackfill(env, { repoFullName: "missing/repo", requestedBy: "api" })).resolves.toMatchObject({ status: "skipped" }); @@ -3030,7 +3028,6 @@ describe("GitHub backfill", () => { checkRunMode: "enabled", checkRunDetailLevel: "standard", backfillEnabled: true, - privateTrustEnabled: true, }); await upsertRepoSyncSegment(env, { repoFullName: "JSONbored/gittensory", diff --git a/test/unit/focus-manifest.test.ts b/test/unit/focus-manifest.test.ts index 59646e6e41..cbcb7d27f8 100644 --- a/test/unit/focus-manifest.test.ts +++ b/test/unit/focus-manifest.test.ts @@ -305,7 +305,6 @@ describe(".gittensory.yml.example field-exhaustiveness (#1670)", () => { includeMaintainerAuthors: "includeMaintainerAuthors:", requireLinkedIssue: "requireLinkedIssue:", backfillEnabled: "backfillEnabled:", - privateTrustEnabled: "privateTrustEnabled:", autonomy: "autonomy:", autoMaintain: "autoMaintain:", agentPaused: "agentPaused:", @@ -1755,7 +1754,6 @@ describe("parseFocusManifest settings override + resolveEffectiveSettings", () = includeMaintainerAuthors: true, requireLinkedIssue: true, backfillEnabled: false, - privateTrustEnabled: true, }, }); expect(m.present).toBe(true); @@ -1777,7 +1775,6 @@ describe("parseFocusManifest settings override + resolveEffectiveSettings", () = includeMaintainerAuthors: true, requireLinkedIssue: true, backfillEnabled: false, - privateTrustEnabled: true, }); }); diff --git a/test/unit/maintainer-activation.test.ts b/test/unit/maintainer-activation.test.ts index 18da722617..997001b235 100644 --- a/test/unit/maintainer-activation.test.ts +++ b/test/unit/maintainer-activation.test.ts @@ -48,7 +48,6 @@ function settings(overrides: Partial = {}): RepositorySettin includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off", aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, diff --git a/test/unit/policy-sanitizer.test.ts b/test/unit/policy-sanitizer.test.ts index 2812d92623..72f3678a81 100644 --- a/test/unit/policy-sanitizer.test.ts +++ b/test/unit/policy-sanitizer.test.ts @@ -82,7 +82,6 @@ function settingsFor(repoFullName: string, overrides: Partial { checkRunMode: "off", checkRunDetailLevel: "minimal", backfillEnabled: true, - privateTrustEnabled: true, }); await processJob(env, { type: "github-webhook", @@ -16916,7 +16915,6 @@ describe("queue processors", () => { checkRunMode: "off", checkRunDetailLevel: "minimal", backfillEnabled: true, - privateTrustEnabled: true, }); await processJob(env, { type: "github-webhook", @@ -16964,7 +16962,6 @@ describe("queue processors", () => { checkRunMode: "off", checkRunDetailLevel: "minimal", backfillEnabled: true, - privateTrustEnabled: true, }); await processJob(env, { type: "github-webhook", @@ -17041,7 +17038,6 @@ describe("queue processors", () => { checkRunDetailLevel: "minimal", gateCheckMode: "enabled", backfillEnabled: true, - privateTrustEnabled: true, autonomy: { update_branch: "auto" }, }); let postedBody = ""; @@ -17226,7 +17222,6 @@ describe("queue processors", () => { checkRunDetailLevel: "minimal", gateCheckMode: "enabled", backfillEnabled: true, - privateTrustEnabled: true, autonomy: { update_branch: "auto" }, }); let postedBody = ""; @@ -17370,7 +17365,6 @@ describe("queue processors", () => { checkRunDetailLevel: "minimal", gateCheckMode: "enabled", backfillEnabled: true, - privateTrustEnabled: true, autonomy: { update_branch: "auto" }, }); let postedBody = ""; @@ -17543,7 +17537,6 @@ describe("queue processors", () => { checkRunDetailLevel: "minimal", gateCheckMode: "enabled", backfillEnabled: true, - privateTrustEnabled: true, autonomy: { update_branch: "auto" }, }); let postedBody = ""; @@ -17723,7 +17716,6 @@ describe("queue processors", () => { checkRunDetailLevel: "minimal", gateCheckMode: "enabled", backfillEnabled: true, - privateTrustEnabled: true, autonomy: { update_branch: "auto" }, linkedIssueGateMode: "block", }); @@ -17888,7 +17880,6 @@ describe("queue processors", () => { checkRunDetailLevel: "minimal", gateCheckMode: "enabled", backfillEnabled: true, - privateTrustEnabled: true, autonomy: { update_branch: "auto" }, qualityGateMode: "advisory", qualityGateMinScore: 100, @@ -18290,7 +18281,6 @@ describe("queue processors", () => { checkRunDetailLevel: "minimal", gateCheckMode: "enabled", backfillEnabled: true, - privateTrustEnabled: true, }); // Seed a FAILED check summary with a per-check WHY (codecov-style) so listCheckSummaries returns it and the // unified site populates failingDetails. (The PR row + headSha must match for the check to associate.) diff --git a/test/unit/registration-readiness.test.ts b/test/unit/registration-readiness.test.ts index c19bf18d79..e30ed3eac5 100644 --- a/test/unit/registration-readiness.test.ts +++ b/test/unit/registration-readiness.test.ts @@ -62,7 +62,6 @@ function settingsFor(repoFullName: string, overrides: Partial = {}): RepositorySettin includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off", aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, diff --git a/test/unit/repository-settings-enforcement.test.ts b/test/unit/repository-settings-enforcement.test.ts index 936c0ef895..b5508eea16 100644 --- a/test/unit/repository-settings-enforcement.test.ts +++ b/test/unit/repository-settings-enforcement.test.ts @@ -36,7 +36,6 @@ function settings(over: Partial = {}): RepositorySettings { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off", aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, diff --git a/test/unit/self-dogfood-registration-pack.test.ts b/test/unit/self-dogfood-registration-pack.test.ts index f41c998963..f666afc1bb 100644 --- a/test/unit/self-dogfood-registration-pack.test.ts +++ b/test/unit/self-dogfood-registration-pack.test.ts @@ -75,7 +75,6 @@ function settingsFor(repoFullName: string, overrides: Partial = {}): RepositorySettin includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off", aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, diff --git a/test/unit/signals-coverage.test.ts b/test/unit/signals-coverage.test.ts index 961557653d..b1b70e7bc1 100644 --- a/test/unit/signals-coverage.test.ts +++ b/test/unit/signals-coverage.test.ts @@ -2216,7 +2216,6 @@ function repoSettings(repoFullName: string): RepositorySettings { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off", aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, diff --git a/test/unit/signals-v2.test.ts b/test/unit/signals-v2.test.ts index b01ed8b1b3..a5d685d871 100644 --- a/test/unit/signals-v2.test.ts +++ b/test/unit/signals-v2.test.ts @@ -2105,7 +2105,6 @@ describe("v2 signal builders", () => { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off", aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, diff --git a/test/unit/signals.test.ts b/test/unit/signals.test.ts index 1fbe1af33d..da94eb2702 100644 --- a/test/unit/signals.test.ts +++ b/test/unit/signals.test.ts @@ -523,7 +523,6 @@ describe("world-class backend signals", () => { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off" as const, aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, @@ -578,7 +577,6 @@ describe("world-class backend signals", () => { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off" as const, aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, @@ -653,7 +651,6 @@ describe("world-class backend signals", () => { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off" as const, aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, @@ -782,7 +779,6 @@ describe("world-class backend signals", () => { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off" as const, aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, @@ -853,7 +849,6 @@ describe("world-class backend signals", () => { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off" as const, aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, @@ -968,7 +963,6 @@ describe("world-class backend signals", () => { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off", aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false, diff --git a/test/unit/unified-comment-parity.test.ts b/test/unit/unified-comment-parity.test.ts index f0df9e59da..b9040f7a86 100644 --- a/test/unit/unified-comment-parity.test.ts +++ b/test/unit/unified-comment-parity.test.ts @@ -72,7 +72,6 @@ const settings: RepositorySettings = { includeMaintainerAuthors: false, requireLinkedIssue: false, backfillEnabled: true, - privateTrustEnabled: true, aiReviewMode: "off", aiReviewByok: false, aiReviewAllAuthors: false, closeOwnerAuthors: false,