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:
packages.pin(Record<string, string>) — validated atsrc/config-validation.ts:205, defaulted atsrc/config.ts:39, never consumed by scanner/resolver/writerpullRequest.commitMessageFormat/titleFormat/bodyTemplate— declaredsrc/types.ts:124-128;formatCommitMessage/formatPRTitle/formatPRBodyinsrc/utils/helpers.tsaccept a template argument no caller suppliesreleaseNotes.enabled/maxReleases/includeCompareLinks— onlymaxBodyLength(src/pr/pr-generator.ts:1073) andsanitizeReferences(:1132) are honored; release count is hardcodedslice(0, 3)atpr-generator.ts:682schedule.timezone— declared butsrc/scheduler/scheduler.tshas no timezone handlingpullRequest.teamReviewers— supported inPullRequestOptionsbut never fed from config- CLI
--config <path>—CLIOptions.configexists (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 setbodyTemplate— 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.tstitle/body generation and the commit paths insrc/buddy.ts/src/git/github-provider.ts
Release notes
enabled: falseskipsrelease-notes-fetcherentirely (perf win on large PRs)maxReleasesreplaces the hardcodedslice(0, 3)(pr-generator.ts:682)includeCompareLinks: falseomits 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 atsrc/buddy.ts:458/501/541/608/708) - Register a real global
--config <path>flag; thread intoloadConfig({ configFile })via bunfig's overrides insrc/config.ts
Tasks
- Implement each item above with per-item tests (success/failure/edge)
- Audit pass: grep every
BuddyBotConfigfield and assert a consumer exists — add atest/config-consumers.test.tsmeta-test that fails when a typed option has no reference outside types/validation/defaults - Update
docs/config.mdwith the now-real semantics + token tables
Acceptance criteria
- Every documented config option observably changes behavior (covered by tests)
- Custom
bodyTemplatePRs still rebase/auto-close (manifest preserved) buddy-bot scan --config ./custom.config.tsloads the specified file
Dependencies
- #1368 (manifest) must land before
bodyTemplateis honored