Merge remote changes
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -9,7 +9,7 @@
|
|||||||
"name": "beads",
|
"name": "beads",
|
||||||
"source": "./",
|
"source": "./",
|
||||||
"description": "AI-supervised issue tracker for coding workflows",
|
"description": "AI-supervised issue tracker for coding workflows",
|
||||||
"version": "0.20.1"
|
"version": "0.21.0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "beads",
|
"name": "beads",
|
||||||
"description": "AI-supervised issue tracker for coding workflows. Manage tasks, discover work, and maintain context with simple CLI commands.",
|
"description": "AI-supervised issue tracker for coding workflows. Manage tasks, discover work, and maintain context with simple CLI commands.",
|
||||||
"version": "0.20.1",
|
"version": "0.21.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Steve Yegge",
|
"name": "Steve Yegge",
|
||||||
"url": "https://github.com/steveyegge"
|
"url": "https://github.com/steveyegge"
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -56,3 +56,4 @@ dist/
|
|||||||
|
|
||||||
# Git worktrees
|
# Git worktrees
|
||||||
.worktrees/
|
.worktrees/
|
||||||
|
.beads/pollution-backup.jsonl
|
||||||
|
|||||||
@@ -1112,14 +1112,36 @@ func createAutoImportFunc(ctx context.Context, store storage.Storage, log daemon
|
|||||||
log.log("Removed stale lock (%s), proceeding", holder)
|
log.log("Removed stale lock (%s), proceeding", holder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull from git
|
// Check JSONL modification time to avoid redundant imports
|
||||||
if err := gitPull(importCtx); err != nil {
|
// (e.g., from self-triggered file watcher events after our own export)
|
||||||
log.log("Pull failed: %v", err)
|
jsonlInfo, err := os.Stat(jsonlPath)
|
||||||
return
|
if err != nil {
|
||||||
}
|
log.log("Failed to stat JSONL: %v", err)
|
||||||
log.log("Pulled from remote")
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Count issues before import
|
// Get database modification time
|
||||||
|
dbPath := filepath.Join(beadsDir, "beads.db")
|
||||||
|
dbInfo, err := os.Stat(dbPath)
|
||||||
|
if err != nil {
|
||||||
|
log.log("Failed to stat database: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if JSONL is older than database (nothing new to import)
|
||||||
|
if !jsonlInfo.ModTime().After(dbInfo.ModTime()) {
|
||||||
|
log.log("Skipping import: JSONL not newer than database")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pull from git
|
||||||
|
if err := gitPull(importCtx); err != nil {
|
||||||
|
log.log("Pull failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.log("Pulled from remote")
|
||||||
|
|
||||||
|
// Count issues before import
|
||||||
beforeCount, err := countDBIssues(importCtx, store)
|
beforeCount, err := countDBIssues(importCtx, store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.log("Failed to count issues before import: %v", err)
|
log.log("Failed to count issues before import: %v", err)
|
||||||
@@ -1470,7 +1492,7 @@ func runDaemonLoop(interval time.Duration, autoCommit, autoPush bool, logPath, p
|
|||||||
// Choose event loop based on BEADS_DAEMON_MODE
|
// Choose event loop based on BEADS_DAEMON_MODE
|
||||||
daemonMode := os.Getenv("BEADS_DAEMON_MODE")
|
daemonMode := os.Getenv("BEADS_DAEMON_MODE")
|
||||||
if daemonMode == "" {
|
if daemonMode == "" {
|
||||||
daemonMode = "poll" // Default to polling for Phase 1
|
daemonMode = "events" // Default to event-driven mode (production-ready as of v0.21.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch daemonMode {
|
switch daemonMode {
|
||||||
|
|||||||
@@ -47,9 +47,13 @@ func runEventDrivenLoop(
|
|||||||
watcher, err := NewFileWatcher(jsonlPath, func() {
|
watcher, err := NewFileWatcher(jsonlPath, func() {
|
||||||
importDebouncer.Trigger()
|
importDebouncer.Trigger()
|
||||||
})
|
})
|
||||||
|
var fallbackTicker *time.Ticker
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.log("WARNING: File watcher unavailable (%v), mutations will trigger export only", err)
|
log.log("WARNING: File watcher unavailable (%v), using 60s polling fallback", err)
|
||||||
watcher = nil
|
watcher = nil
|
||||||
|
// Fallback ticker to check for remote changes when watcher unavailable
|
||||||
|
fallbackTicker = time.NewTicker(60 * time.Second)
|
||||||
|
defer fallbackTicker.Stop()
|
||||||
} else {
|
} else {
|
||||||
watcher.Start(ctx, log)
|
watcher.Start(ctx, log)
|
||||||
defer watcher.Close()
|
defer watcher.Close()
|
||||||
@@ -97,6 +101,16 @@ func runEventDrivenLoop(
|
|||||||
// Periodic health validation (not sync)
|
// Periodic health validation (not sync)
|
||||||
checkDaemonHealth(ctx, store, log)
|
checkDaemonHealth(ctx, store, log)
|
||||||
|
|
||||||
|
case <-func() <-chan time.Time {
|
||||||
|
if fallbackTicker != nil {
|
||||||
|
return fallbackTicker.C
|
||||||
|
}
|
||||||
|
// Never fire if watcher is available
|
||||||
|
return make(chan time.Time)
|
||||||
|
}():
|
||||||
|
log.log("Fallback ticker: checking for remote changes")
|
||||||
|
importDebouncer.Trigger()
|
||||||
|
|
||||||
case sig := <-sigChan:
|
case sig := <-sigChan:
|
||||||
if isReloadSignal(sig) {
|
if isReloadSignal(sig) {
|
||||||
log.log("Received reload signal, ignoring")
|
log.log("Received reload signal, ignoring")
|
||||||
@@ -120,12 +134,15 @@ func runEventDrivenLoop(
|
|||||||
return
|
return
|
||||||
|
|
||||||
case err := <-serverErrChan:
|
case err := <-serverErrChan:
|
||||||
log.log("RPC server failed: %v", err)
|
log.log("RPC server failed: %v", err)
|
||||||
cancel()
|
cancel()
|
||||||
if watcher != nil {
|
if watcher != nil {
|
||||||
watcher.Close()
|
watcher.Close()
|
||||||
}
|
}
|
||||||
return
|
if stopErr := server.Stop(); stopErr != nil {
|
||||||
|
log.log("Error stopping server: %v", stopErr)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,12 +45,20 @@ Example:
|
|||||||
// Get all issues
|
// Get all issues
|
||||||
allIssues, err := store.SearchIssues(ctx, "", types.IssueFilter{})
|
allIssues, err := store.SearchIssues(ctx, "", types.IssueFilter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error fetching issues: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Error fetching issues: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find duplicates
|
// Filter out closed issues - they're done, no point detecting duplicates
|
||||||
duplicateGroups := findDuplicateGroups(allIssues)
|
openIssues := make([]*types.Issue, 0, len(allIssues))
|
||||||
|
for _, issue := range allIssues {
|
||||||
|
if issue.Status != types.StatusClosed {
|
||||||
|
openIssues = append(openIssues, issue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find duplicates (only among open issues)
|
||||||
|
duplicateGroups := findDuplicateGroups(openIssues)
|
||||||
|
|
||||||
if len(duplicateGroups) == 0 {
|
if len(duplicateGroups) == 0 {
|
||||||
if !jsonOutput {
|
if !jsonOutput {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// Version is the current version of bd (overridden by ldflags at build time)
|
// Version is the current version of bd (overridden by ldflags at build time)
|
||||||
Version = "0.20.1"
|
Version = "0.21.0"
|
||||||
// Build can be set via ldflags at compile time
|
// Build can be set via ldflags at compile time
|
||||||
Build = "dev"
|
Build = "dev"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "beads-mcp"
|
name = "beads-mcp"
|
||||||
version = "0.20.2"
|
version = "0.21.0"
|
||||||
description = "MCP server for beads issue tracker."
|
description = "MCP server for beads issue tracker."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ This package provides an MCP (Model Context Protocol) server that exposes
|
|||||||
beads (bd) issue tracker functionality to MCP Clients.
|
beads (bd) issue tracker functionality to MCP Clients.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = "0.20.2"
|
__version__ = "0.21.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user