feat(types): add StatusPinned for persistent beads (bd-6v2)

Add pinned status for beads that should stay open indefinitely:
- Add StatusPinned constant and update IsValid()
- Add PinnedIssues count to Statistics struct
- Protect pinned issues from bd close (requires --force)
- Show pinned count in bd stats output

🤖 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-18 21:55:27 -08:00
parent 8fa1eda207
commit f4f51da007
4 changed files with 39 additions and 3 deletions

View File

@@ -272,6 +272,9 @@ var statsCmd = &cobra.Command{
if stats.TombstoneIssues > 0 {
fmt.Printf("Deleted: %d (tombstones)\n", stats.TombstoneIssues)
}
if stats.PinnedIssues > 0 {
fmt.Printf("Pinned: %d\n", stats.PinnedIssues)
}
if stats.AverageLeadTime > 0 {
fmt.Printf("Avg Lead Time: %.1f hours\n", stats.AverageLeadTime)
}
@@ -313,6 +316,9 @@ var statsCmd = &cobra.Command{
if stats.TombstoneIssues > 0 {
fmt.Printf("Deleted: %d (tombstones)\n", stats.TombstoneIssues)
}
if stats.PinnedIssues > 0 {
fmt.Printf("Pinned: %d\n", stats.PinnedIssues)
}
if stats.EpicsEligibleForClosure > 0 {
fmt.Printf("Epics Ready to Close: %s\n", green(fmt.Sprintf("%d", stats.EpicsEligibleForClosure)))
}

View File

@@ -968,6 +968,7 @@ var closeCmd = &cobra.Command{
reason = "Closed"
}
jsonOutput, _ := cmd.Flags().GetBool("json")
force, _ := cmd.Flags().GetBool("force")
ctx := rootCtx
@@ -1001,6 +1002,21 @@ var closeCmd = &cobra.Command{
if daemonClient != nil {
closedIssues := []*types.Issue{}
for _, id := range resolvedIDs {
// Check if issue is pinned (bd-6v2)
if !force {
showArgs := &rpc.ShowArgs{ID: id}
showResp, showErr := daemonClient.Show(showArgs)
if showErr == nil {
var issue types.Issue
if json.Unmarshal(showResp.Data, &issue) == nil {
if issue.Status == types.StatusPinned {
fmt.Fprintf(os.Stderr, "Error: cannot close pinned issue %s (use --force to override)\n", id)
continue
}
}
}
}
closeArgs := &rpc.CloseArgs{
ID: id,
Reason: reason,
@@ -1036,6 +1052,15 @@ var closeCmd = &cobra.Command{
// Direct mode
closedIssues := []*types.Issue{}
for _, id := range resolvedIDs {
// Check if issue is pinned (bd-6v2)
if !force {
issue, _ := store.GetIssue(ctx, id)
if issue != nil && issue.Status == types.StatusPinned {
fmt.Fprintf(os.Stderr, "Error: cannot close pinned issue %s (use --force to override)\n", id)
continue
}
}
if err := store.CloseIssue(ctx, id, reason, actor); err != nil {
fmt.Fprintf(os.Stderr, "Error closing %s: %v\n", id, err)
continue
@@ -1335,5 +1360,6 @@ func init() {
closeCmd.Flags().StringP("reason", "r", "", "Reason for closing")
closeCmd.Flags().Bool("json", false, "Output JSON format")
closeCmd.Flags().BoolP("force", "f", false, "Force close pinned issues")
rootCmd.AddCommand(closeCmd)
}