diff --git a/apps/loopover-ui/src/lib/selfhost-env-reference.ts b/apps/loopover-ui/src/lib/selfhost-env-reference.ts index dd6b6992a..d41d76c84 100644 --- a/apps/loopover-ui/src/lib/selfhost-env-reference.ts +++ b/apps/loopover-ui/src/lib/selfhost-env-reference.ts @@ -5,6 +5,10 @@ export type SelfHostEnvReferenceRow = { }; export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [ + { + name: "ADMIN_GITHUB_LOGINS", + firstReference: "src/queue/processors.ts", + }, { name: "AI_ADVISORY", firstReference: "src/selfhost/ai.ts", @@ -21,10 +25,18 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [ name: "AI_ADVISORY_MODEL", firstReference: "src/server.ts", }, + { + name: "AI_BYOK_DAILY_REPO_LIMIT", + firstReference: "src/services/ai-review.ts", + }, { name: "AI_COMBINE", firstReference: "src/selfhost/ai.ts", }, + { + name: "AI_DAILY_NEURON_BUDGET", + firstReference: "src/services/ai-review.ts", + }, { name: "AI_DUAL_REVIEW", firstReference: "src/selfhost/ai.ts", @@ -41,6 +53,14 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [ name: "AI_EMBED_MODEL", firstReference: "src/selfhost/ai.ts", }, + { + name: "AI_GATEWAY_ID", + firstReference: "src/services/ai-review.ts", + }, + { + name: "AI_MAX_OUTPUT_TOKENS", + firstReference: "src/services/ai-review.ts", + }, { name: "AI_ON_MERGE", firstReference: "src/selfhost/ai.ts", @@ -49,6 +69,22 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [ name: "AI_PROVIDER", firstReference: "src/selfhost/ai-config.ts", }, + { + name: "AI_PUBLIC_COMMENTS_ENABLED", + firstReference: "src/services/ai-review.ts", + }, + { + name: "AI_REVIEW_PLAN", + firstReference: "src/services/ai-review.ts", + }, + { + name: "AI_SUMMARIES_ENABLED", + firstReference: "src/services/ai-review.ts", + }, + { + name: "AI_VISION", + firstReference: "src/queue/processors.ts", + }, { name: "AI_VISION_API_KEY", firstReference: "src/server.ts", @@ -133,6 +169,14 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [ name: "CONFIG_DIR_EMPTY_ACKNOWLEDGED", firstReference: "src/server.ts", }, + { + name: "CONTRIBUTOR_CAP_CANCEL_CI_DEFAULT", + firstReference: "src/queue/processors.ts", + }, + { + name: "CONTRIBUTOR_EVIDENCE_BATCH_SIZE", + firstReference: "src/queue/processors.ts", + }, { name: "CRON_INTERVAL_MS", firstReference: "src/server.ts", @@ -177,6 +221,10 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [ name: "GITHUB_APP_PRIVATE_KEY", firstReference: "src/selfhost/orb-collector.ts", }, + { + name: "GITHUB_APP_SLUG", + firstReference: "src/queue/processors.ts", + }, { name: "GITHUB_CACHE_TTL_SECONDS", firstReference: "src/server.ts", @@ -193,6 +241,10 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [ name: "GITHUB_INSTALLATION_CONCURRENCY_LIMIT", firstReference: "src/selfhost/installation-concurrency-admission.ts", }, + { + name: "GITHUB_PUBLIC_TOKEN", + firstReference: "src/queue/ai-review-orchestration.ts", + }, { name: "HOME", firstReference: "src/selfhost/ai.ts", @@ -209,6 +261,10 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [ name: "LOOPOVER_REPO_CONFIG_DIR", firstReference: "src/server.ts", }, + { + name: "LOOPOVER_REVIEW_CONTINUOUS", + firstReference: "src/queue/processors.ts", + }, { name: "LOOPOVER_VERSION", firstReference: "src/selfhost/otel.ts", @@ -486,17 +542,26 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [ export const SELFHOST_ENV_REFERENCE_MARKDOWN = [ "| Name | First reference |", "| --- | --- |", + "| `ADMIN_GITHUB_LOGINS` | `src/queue/processors.ts` |", "| `AI_ADVISORY` | `src/selfhost/ai.ts` |", "| `AI_ADVISORY_API_KEY` | `src/server.ts` |", "| `AI_ADVISORY_BASE_URL` | `src/server.ts` |", "| `AI_ADVISORY_MODEL` | `src/server.ts` |", + "| `AI_BYOK_DAILY_REPO_LIMIT` | `src/services/ai-review.ts` |", "| `AI_COMBINE` | `src/selfhost/ai.ts` |", + "| `AI_DAILY_NEURON_BUDGET` | `src/services/ai-review.ts` |", "| `AI_DUAL_REVIEW` | `src/selfhost/ai.ts` |", "| `AI_EMBED_API_KEY` | `src/server.ts` |", "| `AI_EMBED_BASE_URL` | `src/server.ts` |", "| `AI_EMBED_MODEL` | `src/selfhost/ai.ts` |", + "| `AI_GATEWAY_ID` | `src/services/ai-review.ts` |", + "| `AI_MAX_OUTPUT_TOKENS` | `src/services/ai-review.ts` |", "| `AI_ON_MERGE` | `src/selfhost/ai.ts` |", "| `AI_PROVIDER` | `src/selfhost/ai-config.ts` |", + "| `AI_PUBLIC_COMMENTS_ENABLED` | `src/services/ai-review.ts` |", + "| `AI_REVIEW_PLAN` | `src/services/ai-review.ts` |", + "| `AI_SUMMARIES_ENABLED` | `src/services/ai-review.ts` |", + "| `AI_VISION` | `src/queue/processors.ts` |", "| `AI_VISION_API_KEY` | `src/server.ts` |", "| `AI_VISION_BASE_URL` | `src/server.ts` |", "| `AI_VISION_MODEL` | `src/server.ts` |", @@ -518,6 +583,8 @@ export const SELFHOST_ENV_REFERENCE_MARKDOWN = [ "| `CODEX_AI_TIMEOUT_MS` | `src/selfhost/ai.ts` |", "| `CODEX_HOME` | `src/selfhost/ai.ts` |", "| `CONFIG_DIR_EMPTY_ACKNOWLEDGED` | `src/server.ts` |", + "| `CONTRIBUTOR_CAP_CANCEL_CI_DEFAULT` | `src/queue/processors.ts` |", + "| `CONTRIBUTOR_EVIDENCE_BATCH_SIZE` | `src/queue/processors.ts` |", "| `CRON_INTERVAL_MS` | `src/server.ts` |", "| `DATABASE_PATH` | `src/server.ts` |", "| `DATABASE_URL` | `src/selfhost/preflight.ts` |", @@ -529,14 +596,17 @@ export const SELFHOST_ENV_REFERENCE_MARKDOWN = [ "| `FOREGROUND_LIVENESS_MAX_RELEASE_PER_SWEEP` | `src/selfhost/foreground-liveness.ts` |", "| `GITHUB_APP_ID` | `src/selfhost/orb-collector.ts` |", "| `GITHUB_APP_PRIVATE_KEY` | `src/selfhost/orb-collector.ts` |", + "| `GITHUB_APP_SLUG` | `src/queue/processors.ts` |", "| `GITHUB_CACHE_TTL_SECONDS` | `src/server.ts` |", "| `GITHUB_INSTALLATION_CONCURRENCY_DEFER_MS` | `src/selfhost/installation-concurrency-admission.ts` |", "| `GITHUB_INSTALLATION_CONCURRENCY_ENABLED` | `src/selfhost/installation-concurrency-admission.ts` |", "| `GITHUB_INSTALLATION_CONCURRENCY_LIMIT` | `src/selfhost/installation-concurrency-admission.ts` |", + "| `GITHUB_PUBLIC_TOKEN` | `src/queue/ai-review-orchestration.ts` |", "| `HOME` | `src/selfhost/ai.ts` |", "| `LOOPOVER_ENABLE_PAGERDUTY` | `src/services/notify-pagerduty.ts` |", "| `LOOPOVER_ENABLE_UNSAFE_CODEX_REVIEWER` | `src/selfhost/ai.ts` |", "| `LOOPOVER_REPO_CONFIG_DIR` | `src/server.ts` |", + "| `LOOPOVER_REVIEW_CONTINUOUS` | `src/queue/processors.ts` |", "| `LOOPOVER_VERSION` | `src/selfhost/otel.ts` |", "| `MAINTENANCE_ADMISSION_DEFER_MS` | `src/selfhost/maintenance-admission.ts` |", "| `MAINTENANCE_ADMISSION_DRAIN_AGE_MS` | `src/selfhost/maintenance-admission.ts` |", diff --git a/scripts/gen-selfhost-env-reference.mjs b/scripts/gen-selfhost-env-reference.mjs index b598fb455..7afdc7b9e 100644 --- a/scripts/gen-selfhost-env-reference.mjs +++ b/scripts/gen-selfhost-env-reference.mjs @@ -10,6 +10,12 @@ export const DEFAULT_SOURCE_ROOTS = [ "src/server.ts", "src/services/notify-discord.ts", "src/services/notify-pagerduty.ts", + // The AI review pipeline reads self-host AI_* knobs (AI_SUMMARIES_ENABLED, AI_PUBLIC_COMMENTS_ENABLED, + // AI_MAX_OUTPUT_TOKENS, AI_BYOK_DAILY_REPO_LIMIT) here, not under src/selfhost, so they were absent from the + // generated reference despite being declared self-host vars in env.d.ts (#6993). + "src/services/ai-review.ts", + "src/queue/ai-review-orchestration.ts", + "src/queue/processors.ts", "scripts/build-selfhost.mjs", "scripts/migrate-selfhost-sqlite-to-postgres.ts", "scripts/smoke-observability-traces.mjs", diff --git a/test/unit/selfhost-env-reference-script.test.ts b/test/unit/selfhost-env-reference-script.test.ts index 0bd840c82..47a935844 100644 --- a/test/unit/selfhost-env-reference-script.test.ts +++ b/test/unit/selfhost-env-reference-script.test.ts @@ -161,3 +161,17 @@ describe("gen-selfhost-env-reference (#2081)", () => { expect(readFileSync(outputAbs, "utf8")).toBe(generated); }); }); + +describe("AI review-pipeline self-host env vars (#6993)", () => { + it("scans the AI review source roots so their self-host AI_* vars are collected", () => { + // Against the REAL repo with the default (now-extended) source roots: the four AI review-pipeline knobs are + // read in src/services/ai-review.ts etc., not under src/selfhost, so they only surface once those roots are + // scanned. Before #6993 none of these appeared in the generated reference. + const byName = new Map(collectSelfHostEnvVars({}).map((row) => [row.name, row.firstReference])); + for (const name of ["AI_SUMMARIES_ENABLED", "AI_PUBLIC_COMMENTS_ENABLED", "AI_MAX_OUTPUT_TOKENS", "AI_BYOK_DAILY_REPO_LIMIT"]) { + expect(byName.has(name), name).toBe(true); + } + // AI_MAX_OUTPUT_TOKENS is read only in ai-review.ts, so its first reference proves the new root is the source. + expect(byName.get("AI_MAX_OUTPUT_TOKENS")).toBe("src/services/ai-review.ts"); + }); +});