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/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/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 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/src/types.ts b/src/types.ts
index 24b6e0fa6e..3af634f15a 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -844,7 +844,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/test/integration/routes-errors.test.ts b/test/integration/routes-errors.test.ts
index 9f0e08e1b7..3cfe12e8ea 100644
--- a/test/integration/routes-errors.test.ts
+++ b/test/integration/routes-errors.test.ts
@@ -1172,13 +1172,12 @@ describe("api route guards and error branches", () => {
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/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();
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 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/queue.test.ts b/test/unit/queue.test.ts
index 0df1406fe7..ba7e9176d6 100644
--- a/test/unit/queue.test.ts
+++ b/test/unit/queue.test.ts
@@ -16885,7 +16885,6 @@ describe("queue processors", () => {
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/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/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): 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();
- }
- });
-});
diff --git a/test/unit/settings-preview.test.ts b/test/unit/settings-preview.test.ts
index 03cccc58fd..bbb0997970 100644
--- a/test/unit/settings-preview.test.ts
+++ b/test/unit/settings-preview.test.ts
@@ -60,7 +60,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/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,