diff --git a/docs/setup.md b/docs/setup.md index 128bf5e..05f2a85 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -76,7 +76,7 @@ Fill in: - `triager`: the GitHub login that owns author-side steps of Dependabot and outside-contributor PRs. They must also be in `users`, or nobody gets tagged for those PRs. - `repos`: every tracked repo, `owner/name`. - `enabled`: leave `false` until the [production cutover](#production-cutover-checklist). - - Optional tuning (defaults in `src/features/pr_management/config.ts`): `reminders` (thresholds and message templates), `drafts` (nudge and report ages), `report` (time and time zone, default 09:30 `America/New_York`), `botAuthors`, `wipTitlePattern`. + - Optional tuning (defaults in `src/features/pr_management/config.ts`): `reminders` (thresholds and message templates), `drafts` (nudge and report ages), `report` (`enabled`, time and time zone, default on at 09:30 `America/New_York`), `botAuthors`, `wipTitlePattern`. - `environments.staging`: `dryRun: true` and `testChannel` (a channel such as `#nathan-test`). In dry run everything Nathan would post, in any channel or DM, goes to the test channel instead. Staging's overlay can enable `pr_management` on its own (`environments.staging.features.pr_management.enabled: true`), so it can be tested while production stays off. diff --git a/nathan.config.ts b/nathan.config.ts index 7a9ad77..65c94d0 100644 --- a/nathan.config.ts +++ b/nathan.config.ts @@ -25,6 +25,8 @@ export default defineConfig({ repos: ["Kiln-AI/Kiln", "Kiln-AI/kiln_server"], channel: "C0996APVD9R", // #prs triager: "chiang-daniel", + // Daily report to #prs is off; `/nathan pr_report` still DMs it on demand. + report: { enabled: false }, }, }, diff --git a/src/features/pr_management/config.ts b/src/features/pr_management/config.ts index 56c115d..8d9bafa 100644 --- a/src/features/pr_management/config.ts +++ b/src/features/pr_management/config.ts @@ -78,6 +78,8 @@ const draftsSchema = z.strictObject({ }); const reportSchema = z.strictObject({ + /** Whether the daily report is posted to the PR channel. `/nathan pr_report` works either way. */ + enabled: z.boolean().default(true), /** Local time (24h "HH:MM") the daily report is posted on weekdays. */ at: z .string() diff --git a/src/features/pr_management/index.ts b/src/features/pr_management/index.ts index 94eeedb..f05ec90 100644 --- a/src/features/pr_management/index.ts +++ b/src/features/pr_management/index.ts @@ -43,11 +43,13 @@ export const prManagement = defineFeature({ for (const event of GITHUB_EVENTS) registrar.github.on(event, onWebhook); registrar.schedule({ name: "sweep", when: { everyHour: true }, run: () => sweep(ctx) }); - registrar.schedule({ - name: "daily_report", - when: reportSchedule(config.report), - run: ({ firedAt }) => postDailyReport(ctx, firedAt), - }); + if (config.report.enabled) { + registrar.schedule({ + name: "daily_report", + when: reportSchedule(config.report), + run: ({ firedAt }) => postDailyReport(ctx, firedAt), + }); + } registerRequestPR(registrar, ctx); registerPersonalQueue(registrar, ctx); diff --git a/test/features/pr_management/config.test.ts b/test/features/pr_management/config.test.ts index 3dee168..2081d56 100644 --- a/test/features/pr_management/config.test.ts +++ b/test/features/pr_management/config.test.ts @@ -28,7 +28,7 @@ describe("pr_management config", () => { templates: DEFAULT_REMINDER_TEMPLATES, }, drafts: { nudgeAfterDays: 14, nudgeEveryDays: 7, reportAfterDays: 30 }, - report: { at: "09:30", timezone: "America/New_York" }, + report: { enabled: true, at: "09:30", timezone: "America/New_York" }, }); }); diff --git a/test/features/pr_management/report.test.ts b/test/features/pr_management/report.test.ts index c3b3988..6f79f41 100644 --- a/test/features/pr_management/report.test.ts +++ b/test/features/pr_management/report.test.ts @@ -386,6 +386,14 @@ describe("the daily report task", () => { ]); }); + it("posts nothing when the report is disabled", async () => { + const h = prApp({ config: prConfig({ report: { enabled: false } }) }); + h.github.upsert(aPR({ pendingReviewers: ["bob"] })); + + await tickAt(h, "2026-10-09T13:30:00Z"); + expect(reports(h)).toEqual([]); + }); + it("covers the time since the last report and shows the change in open PRs", async () => { const h = prApp(); h.github.upsert(aPR({ number: 1, createdAt: at("2026-10-08T10:00:00Z") }));