@miller-tech/uap 1.51.0 → 1.52.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -69,8 +69,43 @@ for pattern in "${EXEMPT_PATTERNS[@]}"; do
69
69
  fi
70
70
  done
71
71
 
72
- # Allow if path is inside a worktree (substring match, handles nested worktrees)
72
+ # Allow if path is inside a worktree (substring match, handles nested worktrees).
73
+ # Before allowing a real source edit, announce it to the SHARED coordination DB
74
+ # and check for a live overlap so independently-launched agents coordinate and
75
+ # never silently clobber the same file. Always fails open.
73
76
  if echo "$ABS_PATH" | grep -q '\.worktrees/'; then
77
+ if [ -f "$HOOK_DIR/coordinate-file.sh" ]; then
78
+ # Shared coordination DB = the MAIN worktree's, so agents running in
79
+ # different .worktrees/ all see each other. git-common-dir resolves the
80
+ # shared .git even from a linked worktree.
81
+ GCD="$(git rev-parse --git-common-dir 2>/dev/null || true)"
82
+ case "$GCD" in
83
+ /*) : ;;
84
+ "") GCD="" ;;
85
+ *) GCD="$PWD/$GCD" ;;
86
+ esac
87
+ if [ -n "$GCD" ]; then
88
+ MAIN_ROOT="$(cd "$(dirname "$GCD")" 2>/dev/null && pwd || echo "$REPO_ROOT")"
89
+ else
90
+ MAIN_ROOT="$REPO_ROOT"
91
+ fi
92
+ COORD_DB="$MAIN_ROOT/agents/data/coordination/coordination.db"
93
+ # Repo-relative path so the same logical file across worktrees collides.
94
+ REL_PATH="${ABS_PATH#"$REPO_ROOT"/}"
95
+ WT_BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
96
+ SESSION_ID="$(printf '%s' "$INPUT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null || true)"
97
+ if [ -n "$SESSION_ID" ]; then
98
+ AGENT_ID="claude-${SESSION_ID}"
99
+ else
100
+ AGENT_ID="${UAP_AGENT_ID:-claude-${WT_BRANCH:-unknown}}"
101
+ fi
102
+ if bash "$HOOK_DIR/coordinate-file.sh" \
103
+ "$COORD_DB" "$AGENT_ID" "${UAP_AGENT_NAME:-agent}" "$WT_BRANCH" "$REL_PATH" "$ABS_PATH"; then
104
+ exit 0
105
+ fi
106
+ # Non-zero from coordinate-file.sh = live-conflict block (reason on stderr).
107
+ exit 2
108
+ fi
74
109
  exit 0
75
110
  fi
76
111
 
@@ -7,7 +7,20 @@ set -euo pipefail
7
7
 
8
8
  PROJECT_DIR="${CLAUDE_PROJECT_DIR:-${FACTORY_PROJECT_DIR:-${CURSOR_PROJECT_DIR:-.}}}"
9
9
  DB_PATH="${PROJECT_DIR}/agents/data/memory/short_term.db"
10
- COORD_DB="${PROJECT_DIR}/agents/data/coordination/coordination.db"
10
+
11
+ # Coordination DB is SHARED across all worktrees (see session-start.sh).
12
+ _GCD="$(git -C "$PROJECT_DIR" rev-parse --git-common-dir 2>/dev/null || true)"
13
+ case "$_GCD" in
14
+ /*) : ;;
15
+ "") _GCD="" ;;
16
+ *) _GCD="$PROJECT_DIR/$_GCD" ;;
17
+ esac
18
+ if [ -n "$_GCD" ]; then
19
+ COORD_ROOT="$(cd "$(dirname "$_GCD")" 2>/dev/null && pwd || echo "$PROJECT_DIR")"
20
+ else
21
+ COORD_ROOT="$PROJECT_DIR"
22
+ fi
23
+ COORD_DB="${COORD_ROOT}/agents/data/coordination/coordination.db"
11
24
  TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
12
25
 
13
26
  # Store session end marker
@@ -18,14 +31,24 @@ if [ -f "$DB_PATH" ]; then
18
31
  " 2>/dev/null || true
19
32
  fi
20
33
 
21
- # Clean up all active agents and work claims
34
+ # Reap STALE coordination state only. The coordination DB is shared across all
35
+ # worktrees, so this hook must NOT mark every agent completed or complete every
36
+ # announcement — that would wipe other LIVE agents' state. Instead, complete the
37
+ # state of agents whose heartbeat has gone stale (>5 min), which covers this
38
+ # ending session (its heartbeat stops) without touching active peers.
39
+ STALE_SECS="${UAP_COORD_REAP_SECONDS:-300}"
22
40
  if [ -f "$COORD_DB" ]; then
23
41
  sqlite3 "$COORD_DB" "
24
- UPDATE work_announcements SET completed_at = '$TIMESTAMP'
25
- WHERE completed_at IS NULL;
26
- DELETE FROM work_claims;
27
42
  UPDATE agent_registry SET status = 'completed'
28
- WHERE status IN ('active', 'idle');
43
+ WHERE status IN ('active', 'idle')
44
+ AND (strftime('%s','now') - strftime('%s', last_heartbeat)) >= $STALE_SECS;
45
+ UPDATE work_announcements SET completed_at = '$TIMESTAMP'
46
+ WHERE completed_at IS NULL
47
+ AND agent_id IN (
48
+ SELECT id FROM agent_registry
49
+ WHERE status = 'completed'
50
+ OR (strftime('%s','now') - strftime('%s', last_heartbeat)) >= $STALE_SECS
51
+ );
29
52
  " 2>/dev/null || true
30
53
  fi
31
54
 
@@ -6,7 +6,23 @@ set -euo pipefail
6
6
 
7
7
  PROJECT_DIR="${CLAUDE_PROJECT_DIR:-${FACTORY_PROJECT_DIR:-${CURSOR_PROJECT_DIR:-.}}}"
8
8
  DB_PATH="${PROJECT_DIR}/agents/data/memory/short_term.db"
9
- COORD_DB="${PROJECT_DIR}/agents/data/coordination/coordination.db"
9
+
10
+ # Coordination DB is SHARED across all worktrees: resolve it to the MAIN
11
+ # worktree (git-common-dir points at the shared .git even from a linked
12
+ # worktree) so agents in different .worktrees/ register into one registry and
13
+ # can see each other's file announcements. Falls back to PROJECT_DIR.
14
+ _GCD="$(git -C "$PROJECT_DIR" rev-parse --git-common-dir 2>/dev/null || true)"
15
+ case "$_GCD" in
16
+ /*) : ;;
17
+ "") _GCD="" ;;
18
+ *) _GCD="$PROJECT_DIR/$_GCD" ;;
19
+ esac
20
+ if [ -n "$_GCD" ]; then
21
+ COORD_ROOT="$(cd "$(dirname "$_GCD")" 2>/dev/null && pwd || echo "$PROJECT_DIR")"
22
+ else
23
+ COORD_ROOT="$PROJECT_DIR"
24
+ fi
25
+ COORD_DB="${COORD_ROOT}/agents/data/coordination/coordination.db"
10
26
 
11
27
  if [ ! -f "$DB_PATH" ]; then
12
28
  exit 0