diff --git a/src/review/maintainer-recap-wire.ts b/src/review/maintainer-recap-wire.ts index 6ad9096b4c..96e09daaac 100644 --- a/src/review/maintainer-recap-wire.ts +++ b/src/review/maintainer-recap-wire.ts @@ -96,10 +96,12 @@ export function shouldFireMaintainerRecap( } /** The repos this recap scans. Mirrors ops-wire.ts's opsScanRepos / pr-reconciliation.ts's watchedRepos: prefer - * agent-configured repos when any opted in (the acting-autonomy surface), else fall back to every registered - * repo so the digest still reports before the agent is enabled anywhere. */ + * agent-configured repos when any opted in (the acting-autonomy surface), else fall back to every installed + * repo so the digest still reports before the agent is enabled anywhere. The maintainer recap digest reports + * on PR/issue backlog and review activity for repos the agent runs on -- core review-ops, unrelated to + * gittensor-subnet registry membership, so `isInstalled` (#5016), not `isRegistered`. */ async function recapScanRepos(env: Env): Promise { - const repos = (await listRepositories(env)).filter((repo) => repo.isRegistered); + const repos = (await listRepositories(env)).filter((repo) => repo.isInstalled); const configured: string[] = []; for (const repo of repos) { try { diff --git a/src/review/ops-wire.ts b/src/review/ops-wire.ts index 5db38f87a0..40ab66331c 100644 --- a/src/review/ops-wire.ts +++ b/src/review/ops-wire.ts @@ -172,12 +172,15 @@ export function worstAnomaly(anomalies: string[]): { line: string; severity: Pag // ── Cron alerts: scan gittensory's outcome data, emit a structured log on drift (flag-gated by the caller) ── -/** The registered repos to scan. Scoped to REGISTERED repos (the ones gittensory actually tracks outcomes - * for) — same `isRegistered` filter the other scheduled fan-outs use. */ +/** The installed repos to scan. Mirrors fanOutAgentRegateSweepJobs's own repo population (#5016): outcome + * telemetry (gate precision, slop calibration, review-burst detection) is core review-quality monitoring for + * any repo the review agent actually runs on, unrelated to gittensor-subnet registry membership -- NOT + * `isRegistered`, which this used to (wrongly) match, despite this doc comment's own inner installationId + * guard below already assuming installation, not registration, is what matters. */ async function opsScanRepos(env: Env): Promise { - const repos = (await listRepositories(env)).filter((repo) => repo.isRegistered); + const repos = (await listRepositories(env)).filter((repo) => repo.isInstalled); // Prefer agent-configured repos when any opted in (the acting-autonomy surface, like the regate sweep); fall - // back to every registered repo so outcome telemetry is still scanned before the agent is enabled anywhere. + // back to every installed repo so outcome telemetry is still scanned before the agent is enabled anywhere. const configured: string[] = []; for (const repo of repos) { try { diff --git a/src/review/selftune-wire.ts b/src/review/selftune-wire.ts index 3aeafb942d..18474e1567 100644 --- a/src/review/selftune-wire.ts +++ b/src/review/selftune-wire.ts @@ -99,8 +99,10 @@ async function buildEvalRow(env: Env, repoFullName: string): Promise { - const repos = (await listRepositories(env)).filter((repo) => repo.isRegistered); + const repos = (await listRepositories(env)).filter((repo) => repo.isInstalled); const configured: string[] = []; for (const repo of repos) { try { diff --git a/test/unit/maintainer-recap-wire.test.ts b/test/unit/maintainer-recap-wire.test.ts index 79426f6e5b..bc444203bd 100644 --- a/test/unit/maintainer-recap-wire.test.ts +++ b/test/unit/maintainer-recap-wire.test.ts @@ -192,6 +192,32 @@ describe("runMaintainerRecapJob — cross-repo digest (#1963, #2248)", () => { expect(posted).toHaveLength(1); }); + it("#5016: includes an installed-but-not-subnet-registered repo in the digest (PR/issue backlog reporting is core review-ops, not subnet-gated)", async () => { + const env = createTestEnv({ DISCORD_WEBHOOK_URL: HOOK }); + await env.DB.prepare("INSERT INTO repositories (full_name, owner, name, is_installed, is_registered) VALUES (?, ?, ?, 1, 0)") + .bind("acme/installed-not-registered", "acme", "installed-not-registered") + .run(); + await seedMergedPr(env, "acme/installed-not-registered", 1); + stubDiscordFetch(); + + const { report } = ranRecap(await runMaintainerRecapJob(env)); + + expect(report.repos.map((r) => r.repoFullName)).toContain("acme/installed-not-registered"); + }); + + it("#5016: excludes a subnet-registered-but-not-installed repo from the digest", async () => { + const env = createTestEnv({ DISCORD_WEBHOOK_URL: HOOK }); + await env.DB.prepare("INSERT INTO repositories (full_name, owner, name, is_installed, is_registered) VALUES (?, ?, ?, 0, 1)") + .bind("acme/registered-not-installed", "acme", "registered-not-installed") + .run(); + await seedMergedPr(env, "acme/registered-not-installed", 1); + stubDiscordFetch(); + + const { report } = ranRecap(await runMaintainerRecapJob(env)); + + expect(report.repos.map((r) => r.repoFullName)).not.toContain("acme/registered-not-installed"); + }); + it("keeps miner cohort diagnostics out of the scheduled external recap", async () => { const env = createTestEnv({ DISCORD_WEBHOOK_URL: HOOK }); await seedRegisteredRepo(env, "owner/alpha"); diff --git a/test/unit/ops-wire.test.ts b/test/unit/ops-wire.test.ts index c67add3abb..53522d60ef 100644 --- a/test/unit/ops-wire.test.ts +++ b/test/unit/ops-wire.test.ts @@ -291,6 +291,30 @@ describe("runOpsAlerts — cron path over gittensory's outcome data", () => { expect(found["owner/no-install"]).toBeUndefined(); }); + it("#5016: scans an installed-but-not-subnet-registered repo (outcome monitoring is core review-ops, not subnet-gated)", async () => { + const env = createTestEnv(); + await env.DB.prepare("INSERT INTO repositories (full_name, owner, name, is_installed, is_registered) VALUES (?, ?, ?, 1, 0)") + .bind("acme/installed-not-registered", "acme", "installed-not-registered") + .run(); + await seedGateFalsePositiveAnomaly(env, "acme/installed-not-registered"); + + const found = await runOpsAlerts(env); + + expect(found["acme/installed-not-registered"]?.some((a) => /gate false-positive spike/.test(a))).toBe(true); + }); + + it("#5016: excludes a subnet-registered-but-not-installed repo from the ops scan", async () => { + const env = createTestEnv(); + await env.DB.prepare("INSERT INTO repositories (full_name, owner, name, is_installed, is_registered) VALUES (?, ?, ?, 0, 1)") + .bind("acme/registered-not-installed", "acme", "registered-not-installed") + .run(); + await seedGateFalsePositiveAnomaly(env, "acme/registered-not-installed"); + + const found = await runOpsAlerts(env); + + expect(found["acme/registered-not-installed"]).toBeUndefined(); + }); + it("detects and reports a review burst end-to-end (a PR published far more review surfaces than normal in the window)", async () => { setSelfHostedMetricsMode(true); // keep the repo label so the counter assertion can target the exact series const env = createTestEnv(); diff --git a/test/unit/selftune-wiring.test.ts b/test/unit/selftune-wiring.test.ts index 0e120ddab4..20379f8efc 100644 --- a/test/unit/selftune-wiring.test.ts +++ b/test/unit/selftune-wiring.test.ts @@ -301,6 +301,40 @@ describe("selfTuneRepos — per-repo review.selftune FORCE-OFF (#4104)", () => { expect(await loadShadowOverride(env as never, `${owner}/${name}`)).toBeNull(); }); + it("#5016: tunes an installed-but-not-subnet-registered repo (gate self-calibration is core review-ops, not subnet-gated)", async () => { + const owner = "acme"; + const name = "installed-not-registered"; + const env = createTestEnv({ LOOPOVER_REVIEW_SELFTUNE: "true" }); + await env.DB.prepare("INSERT INTO repositories (full_name, owner, name, is_installed, is_registered, installation_id) VALUES (?, ?, ?, 1, 0, ?)") + .bind(`${owner}/${name}`, owner, name, 9601) + .run(); + await env.DB.prepare("INSERT INTO repository_settings (repo_full_name, autonomy_json) VALUES (?, ?)") + .bind(`${owner}/${name}`, ACTING_AUTONOMY) + .run(); + await seedRecommendationOutcomes(env, `${owner}/${name}`, 5, 10); + + await runSelfTune(env); + + expect((await loadShadowOverride(env as never, `${owner}/${name}`))?.override.confidenceFloor).toBeGreaterThan(0); + }); + + it("#5016: excludes a subnet-registered-but-not-installed repo from the tuning pass", async () => { + const owner = "acme"; + const name = "registered-not-installed"; + const env = createTestEnv({ LOOPOVER_REVIEW_SELFTUNE: "true" }); + await env.DB.prepare("INSERT INTO repositories (full_name, owner, name, is_installed, is_registered, installation_id) VALUES (?, ?, ?, 0, 1, ?)") + .bind(`${owner}/${name}`, owner, name, 9602) + .run(); + await env.DB.prepare("INSERT INTO repository_settings (repo_full_name, autonomy_json) VALUES (?, ?)") + .bind(`${owner}/${name}`, ACTING_AUTONOMY) + .run(); + await seedRecommendationOutcomes(env, `${owner}/${name}`, 5, 10); + + await runSelfTune(env); + + expect(await loadShadowOverride(env as never, `${owner}/${name}`)).toBeNull(); + }); + it("unset review.selftune (the default) does not change today's behavior — an agent-configured repo still tunes normally", async () => { const env = createTestEnv({ LOOPOVER_REVIEW_SELFTUNE: "true" }); await seedRegisteredRepo(env, "owner/repo", ACTING_AUTONOMY);