release: v0.34.0

## Added
- Wisp commands - bd wisp create/list/gc for ephemeral molecule management
- Chemistry UX - bd pour, bd mol bond --wisp/--pour for phase control
- Cross-project deps - external:<repo>:<id> syntax, bd ship command
- Orphan detection in bd doctor

## Changed
- Multi-repo config uses YAML - bd repo add/remove writes to .beads/config.yaml

## Fixed
- Wisp storage auto-copies issue_prefix from main database
- Prefix validation in multi-repo mode
- Remove orphaned repo_test.go
- Update version tests for 0.34.0 thresholds

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-22 03:18:55 -08:00
parent 32181fd5a2
commit 199def9fed
15 changed files with 93 additions and 122 deletions

View File

@@ -895,7 +895,8 @@ func TestCheckMetadataVersionTracking(t *testing.T) {
{
name: "slightly outdated version",
setupVersion: func(beadsDir string) error {
return os.WriteFile(filepath.Join(beadsDir, ".local_version"), []byte("0.24.0\n"), 0644)
// Use a version that's less than 10 minor versions behind current
return os.WriteFile(filepath.Join(beadsDir, ".local_version"), []byte("0.30.0\n"), 0644)
},
expectedStatus: doctor.StatusOK,
expectWarning: false,
@@ -903,7 +904,8 @@ func TestCheckMetadataVersionTracking(t *testing.T) {
{
name: "very old version",
setupVersion: func(beadsDir string) error {
return os.WriteFile(filepath.Join(beadsDir, ".local_version"), []byte("0.14.0\n"), 0644)
// Use a version that's 10+ minor versions behind current (triggers warning)
return os.WriteFile(filepath.Join(beadsDir, ".local_version"), []byte("0.24.0\n"), 0644)
},
expectedStatus: doctor.StatusWarning,
expectWarning: true,

View File

@@ -288,6 +288,17 @@ type VersionChange struct {
// versionChanges contains agent-actionable changes for recent versions
var versionChanges = []VersionChange{
{
Version: "0.34.0",
Date: "2025-12-22",
Changes: []string{
"NEW: Wisp commands - bd wisp create/list/gc for ephemeral molecule management",
"NEW: Chemistry UX - bd pour, bd mol bond --wisp/--pour for phase control",
"NEW: Cross-project deps - external:<repo>:<id> syntax, bd ship command",
"BREAKING: bd repo add/remove now writes to .beads/config.yaml (not DB)",
"FIX: Wisp storage auto-copies issue_prefix from main database",
},
},
{
Version: "0.33.2",
Date: "2025-12-21",

View File

@@ -1,109 +0,0 @@
package main
import (
"context"
"testing"
)
func TestGetRepoConfig_EmptyValue(t *testing.T) {
ctx := context.Background()
store, cleanup := setupTestDB(t)
defer cleanup()
// Test 1: No config set at all - should return empty map
repos, err := getRepoConfig(ctx, store)
if err != nil {
t.Fatalf("getRepoConfig with no config failed: %v", err)
}
if len(repos) != 0 {
t.Errorf("Expected empty map, got %d entries", len(repos))
}
// Test 2: Empty string value - should return empty map (this was the bug)
// This simulates GetConfig returning ("", nil) which caused "unexpected end of JSON input"
err = store.SetConfig(ctx, "repos.additional", "")
if err != nil {
t.Fatalf("SetConfig failed: %v", err)
}
repos, err = getRepoConfig(ctx, store)
if err != nil {
t.Fatalf("getRepoConfig with empty value failed: %v", err)
}
if len(repos) != 0 {
t.Errorf("Expected empty map for empty value, got %d entries", len(repos))
}
// Test 3: Valid JSON value - should parse correctly
err = store.SetConfig(ctx, "repos.additional", `{"alias1":"/path/to/repo1","alias2":"/path/to/repo2"}`)
if err != nil {
t.Fatalf("SetConfig with JSON failed: %v", err)
}
repos, err = getRepoConfig(ctx, store)
if err != nil {
t.Fatalf("getRepoConfig with valid JSON failed: %v", err)
}
if len(repos) != 2 {
t.Errorf("Expected 2 repos, got %d", len(repos))
}
if repos["alias1"] != "/path/to/repo1" {
t.Errorf("Expected '/path/to/repo1', got '%s'", repos["alias1"])
}
if repos["alias2"] != "/path/to/repo2" {
t.Errorf("Expected '/path/to/repo2', got '%s'", repos["alias2"])
}
}
func TestSetRepoConfig(t *testing.T) {
ctx := context.Background()
store, cleanup := setupTestDB(t)
defer cleanup()
// Set repos and verify round-trip
repos := map[string]string{
"planning": "/home/user/planning-repo",
"shared": "/home/user/shared-repo",
}
err := setRepoConfig(ctx, store, repos)
if err != nil {
t.Fatalf("setRepoConfig failed: %v", err)
}
// Read back
result, err := getRepoConfig(ctx, store)
if err != nil {
t.Fatalf("getRepoConfig after set failed: %v", err)
}
if len(result) != 2 {
t.Errorf("Expected 2 repos, got %d", len(result))
}
if result["planning"] != "/home/user/planning-repo" {
t.Errorf("Expected planning repo path, got '%s'", result["planning"])
}
if result["shared"] != "/home/user/shared-repo" {
t.Errorf("Expected shared repo path, got '%s'", result["shared"])
}
}
func TestRepoConfigEmptyMap(t *testing.T) {
ctx := context.Background()
store, cleanup := setupTestDB(t)
defer cleanup()
// Set empty map
repos := make(map[string]string)
err := setRepoConfig(ctx, store, repos)
if err != nil {
t.Fatalf("setRepoConfig with empty map failed: %v", err)
}
// Read back - should work and return empty map
result, err := getRepoConfig(ctx, store)
if err != nil {
t.Fatalf("getRepoConfig after empty set failed: %v", err)
}
if len(result) != 0 {
t.Errorf("Expected empty map, got %d entries", len(result))
}
}

View File

@@ -1,6 +1,6 @@
#!/bin/sh
# bd-shim v1
# bd-hooks-version: 0.33.2
# bd-hooks-version: 0.34.0
#
# bd (beads) post-checkout hook - thin shim
#

View File

@@ -1,6 +1,6 @@
#!/bin/sh
# bd-shim v1
# bd-hooks-version: 0.33.2
# bd-hooks-version: 0.34.0
#
# bd (beads) post-merge hook - thin shim
#

View File

@@ -1,6 +1,6 @@
#!/bin/sh
# bd-shim v1
# bd-hooks-version: 0.33.2
# bd-hooks-version: 0.34.0
#
# bd (beads) pre-commit hook - thin shim
#

View File

@@ -1,6 +1,6 @@
#!/bin/sh
# bd-shim v1
# bd-hooks-version: 0.33.2
# bd-hooks-version: 0.34.0
#
# bd (beads) pre-push hook - thin shim
#

View File

@@ -14,7 +14,7 @@ import (
var (
// Version is the current version of bd (overridden by ldflags at build time)
Version = "0.33.2"
Version = "0.34.0"
// Build can be set via ldflags at compile time
Build = "dev"
// Commit and branch the git revision the binary was built from (optional ldflag)