agent-relay-server 0.25.0 → 0.27.0

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.
@@ -14,12 +14,13 @@
14
14
  // "handed off, healthy, wait" guidance, and `actionNeeded:false` is the explicit
15
15
  // anti-panic signal.
16
16
 
17
+ import { TERMINAL_WORKSPACE_STATUS_VALUES } from "agent-relay-sdk";
17
18
  import type { WorkspaceRecord, WorkspaceStatus } from "./types";
18
19
 
19
20
  // Statuses where the worktree's lifecycle is over — landed or torn down. Single
20
21
  // home; imported by maintenance (stale reap), routes (orphan scan), and the MCP
21
22
  // initialize primer (don't brief an agent on a dead workspace). Was duplicated.
22
- export const TERMINAL_WORKSPACE_STATUSES = new Set<WorkspaceStatus>(["cleaned", "merged", "abandoned"]);
23
+ export const TERMINAL_WORKSPACE_STATUSES = new Set<WorkspaceStatus>(TERMINAL_WORKSPACE_STATUS_VALUES);
23
24
 
24
25
  // The "handed off, waiting to land" statuses — an agent has finished and the
25
26
  // auto-merge-back is responsible for getting the branch onto base. SINGLE HOME:
@@ -33,6 +34,35 @@ export const TERMINAL_WORKSPACE_STATUSES = new Set<WorkspaceStatus>(["cleaned",
33
34
  // it's also where a failed auto-merge lands for a retry, see routes.ts.)
34
35
  export const READY_TO_LAND_STATUSES = new Set<WorkspaceStatus>(["ready", "review_requested"]);
35
36
 
37
+ // Land-state shape a host reports for a worktree (subset of WorkspaceMergePreview
38
+ // / WorkspaceGitState — the fields that decide reapability). Kept structural so
39
+ // both the merge-preview path and a raw git-state probe satisfy it.
40
+ export interface WorktreeReapState {
41
+ /** Work already in base (squash/cherry/PR-merged). Detection only under-reports. */
42
+ landed?: boolean;
43
+ /** Commits ahead of base by raw count (a squash-landed branch still shows >0). */
44
+ ahead?: number;
45
+ /** Commits ahead whose patch is NOT already in base — the squash-aware count. */
46
+ unmergedAhead?: number;
47
+ /** Uncommitted working-tree changes. */
48
+ dirtyCount?: number;
49
+ }
50
+
51
+ // THE reap-safety invariant (#244): a worktree may be removed only when nothing
52
+ // would be lost — clean tree AND (no commits ahead OR the work already landed).
53
+ // SINGLE HOME: the orphan reaper, the orphan-reclaim gate, and the host's
54
+ // exit-time `reconcileWorkspace` "empty" check all mean the same thing; they
55
+ // drifted into three private copies and a land-blind force-remove slipped
56
+ // through (the recovered NUL-guard test was one keystroke from deletion).
57
+ // Mirror `reconcileWorkspace`: landing detection can only under-report, so an
58
+ // uncertain worktree is NEVER reapable — it gets flagged for review instead.
59
+ export function worktreeReapable(state: WorktreeReapState | null | undefined): boolean {
60
+ if (!state) return false;
61
+ if ((state.dirtyCount ?? 0) > 0) return false;
62
+ if (state.landed === true) return true;
63
+ return (state.unmergedAhead ?? state.ahead ?? 0) === 0;
64
+ }
65
+
36
66
  // How long a workspace may sit in a ready-to-land status before the directive
37
67
  // projection stops saying "healthy, just wait" and surfaces it as needs-attention
38
68
  // (#242 watchdog). A clean auto-merge runs ~every 2 min, so a handful of missed