Skip to content

fix(core): respect worktree.baseBranch in cleanup service#1424

Closed
truffle-dev wants to merge 1 commit intocoleam00:devfrom
truffle-dev:fix/cleanup-respect-baseBranch-config
Closed

fix(core): respect worktree.baseBranch in cleanup service#1424
truffle-dev wants to merge 1 commit intocoleam00:devfrom
truffle-dev:fix/cleanup-respect-baseBranch-config

Conversation

@truffle-dev
Copy link
Copy Markdown
Contributor

@truffle-dev truffle-dev commented Apr 26, 2026

Closes #1419.

Bug

On startup, the cleanup service throws repeated env_cleanup_error for every tracked environment whose repo has a non-main default branch and no origin/HEAD (e.g. repos using master). The error message itself tells users to set worktree.baseBranch in .archon/config.yaml — but the cleanup service never reads that config, so the suggestion is a dead end.

{"level":50,"module":"cleanup","err":{"message":"Cannot detect default branch for /home/user/myrepo: neither origin/HEAD nor origin/main exist. Set worktree.baseBranch in .archon/config.yaml to specify the branch explicitly."},"msg":"env_cleanup_error"}

Root cause

packages/core/src/services/cleanup-service.ts calls getDefaultBranch(repoPath) directly at three call sites without first consulting loadRepoConfig:

  • runScheduledCleanup — runs on every startup tick, source of the reported log spam
  • getWorktreeStatusBreakdown — same auto-detect path used by status displays
  • cleanupMergedWorktrees — same path used when cleaning merged worktrees

The same pattern is already implemented correctly in packages/git/src/repo.ts:syncWorkspace, where the caller passes a baseBranch parameter and falls back to auto-detection only when omitted.

Fix

Add a small resolveBaseBranch helper that reads loadRepoConfig first and only falls back to getDefaultBranch when the config has no value (or only whitespace):

async function resolveBaseBranch(repoPath: RepoPath): Promise<BranchName> {
  const repoConfig = await loadRepoConfig(repoPath);
  const configured = repoConfig?.worktree?.baseBranch?.trim();
  if (configured) {
    return toBranchName(configured);
  }
  return await getDefaultBranch(repoPath);
}

All three call sites swap getDefaultBranch(repoPath)resolveBaseBranch(repoPath). The reporter only flagged the first site; sweeping all three keeps the behavior consistent across the cleanup surface.

Tests

Five new tests in packages/core/src/services/cleanup-service.test.ts:

  1. runScheduledCleanup uses worktree.baseBranch from repo config and skips git auto-detection
  2. runScheduledCleanup falls back to getDefaultBranch when repo config has no baseBranch
  3. runScheduledCleanup treats whitespace-only baseBranch as unset and falls back
  4. getWorktreeStatusBreakdown uses worktree.baseBranch for merge detection
  5. cleanupMergedWorktrees uses worktree.baseBranch when comparing merge state

Existing 42 tests in the file continue to pass.

bun test src/services/cleanup-service.test.ts
 47 pass
 0 fail
 98 expect() calls

Verification

  • bun run typecheck — clean across all 10 packages
  • bunx prettier --check on both files — clean
  • bunx eslint on cleanup-service.ts — clean (0 errors, 0 warnings)
  • Branch based on upstream/dev per CONTRIBUTING.md

Summary by CodeRabbit

  • New Features

    • Worktree cleanup operations now respect an optional base branch configuration setting from your project configuration file. Users can specify a custom comparison branch for cleanup operations instead of always defaulting to the repository's default branch, providing greater control over branch comparison logic.
  • Tests

    • Expanded test coverage for cleanup service behavior with both configured base branch settings and default branch fallback scenarios.

The cleanup service called getDefaultBranch directly at three sites
without first consulting `worktree.baseBranch` from `.archon/config.yaml`.
On repos where the default branch is `master` and `origin/HEAD` is unset,
git auto-detection throws and produces repeated `env_cleanup_error` logs
on every startup — even though the error message tells users to set
`worktree.baseBranch`, which the cleanup service silently ignored.

Add a small `resolveBaseBranch` helper that reads `loadRepoConfig` first
and only falls back to `getDefaultBranch` when the config has no value
(or only whitespace). Sweep all three call sites:

- runScheduledCleanup (line 327)
- getWorktreeStatusBreakdown (line 481)
- cleanupMergedWorktrees (line 609)

The same pattern already exists in `packages/git/src/repo.ts:syncWorkspace`,
where the caller passes a `baseBranch` parameter and falls back to
auto-detection only when omitted.

Five regression tests cover: config-respect at all three sites, fallback
when config is empty, and the whitespace-only edge case.

Closes coleam00#1419
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 26, 2026

📝 Walkthrough

Walkthrough

The PR adds config-aware base branch resolution to the cleanup service. A new resolveBaseBranch helper reads worktree.baseBranch from repo config, using that value when present and non-empty, otherwise falling back to git auto-detection. This fixes a bug where the documented config field was silently ignored.

Changes

Cohort / File(s) Summary
Cleanup Service Implementation
packages/core/src/services/cleanup-service.ts
Introduces resolveBaseBranch helper that loads repo config and prefers worktree.baseBranch from .archon/config.yaml over getDefaultBranch, replacing direct branch detection calls in scheduled cleanup and worktree status breakdown logic.
Cleanup Service Tests
packages/core/src/services/cleanup-service.test.ts
Adds comprehensive test coverage for config-driven branch resolution: mocks config-loader, verifies worktree.baseBranch is used when present, confirms getDefaultBranch is suppressed, and validates fallback behavior when config is absent or empty.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A config once lost, now found at last,
The baseBranch secret—no longer passed!
No more shall master hide in shame,
For .archon/config will stake its claim.
Clean worktrees sing, errors gone away,
Archon reads config, hip-hop-hooray! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(core): respect worktree.baseBranch in cleanup service' accurately summarizes the main change: enabling the cleanup service to read and use the worktree.baseBranch config value.
Description check ✅ Passed The PR description comprehensively covers the bug, root cause, fix implementation, tests added, and verification steps, meeting the template requirements for Summary, Architecture context, and Validation Evidence.
Linked Issues check ✅ Passed The PR fully addresses issue #1419 by implementing the resolveBaseBranch helper that reads loadRepoConfig and falls back to getDefaultBranch, updating all three affected call sites (runScheduledCleanup, getWorktreeStatusBreakdown, cleanupMergedWorktrees) and adding five comprehensive tests.
Out of Scope Changes check ✅ Passed All changes are scoped to the cleanup service implementation and tests; no out-of-scope modifications to unrelated modules or unnecessary refactoring detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/core/src/services/cleanup-service.ts (1)

27-42: The code is functionally correct; consider adding a comment explaining why the PR 1423 decision was reversed.

The switch to loadRepoConfig is safe and properly mitigated by the test mock setup in cleanup-service.test.ts (lines 99–100), which short-circuits the @archon/providers dependency chain before importing the cleanup service. The RepoConfig interface correctly includes worktree?.baseBranch?: string, and no test failures are evident.

However, PR 1423 deliberately avoided loadRepoConfig for this exact reason. Since that decision has been reversed, a brief comment in resolveBaseBranch (e.g., "We now use loadRepoConfig because test mocks handle the @archon/providers chain") would clarify intent for future maintainers and prevent accidental reversion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/cleanup-service.ts` around lines 27 - 42, Add a
brief explanatory comment above resolveBaseBranch saying we intentionally use
loadRepoConfig (reversing the prior PR 1423 decision) because test mocks
short-circuit the `@archon/providers` dependency chain and RepoConfig includes
worktree.baseBranch; mention that this prevents noisy git auto-detection and
that getDefaultBranch remains the fallback. Reference the function name
resolveBaseBranch, the loader loadRepoConfig, and the fallback getDefaultBranch
in the comment so future maintainers understand the reasoning.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/core/src/services/cleanup-service.ts`:
- Around line 27-42: Add a brief explanatory comment above resolveBaseBranch
saying we intentionally use loadRepoConfig (reversing the prior PR 1423
decision) because test mocks short-circuit the `@archon/providers` dependency
chain and RepoConfig includes worktree.baseBranch; mention that this prevents
noisy git auto-detection and that getDefaultBranch remains the fallback.
Reference the function name resolveBaseBranch, the loader loadRepoConfig, and
the fallback getDefaultBranch in the comment so future maintainers understand
the reasoning.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4816ad59-cd1a-4260-bcb7-fb6f5bf2ba11

📥 Commits

Reviewing files that changed from the base of the PR and between 9122673 and 9c1c37b.

📒 Files selected for processing (2)
  • packages/core/src/services/cleanup-service.test.ts
  • packages/core/src/services/cleanup-service.ts

@truffle-dev
Copy link
Copy Markdown
Contributor Author

Closing this. I missed that @kagura-agent opened #1423 at 09:08Z with the same approach (resolveMainBranch helper, 3 call sites swept) two hours before I opened this one. Sorry for the duplicate — should have re-checked open PRs before pushing rather than relying on a stale scout note.

If you end up wanting any of the extras here once #1423 lands, the differences are:

Happy to drop those as a follow-up PR after #1423 merges if useful, or open a comment on #1423 with the whitespace nit.

@truffle-dev truffle-dev deleted the fix/cleanup-respect-baseBranch-config branch April 26, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

worktree.baseBranch in .archon/config.yaml is documented but never read — causes repeated env_cleanup_error on startup

1 participant