fix(routing): disable auto-routing by default (#1177)

Change routing.mode default from "auto" to "" (empty/disabled).

This fixes GH#1165 where fresh `bd init --prefix X` followed by
`bd create` would unexpectedly route to ~/.beads-planning and fail
with "database not initialized: issue_prefix config is missing".

Auto-routing now requires explicit opt-in via:
- `bd init --contributor` flag, OR
- `bd config set routing.mode auto`

Includes test verifying the default and doc updates clarifying
the opt-in requirement.
This commit is contained in:
Peter Chanthamynavong
2026-01-20 14:05:07 -08:00
committed by GitHub
parent 9ed74ca233
commit 228d78c180
4 changed files with 35 additions and 3 deletions

View File

@@ -126,7 +126,7 @@ accordingly:
2. **Routing Configuration** (`internal/config/config.go`):
```go
v.SetDefault("routing.mode", "auto")
v.SetDefault("routing.mode", "") // Empty = disabled by default
v.SetDefault("routing.default", ".")
v.SetDefault("routing.contributor", "~/.beads-planning")
```

View File

@@ -45,7 +45,10 @@ bd create "Fix bug" -p 1
Routing is configured via the database config:
```bash
# Set routing mode (auto = detect role, explicit = always use default)
# Auto-routing is disabled by default (routing.mode="")
# Enable with:
bd init --contributor
# OR manually:
bd config set routing.mode auto
# Set default planning repo

View File

@@ -112,7 +112,7 @@ func Initialize() error {
v.SetDefault("remote-sync-interval", "30s")
// Routing configuration defaults
v.SetDefault("routing.mode", "auto")
v.SetDefault("routing.mode", "")
v.SetDefault("routing.default", ".")
v.SetDefault("routing.maintainer", ".")
v.SetDefault("routing.contributor", "~/.beads-planning")

View File

@@ -941,6 +941,35 @@ external_projects:
})
}
func TestRoutingModeDefaultIsEmpty(t *testing.T) {
// GH#1165: routing.mode must default to empty (disabled)
// to prevent unexpected auto-routing to ~/.beads-planning
// Isolate from environment variables
restore := envSnapshot(t)
defer restore()
// Initialize config
if err := Initialize(); err != nil {
t.Fatalf("Initialize() returned error: %v", err)
}
// Verify routing.mode defaults to empty string (disabled)
if got := GetString("routing.mode"); got != "" {
t.Errorf("GetString(routing.mode) = %q, want \"\" (empty = disabled by default)", got)
}
// Verify other routing defaults are still set correctly
if got := GetString("routing.default"); got != "." {
t.Errorf("GetString(routing.default) = %q, want \".\"", got)
}
if got := GetString("routing.maintainer"); got != "." {
t.Errorf("GetString(routing.maintainer) = %q, want \".\"", got)
}
if got := GetString("routing.contributor"); got != "~/.beads-planning" {
t.Errorf("GetString(routing.contributor) = %q, want \"~/.beads-planning\"", got)
}
}
func TestValidationConfigDefaults(t *testing.T) {
// Isolate from environment variables
restore := envSnapshot(t)