ReviewOS

stacks/buddy

Honor dead config options (packages.pin, PR templates, releaseNotes, timezone, --config)

#1371
Closed chris opened this 9 days ago ·
9 days ago

Part of #1367 (Phase 0 — Foundation).

Problem

Several BuddyBotConfig options are typed, validated, defaulted, and documented — but never read by any code path. Config that silently does nothing erodes trust and breaks the epic's "no dead config" principle:

  1. packages.pin (Record<string, string>) — validated at src/config-validation.ts:205, defaulted at src/config.ts:39, never consumed by scanner/resolver/writer
  2. pullRequest.commitMessageFormat / titleFormat / bodyTemplate — declared src/types.ts:124-128; formatCommitMessage/formatPRTitle/formatPRBody in src/utils/helpers.ts accept a template argument no caller supplies
  3. releaseNotes.enabled / maxReleases / includeCompareLinks — only maxBodyLength (src/pr/pr-generator.ts:1073) and sanitizeReferences (:1132) are honored; release count is hardcoded slice(0, 3) at pr-generator.ts:682
  4. schedule.timezone — declared but src/scheduler/scheduler.ts has no timezone handling
  5. pullRequest.teamReviewers — supported in PullRequestOptions but never fed from config
  6. CLI --config <path> — CLIOptions.config exists (bin/cli.ts:100) but is never registered or used

Spec

packages.pin

Pinned packages are held at the pinned version/range: the scanner must (a) skip proposing updates beyond the pin, and (b) propose a downgrade-to-pin PR if the manifest drifts above the pin. Apply in Buddy.scanForUpdates (src/buddy.ts:75) after registry results, alongside ignore filtering. Document interplay with ignore (pin wins) and groups.

PR templates

  • titleFormat — tokens: {title} (generated default), {count}, {group}, {strategy}, {ecosystem}
  • commitMessageFormat — tokens: {message}, plus same set
  • bodyTemplate — tokens: {updates_table}, {release_notes}, {manifest}, {footer}, {package_count}; must always append the metadata manifest from #1368 regardless of template (non-negotiable, otherwise rebase/auto-close break)
  • Wire through src/pr/pr-generator.ts title/body generation and the commit paths in src/buddy.ts / src/git/github-provider.ts

Release notes

  • enabled: false skips release-notes-fetcher entirely (perf win on large PRs)
  • maxReleases replaces the hardcoded slice(0, 3) (pr-generator.ts:682)
  • includeCompareLinks: false omits compare URLs

Scheduler timezone

Apply schedule.timezone in src/scheduler/scheduler.ts cron evaluation (compute next-run in the target TZ via Intl.DateTimeFormat/Temporal-style offset math — no new deps if avoidable). Also surface it into generated workflow cron comments (GitHub cron is UTC-only; document the conversion).

teamReviewers + --config

  • Add pullRequest.teamReviewers?: string[] end-to-end (config → validation → PR creation calls at src/buddy.ts:458/501/541/608/708)
  • Register a real global --config <path> flag; thread into loadConfig({ configFile }) via bunfig's overrides in src/config.ts

Tasks

  • Implement each item above with per-item tests (success/failure/edge)
  • Audit pass: grep every BuddyBotConfig field and assert a consumer exists — add a test/config-consumers.test.ts meta-test that fails when a typed option has no reference outside types/validation/defaults
  • Update docs/config.md with the now-real semantics + token tables

Acceptance criteria

  • Every documented config option observably changes behavior (covered by tests)
  • Custom bodyTemplate PRs still rebase/auto-close (manifest preserved)
  • buddy-bot scan --config ./custom.config.ts loads the specified file

Dependencies

  • #1368 (manifest) must land before bodyTemplate is honored

Sign in to comment on this issue.