chore: remove issue ID references from comments and changelogs
Strip (bd-xxx), (gt-xxx) suffixes from code comments and changelog entries. The descriptions remain meaningful without the ephemeral issue IDs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -59,23 +59,23 @@ func formatJSONStringArray(arr []string) string {
|
||||
return string(data)
|
||||
}
|
||||
|
||||
// REMOVED (bd-8e05): getNextIDForPrefix and AllocateNextID - sequential ID generation
|
||||
// REMOVED: getNextIDForPrefix and AllocateNextID - sequential ID generation
|
||||
// no longer needed with hash-based IDs
|
||||
// Migration functions moved to migrations.go (bd-fc2d, bd-b245)
|
||||
// Migration functions moved to migrations.go
|
||||
|
||||
// getNextChildNumber atomically generates the next child number for a parent ID
|
||||
// Uses the child_counters table for atomic, cross-process child ID generation
|
||||
// Hash ID generation functions moved to hash_ids.go (bd-90a5)
|
||||
// Hash ID generation functions moved to hash_ids.go
|
||||
|
||||
// REMOVED (bd-c7af): SyncAllCounters - no longer needed with hash IDs
|
||||
// REMOVED: SyncAllCounters - no longer needed with hash IDs
|
||||
|
||||
// REMOVED (bd-166): derivePrefixFromPath was causing duplicate issues with wrong prefix
|
||||
// REMOVED: derivePrefixFromPath was causing duplicate issues with wrong prefix
|
||||
// The database should ALWAYS have issue_prefix config set explicitly (by 'bd init' or auto-import)
|
||||
// Never derive prefix from filename - it leads to silent data corruption
|
||||
|
||||
// CreateIssue creates a new issue
|
||||
func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, actor string) error {
|
||||
// Fetch custom statuses for validation (bd-1pj6)
|
||||
// Fetch custom statuses for validation
|
||||
customStatuses, err := s.GetCustomStatuses(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get custom statuses: %w", err)
|
||||
@@ -116,7 +116,7 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act
|
||||
return fmt.Errorf("validation failed: %w", err)
|
||||
}
|
||||
|
||||
// Compute content hash (bd-95)
|
||||
// Compute content hash
|
||||
if issue.ContentHash == "" {
|
||||
issue.ContentHash = issue.ComputeContentHash()
|
||||
}
|
||||
@@ -138,7 +138,7 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act
|
||||
// We use raw Exec instead of BeginTx because database/sql doesn't support transaction
|
||||
// modes in BeginTx, and modernc.org/sqlite's BeginTx always uses DEFERRED mode.
|
||||
//
|
||||
// Use retry logic with exponential backoff to handle SQLITE_BUSY under concurrent load (bd-ola6)
|
||||
// Use retry logic with exponential backoff to handle SQLITE_BUSY under concurrent load
|
||||
if err := beginImmediateWithRetry(ctx, conn, 5, 10*time.Millisecond); err != nil {
|
||||
return fmt.Errorf("failed to begin immediate transaction: %w", err)
|
||||
}
|
||||
@@ -156,14 +156,14 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act
|
||||
var configPrefix string
|
||||
err = conn.QueryRowContext(ctx, `SELECT value FROM config WHERE key = ?`, "issue_prefix").Scan(&configPrefix)
|
||||
if err == sql.ErrNoRows || configPrefix == "" {
|
||||
// CRITICAL: Reject operation if issue_prefix config is missing (bd-166)
|
||||
// CRITICAL: Reject operation if issue_prefix config is missing
|
||||
// This prevents duplicate issues with wrong prefix
|
||||
return fmt.Errorf("database not initialized: issue_prefix config is missing (run 'bd init --prefix <prefix>' first)")
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("failed to get config: %w", err)
|
||||
}
|
||||
|
||||
// Use IDPrefix override if set, combined with config prefix (bd-hobo)
|
||||
// Use IDPrefix override if set, combined with config prefix
|
||||
// e.g., configPrefix="bd" + IDPrefix="wisp" → "bd-wisp"
|
||||
prefix := configPrefix
|
||||
if issue.IDPrefix != "" {
|
||||
@@ -172,14 +172,14 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act
|
||||
|
||||
// Generate or validate ID
|
||||
if issue.ID == "" {
|
||||
// Generate hash-based ID with adaptive length based on database size (bd-ea2a13)
|
||||
// Generate hash-based ID with adaptive length based on database size
|
||||
generatedID, err := GenerateIssueID(ctx, conn, prefix, issue, actor)
|
||||
if err != nil {
|
||||
return wrapDBError("generate issue ID", err)
|
||||
}
|
||||
issue.ID = generatedID
|
||||
} else {
|
||||
// Validate that explicitly provided ID matches the configured prefix (bd-177)
|
||||
// Validate that explicitly provided ID matches the configured prefix
|
||||
if err := ValidateIssueIDPrefix(issue.ID, prefix); err != nil {
|
||||
return wrapDBError("validate issue ID prefix", err)
|
||||
}
|
||||
@@ -235,7 +235,7 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act
|
||||
}
|
||||
|
||||
// validateBatchIssues validates all issues in a batch and sets timestamps
|
||||
// Batch operation functions moved to batch_ops.go (bd-c796)
|
||||
// Batch operation functions moved to batch_ops.go
|
||||
|
||||
// GetIssue retrieves an issue by ID
|
||||
func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue, error) {
|
||||
@@ -260,19 +260,19 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue,
|
||||
var deletedBy sql.NullString
|
||||
var deleteReason sql.NullString
|
||||
var originalType sql.NullString
|
||||
// Messaging fields (bd-kwro)
|
||||
// Messaging fields
|
||||
var sender sql.NullString
|
||||
var wisp sql.NullInt64
|
||||
// Pinned field (bd-7h5)
|
||||
// Pinned field
|
||||
var pinned sql.NullInt64
|
||||
// Template field (beads-1ra)
|
||||
// Template field
|
||||
var isTemplate sql.NullInt64
|
||||
// Gate fields (bd-udsi)
|
||||
// Gate fields
|
||||
var awaitType sql.NullString
|
||||
var awaitID sql.NullString
|
||||
var timeoutNs sql.NullInt64
|
||||
var waiters sql.NullString
|
||||
// Agent fields (gt-h5sza)
|
||||
// Agent fields
|
||||
var hookBead sql.NullString
|
||||
var roleBead sql.NullString
|
||||
var agentState sql.NullString
|
||||
@@ -353,22 +353,22 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue,
|
||||
if originalType.Valid {
|
||||
issue.OriginalType = originalType.String
|
||||
}
|
||||
// Messaging fields (bd-kwro)
|
||||
// Messaging fields
|
||||
if sender.Valid {
|
||||
issue.Sender = sender.String
|
||||
}
|
||||
if wisp.Valid && wisp.Int64 != 0 {
|
||||
issue.Ephemeral = true
|
||||
}
|
||||
// Pinned field (bd-7h5)
|
||||
// Pinned field
|
||||
if pinned.Valid && pinned.Int64 != 0 {
|
||||
issue.Pinned = true
|
||||
}
|
||||
// Template field (beads-1ra)
|
||||
// Template field
|
||||
if isTemplate.Valid && isTemplate.Int64 != 0 {
|
||||
issue.IsTemplate = true
|
||||
}
|
||||
// Gate fields (bd-udsi)
|
||||
// Gate fields
|
||||
if awaitType.Valid {
|
||||
issue.AwaitType = awaitType.String
|
||||
}
|
||||
@@ -381,7 +381,7 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue,
|
||||
if waiters.Valid && waiters.String != "" {
|
||||
issue.Waiters = parseJSONStringArray(waiters.String)
|
||||
}
|
||||
// Agent fields (gt-h5sza)
|
||||
// Agent fields
|
||||
if hookBead.Valid {
|
||||
issue.HookBead = hookBead.String
|
||||
}
|
||||
@@ -503,14 +503,14 @@ func (s *SQLiteStorage) GetIssueByExternalRef(ctx context.Context, externalRef s
|
||||
var deletedBy sql.NullString
|
||||
var deleteReason sql.NullString
|
||||
var originalType sql.NullString
|
||||
// Messaging fields (bd-kwro)
|
||||
// Messaging fields
|
||||
var sender sql.NullString
|
||||
var wisp sql.NullInt64
|
||||
// Pinned field (bd-7h5)
|
||||
// Pinned field
|
||||
var pinned sql.NullInt64
|
||||
// Template field (beads-1ra)
|
||||
// Template field
|
||||
var isTemplate sql.NullInt64
|
||||
// Gate fields (bd-udsi)
|
||||
// Gate fields
|
||||
var awaitType sql.NullString
|
||||
var awaitID sql.NullString
|
||||
var timeoutNs sql.NullInt64
|
||||
@@ -585,22 +585,22 @@ func (s *SQLiteStorage) GetIssueByExternalRef(ctx context.Context, externalRef s
|
||||
if originalType.Valid {
|
||||
issue.OriginalType = originalType.String
|
||||
}
|
||||
// Messaging fields (bd-kwro)
|
||||
// Messaging fields
|
||||
if sender.Valid {
|
||||
issue.Sender = sender.String
|
||||
}
|
||||
if wisp.Valid && wisp.Int64 != 0 {
|
||||
issue.Ephemeral = true
|
||||
}
|
||||
// Pinned field (bd-7h5)
|
||||
// Pinned field
|
||||
if pinned.Valid && pinned.Int64 != 0 {
|
||||
issue.Pinned = true
|
||||
}
|
||||
// Template field (beads-1ra)
|
||||
// Template field
|
||||
if isTemplate.Valid && isTemplate.Int64 != 0 {
|
||||
issue.IsTemplate = true
|
||||
}
|
||||
// Gate fields (bd-udsi)
|
||||
// Gate fields
|
||||
if awaitType.Valid {
|
||||
issue.AwaitType = awaitType.String
|
||||
}
|
||||
@@ -638,14 +638,14 @@ var allowedUpdateFields = map[string]bool{
|
||||
"estimated_minutes": true,
|
||||
"external_ref": true,
|
||||
"closed_at": true,
|
||||
// Messaging fields (bd-kwro)
|
||||
// Messaging fields
|
||||
"sender": true,
|
||||
"wisp": true, // Database column is 'ephemeral', mapped in UpdateIssue
|
||||
// Pinned field (bd-7h5)
|
||||
// Pinned field
|
||||
"pinned": true,
|
||||
// NOTE: replies_to, relates_to, duplicate_of, superseded_by removed per Decision 004
|
||||
// Use AddDependency() to create graph edges instead
|
||||
// Agent slot fields (gt-h5sza)
|
||||
// Agent slot fields
|
||||
"hook_bead": true,
|
||||
"role_bead": true,
|
||||
"agent_state": true,
|
||||
@@ -655,7 +655,7 @@ var allowedUpdateFields = map[string]bool{
|
||||
}
|
||||
|
||||
// validatePriority validates a priority value
|
||||
// Validation functions moved to validators.go (bd-d9e0)
|
||||
// Validation functions moved to validators.go
|
||||
|
||||
// determineEventType determines the event type for an update based on old and new status
|
||||
func determineEventType(oldIssue *types.Issue, updates map[string]interface{}) types.EventType {
|
||||
@@ -734,7 +734,7 @@ func (s *SQLiteStorage) UpdateIssue(ctx context.Context, id string, updates map[
|
||||
return fmt.Errorf("issue %s not found", id)
|
||||
}
|
||||
|
||||
// Fetch custom statuses for validation (bd-1pj6)
|
||||
// Fetch custom statuses for validation
|
||||
customStatuses, err := s.GetCustomStatuses(ctx)
|
||||
if err != nil {
|
||||
return wrapDBError("get custom statuses", err)
|
||||
@@ -767,7 +767,7 @@ func (s *SQLiteStorage) UpdateIssue(ctx context.Context, id string, updates map[
|
||||
// Auto-manage closed_at when status changes (enforce invariant)
|
||||
setClauses, args = manageClosedAt(oldIssue, updates, setClauses, args)
|
||||
|
||||
// Recompute content_hash if any content fields changed (bd-95)
|
||||
// Recompute content_hash if any content fields changed
|
||||
contentChanged := false
|
||||
contentFields := []string{"title", "description", "design", "acceptance_criteria", "notes", "status", "priority", "issue_type", "assignee", "external_ref"}
|
||||
for _, field := range contentFields {
|
||||
@@ -886,7 +886,7 @@ func (s *SQLiteStorage) UpdateIssue(ctx context.Context, id string, updates map[
|
||||
return fmt.Errorf("failed to mark issue dirty: %w", err)
|
||||
}
|
||||
|
||||
// Invalidate blocked issues cache if status changed (bd-5qim)
|
||||
// Invalidate blocked issues cache if status changed
|
||||
// Status changes affect which issues are blocked (blockers must be open/in_progress/blocked)
|
||||
if _, statusChanged := updates["status"]; statusChanged {
|
||||
if err := s.invalidateBlockedCache(ctx, tx); err != nil {
|
||||
@@ -1023,14 +1023,14 @@ func (s *SQLiteStorage) RenameDependencyPrefix(ctx context.Context, oldPrefix, n
|
||||
return nil
|
||||
}
|
||||
|
||||
// RenameCounterPrefix is a no-op with hash-based IDs (bd-8e05)
|
||||
// RenameCounterPrefix is a no-op with hash-based IDs
|
||||
// Kept for backward compatibility with rename-prefix command
|
||||
func (s *SQLiteStorage) RenameCounterPrefix(ctx context.Context, oldPrefix, newPrefix string) error {
|
||||
// Hash-based IDs don't use counters, so nothing to update
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetCounter is a no-op with hash-based IDs (bd-8e05)
|
||||
// ResetCounter is a no-op with hash-based IDs
|
||||
// Kept for backward compatibility
|
||||
func (s *SQLiteStorage) ResetCounter(ctx context.Context, prefix string) error {
|
||||
// Hash-based IDs don't use counters, so nothing to reset
|
||||
@@ -1086,7 +1086,7 @@ func (s *SQLiteStorage) CloseIssue(ctx context.Context, id string, reason string
|
||||
return fmt.Errorf("failed to mark issue dirty: %w", err)
|
||||
}
|
||||
|
||||
// Invalidate blocked issues cache since status changed to closed (bd-5qim)
|
||||
// Invalidate blocked issues cache since status changed to closed
|
||||
// Closed issues don't block others, so this affects blocking calculations
|
||||
if err := s.invalidateBlockedCache(ctx, tx); err != nil {
|
||||
return fmt.Errorf("failed to invalidate blocked cache: %w", err)
|
||||
@@ -1155,7 +1155,7 @@ func (s *SQLiteStorage) CreateTombstone(ctx context.Context, id string, actor st
|
||||
return fmt.Errorf("failed to mark issue dirty: %w", err)
|
||||
}
|
||||
|
||||
// Invalidate blocked issues cache since status changed (bd-5qim)
|
||||
// Invalidate blocked issues cache since status changed
|
||||
// Tombstone issues don't block others, so this affects blocking calculations
|
||||
if err := s.invalidateBlockedCache(ctx, tx); err != nil {
|
||||
return fmt.Errorf("failed to invalidate blocked cache: %w", err)
|
||||
@@ -1188,7 +1188,7 @@ func (s *SQLiteStorage) DeleteIssue(ctx context.Context, id string) error {
|
||||
return fmt.Errorf("failed to delete events: %w", err)
|
||||
}
|
||||
|
||||
// Delete comments (no FK cascade on this table) (bd-687g)
|
||||
// Delete comments (no FK cascade on this table)
|
||||
_, err = tx.ExecContext(ctx, `DELETE FROM comments WHERE issue_id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete comments: %w", err)
|
||||
@@ -1218,7 +1218,7 @@ func (s *SQLiteStorage) DeleteIssue(ctx context.Context, id string) error {
|
||||
return wrapDBError("commit delete transaction", err)
|
||||
}
|
||||
|
||||
// REMOVED (bd-c7af): Counter sync after deletion - no longer needed with hash IDs
|
||||
// REMOVED: Counter sync after deletion - no longer needed with hash IDs
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1272,7 +1272,7 @@ func (s *SQLiteStorage) DeleteIssues(ctx context.Context, ids []string, cascade
|
||||
return nil, fmt.Errorf("failed to commit transaction: %w", err)
|
||||
}
|
||||
|
||||
// REMOVED (bd-c7af): Counter sync after deletion - no longer needed with hash IDs
|
||||
// REMOVED: Counter sync after deletion - no longer needed with hash IDs
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@@ -1424,7 +1424,7 @@ func (s *SQLiteStorage) populateDeleteStats(ctx context.Context, tx *sql.Tx, inC
|
||||
}
|
||||
|
||||
func (s *SQLiteStorage) executeDelete(ctx context.Context, tx *sql.Tx, inClause string, args []interface{}, result *DeleteIssuesResult) error {
|
||||
// Note: This method now creates tombstones instead of hard-deleting (bd-3b4)
|
||||
// Note: This method now creates tombstones instead of hard-deleting
|
||||
// Only dependencies are deleted - issues are converted to tombstones
|
||||
|
||||
// 1. Delete dependencies - tombstones don't block other issues
|
||||
@@ -1500,7 +1500,7 @@ func (s *SQLiteStorage) executeDelete(ctx context.Context, tx *sql.Tx, inClause
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Invalidate blocked issues cache since statuses changed (bd-5qim)
|
||||
// 4. Invalidate blocked issues cache since statuses changed
|
||||
if err := s.invalidateBlockedCache(ctx, tx); err != nil {
|
||||
return fmt.Errorf("failed to invalidate blocked cache: %w", err)
|
||||
}
|
||||
@@ -1591,7 +1591,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t
|
||||
whereClauses = append(whereClauses, "status = ?")
|
||||
args = append(args, *filter.Status)
|
||||
} else if !filter.IncludeTombstones {
|
||||
// Exclude tombstones by default unless explicitly filtering for them (bd-1bu)
|
||||
// Exclude tombstones by default unless explicitly filtering for them
|
||||
whereClauses = append(whereClauses, "status != ?")
|
||||
args = append(args, types.StatusTombstone)
|
||||
}
|
||||
@@ -1686,7 +1686,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t
|
||||
whereClauses = append(whereClauses, fmt.Sprintf("id IN (%s)", strings.Join(placeholders, ", ")))
|
||||
}
|
||||
|
||||
// Wisp filtering (bd-kwro.9)
|
||||
// Wisp filtering
|
||||
if filter.Ephemeral != nil {
|
||||
if *filter.Ephemeral {
|
||||
whereClauses = append(whereClauses, "ephemeral = 1") // SQL column is still 'ephemeral'
|
||||
@@ -1695,7 +1695,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t
|
||||
}
|
||||
}
|
||||
|
||||
// Pinned filtering (bd-7h5)
|
||||
// Pinned filtering
|
||||
if filter.Pinned != nil {
|
||||
if *filter.Pinned {
|
||||
whereClauses = append(whereClauses, "pinned = 1")
|
||||
@@ -1704,7 +1704,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t
|
||||
}
|
||||
}
|
||||
|
||||
// Template filtering (beads-1ra)
|
||||
// Template filtering
|
||||
if filter.IsTemplate != nil {
|
||||
if *filter.IsTemplate {
|
||||
whereClauses = append(whereClauses, "is_template = 1")
|
||||
@@ -1713,7 +1713,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t
|
||||
}
|
||||
}
|
||||
|
||||
// Parent filtering (bd-yqhh): filter children by parent issue
|
||||
// Parent filtering: filter children by parent issue
|
||||
if filter.ParentID != nil {
|
||||
whereClauses = append(whereClauses, "id IN (SELECT issue_id FROM dependencies WHERE type = 'parent-child' AND depends_on_id = ?)")
|
||||
args = append(args, *filter.ParentID)
|
||||
|
||||
Reference in New Issue
Block a user