Skip to content

feat(config): configurable worktree prompt branch policy#66

Open
Magentron wants to merge 2 commits intoMiniCodeMonkey:mainfrom
Magentron:feature/worktree-prompt-config
Open

feat(config): configurable worktree prompt branch policy#66
Magentron wants to merge 2 commits intoMiniCodeMonkey:mainfrom
Magentron:feature/worktree-prompt-config

Conversation

@Magentron
Copy link
Copy Markdown

Summary

Replaces the hardcoded "is this main or master?" check that decides whether to prompt the user about creating a git worktree. Two new fields under worktree: in
.chief/config.yaml:

  • worktree.alwaysPrompt (bool, default false) — when true, Chief always shows the worktree prompt before starting a loop, regardless of branch name.
  • worktree.promptBranchPattern (string, default "^(main|master)$") — RE2 regex matched against the current branch. When it matches, Chief prompts. Empty string
    disables matching. Ignored when alwaysPrompt is true. Invalid regex causes a clean startup failure naming the offending field.

Defaults preserve the prior behaviour. Existing config files without the new keys inherit the default pattern on load — the protected-branch safety isn't silently dropped on
upgrade. An explicit promptBranchPattern: "" is the documented opt-out.

Both fields are also editable in the Settings TUI (,). The regex field validates inline: invalid input is rejected with invalid regex: … shown under the editor, the
previous value is preserved, and the editor stays open for correction. Save validates the same way, so a bad regex never makes it to disk.

Internal cleanup carried with this change

  • Removed the exported git.IsProtectedBranch in favour of an unexported isDefaultBranchName used only inside the git package for diff-base detection. The TUI call site now
    consults Config.ShouldPromptForWorktree(branch).
  • Renamed DialogProtectedBranchDialogWorktreePrompt (internal). Dialog title generalised to "⚠️ Worktree Recommended" so it stays accurate when the trigger is a regex
    match or alwaysPrompt: true on a non-default branch.
  • NewAppWithOptions now returns errors for invalid config (was os.Exit) and reliably releases the fsnotify watcher on early-return paths. prd.Watcher.Stop and
    prd.ProgressWatcher.Stop now release the underlying fsnotify watcher even when Start was never called, and are idempotent across repeated calls.
  • Save validates before writing, so future code paths can't persist a malformed pattern.
  • config.ValidateBranchPattern is the single source of truth for the regex rule (used by both Load/Save and the Settings TUI).
  • Documentation updated with the new keys, examples (regex pattern, alwaysPrompt), an RE2 syntax note, and the markdown-escape clarification for the default ^(main\|master)$
    cell.

Test plan

  • go test ./... passes (internal/config ≥ 90% coverage on the new code)
  • On a fresh project (no .chief/config.yaml), starting a loop on main shows the worktree prompt; on feature/x it does not (default-behaviour preserved)
  • On a project with a legacy .chief/config.yaml containing only worktree.setup: "...", starting a loop on main still shows the worktree prompt (no silent regression on
    upgrade)
  • With promptBranchPattern: "^release/.*$" configured, release/v1 triggers the prompt and main does not
  • With alwaysPrompt: true configured, every branch (including feature/x) shows the prompt; the dialog title reads "Worktree Recommended" without claiming the branch is
    "protected"
  • With an explicitly empty promptBranchPattern: "", no branch triggers the prompt unless alwaysPrompt: true
  • Hand-editing .chief/config.yaml with a malformed regex (e.g. "[unclosed") fails Chief startup with a clear error naming worktree.promptBranchPattern
  • In the Settings TUI: editing Prompt branch pattern to "[bad" shows invalid regex: … inline, editor stays open, original value preserved; editing to "^release/.*$"
    saves and exits the editor
  • In the Settings TUI: toggling Always prompt for worktree persists to .chief/config.yaml

Magentron and others added 2 commits April 29, 2026 20:22
Replace the hardcoded main/master check that decided whether to
prompt the user about creating a worktree with two new config fields
under .chief/config.yaml:

- worktree.alwaysPrompt: bool — when true, always prompt regardless
  of branch name.
- worktree.promptBranchPattern: string (regex) — pattern matched
  against the current branch; when it matches, Chief prompts.

Defaults preserve the prior behavior (pattern: ^(main|master)$);
existing config files inherit the default on load. Invalid regex
fails fast at startup with a field-named error. Save also validates
so future write paths can't persist a broken pattern.

Internal cleanup carried with this change:

- Remove exported git.IsProtectedBranch in favor of a private
  isDefaultBranchName for the diff-base helper inside the git
  package; the TUI call site now consults the new policy method.
- Rename DialogProtectedBranch to DialogWorktreePrompt; dialog
  title generalized so it stays accurate when triggered by regex
  match or alwaysPrompt on non-default branches.
- NewAppWithOptions returns errors for invalid config (was
  os.Exit) and reliably releases the fsnotify watcher on early
  return.
- prd.Watcher.Stop and prd.ProgressWatcher.Stop now release the
  underlying fsnotify watcher even when Start was never called,
  and are idempotent across repeated calls.
- Octal literals normalized to the dominant legacy style
  (0755 / 0644) for repo-wide consistency.
- Documentation updated with the new keys, examples, RE2 note,
  Markdown-escape clarification, and accurate Settings TUI scope.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add worktree.alwaysPrompt and worktree.promptBranchPattern to
the Settings TUI overlay so users can edit them without leaving
the app:

- LoadFromConfig surfaces 5 items (was 3); the new worktree
  fields appear under the existing Worktree section.
- ApplyToConfig copies both new keys back to Config.
- ConfirmEdit now returns an error and validates regex input
  inline. On invalid pattern, the editor stays open with an
  inline "invalid regex: …" message; the previous value is
  preserved. Empty pattern is accepted (matches the documented
  opt-out semantics).
- Editor app handler skips Save when ConfirmEdit returns an
  error, keeping the user in edit mode.

DRY: extract config.ValidateBranchPattern as the single source
of truth for the regex rule, used by both compilePromptRegex
(load/save path) and ConfirmEdit (inline TUI validation).
Includes a direct unit test covering empty / valid / invalid
inputs so the contract is locked in.

Docs updated: removed the "not yet exposed in the in-app
Settings TUI" caveat and listed the two new editable items
under the Worktree section.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant