@proletariat/cli 0.3.95 → 0.3.97

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.
Files changed (260) hide show
  1. package/dist/commands/config/index.js +1 -1
  2. package/dist/commands/config/index.js.map +1 -1
  3. package/dist/commands/db/repair.js +160 -35
  4. package/dist/commands/db/repair.js.map +1 -1
  5. package/dist/commands/gc.d.ts +14 -0
  6. package/dist/commands/gc.js +208 -0
  7. package/dist/commands/gc.js.map +1 -0
  8. package/dist/commands/linear/connect.d.ts +5 -0
  9. package/dist/commands/linear/connect.js +84 -0
  10. package/dist/commands/linear/connect.js.map +1 -1
  11. package/dist/commands/pr/merge.js +1 -1
  12. package/dist/commands/pr/merge.js.map +1 -1
  13. package/dist/commands/session/attach.d.ts +3 -3
  14. package/dist/commands/session/attach.js +37 -79
  15. package/dist/commands/session/attach.js.map +1 -1
  16. package/dist/commands/session/exec.js +1 -1
  17. package/dist/commands/session/exec.js.map +1 -1
  18. package/dist/commands/session/health.js +1 -1
  19. package/dist/commands/session/health.js.map +1 -1
  20. package/dist/commands/session/inspect.js +1 -1
  21. package/dist/commands/session/inspect.js.map +1 -1
  22. package/dist/commands/session/list.d.ts +1 -0
  23. package/dist/commands/session/list.js +111 -78
  24. package/dist/commands/session/list.js.map +1 -1
  25. package/dist/commands/session/peek.js +1 -1
  26. package/dist/commands/session/peek.js.map +1 -1
  27. package/dist/commands/session/poke.js +1 -1
  28. package/dist/commands/session/poke.js.map +1 -1
  29. package/dist/commands/session/prune.js +50 -11
  30. package/dist/commands/session/prune.js.map +1 -1
  31. package/dist/commands/session/restart.js +1 -1
  32. package/dist/commands/session/restart.js.map +1 -1
  33. package/dist/commands/session/watch.d.ts +1 -0
  34. package/dist/commands/session/watch.js +46 -2
  35. package/dist/commands/session/watch.js.map +1 -1
  36. package/dist/commands/{action → sync}/index.d.ts +2 -6
  37. package/dist/commands/sync/index.js +68 -0
  38. package/dist/commands/sync/index.js.map +1 -0
  39. package/dist/commands/sync/pause.d.ts +10 -0
  40. package/dist/commands/sync/pause.js +35 -0
  41. package/dist/commands/sync/pause.js.map +1 -0
  42. package/dist/commands/sync/queue.d.ts +10 -0
  43. package/dist/commands/sync/queue.js +106 -0
  44. package/dist/commands/sync/queue.js.map +1 -0
  45. package/dist/commands/sync/resume.d.ts +10 -0
  46. package/dist/commands/sync/resume.js +34 -0
  47. package/dist/commands/sync/resume.js.map +1 -0
  48. package/dist/commands/sync/start.d.ts +11 -0
  49. package/dist/commands/sync/start.js +73 -0
  50. package/dist/commands/sync/start.js.map +1 -0
  51. package/dist/commands/sync/status.d.ts +10 -0
  52. package/dist/commands/sync/status.js +40 -0
  53. package/dist/commands/sync/status.js.map +1 -0
  54. package/dist/commands/sync/stop.d.ts +10 -0
  55. package/dist/commands/sync/stop.js +39 -0
  56. package/dist/commands/sync/stop.js.map +1 -0
  57. package/dist/commands/ticket/create.js +1 -1
  58. package/dist/commands/ticket/create.js.map +1 -1
  59. package/dist/commands/ticket/edit.js +1 -1
  60. package/dist/commands/ticket/edit.js.map +1 -1
  61. package/dist/commands/ticket/list.js +1 -1
  62. package/dist/commands/ticket/list.js.map +1 -1
  63. package/dist/commands/ticket/update.js +1 -1
  64. package/dist/commands/ticket/update.js.map +1 -1
  65. package/dist/commands/work/complete.d.ts +1 -0
  66. package/dist/commands/work/complete.js +27 -25
  67. package/dist/commands/work/complete.js.map +1 -1
  68. package/dist/commands/work/drop.d.ts +14 -0
  69. package/dist/commands/work/drop.js +215 -0
  70. package/dist/commands/work/drop.js.map +1 -0
  71. package/dist/commands/work/ready.d.ts +1 -0
  72. package/dist/commands/work/ready.js +26 -25
  73. package/dist/commands/work/ready.js.map +1 -1
  74. package/dist/commands/work/resolve.js +1 -1
  75. package/dist/commands/work/resolve.js.map +1 -1
  76. package/dist/commands/work/ship.d.ts +1 -0
  77. package/dist/commands/work/ship.js +33 -32
  78. package/dist/commands/work/ship.js.map +1 -1
  79. package/dist/commands/work/start.d.ts +2 -0
  80. package/dist/commands/work/start.js +172 -125
  81. package/dist/commands/work/start.js.map +1 -1
  82. package/dist/commands/work/stop.d.ts +1 -0
  83. package/dist/commands/work/stop.js +40 -0
  84. package/dist/commands/work/stop.js.map +1 -1
  85. package/dist/lib/agents/commands.js +7 -5
  86. package/dist/lib/agents/commands.js.map +1 -1
  87. package/dist/lib/dashboard/data.js +1 -1
  88. package/dist/lib/dashboard/data.js.map +1 -1
  89. package/dist/lib/database/db-safety.d.ts +22 -0
  90. package/dist/lib/database/db-safety.js +91 -4
  91. package/dist/lib/database/db-safety.js.map +1 -1
  92. package/dist/lib/database/drizzle-schema.d.ts +17 -0
  93. package/dist/lib/database/drizzle-schema.js +1 -0
  94. package/dist/lib/database/drizzle-schema.js.map +1 -1
  95. package/dist/lib/database/index.d.ts +1 -1
  96. package/dist/lib/database/index.js +1 -1
  97. package/dist/lib/database/index.js.map +1 -1
  98. package/dist/lib/database/migrations/0017_drop_agent_work_fk.d.ts +13 -0
  99. package/dist/lib/database/migrations/0017_drop_agent_work_fk.js +85 -0
  100. package/dist/lib/database/migrations/0017_drop_agent_work_fk.js.map +1 -0
  101. package/dist/lib/database/migrations/0018_create_ticket_refs.d.ts +11 -0
  102. package/dist/lib/database/migrations/0018_create_ticket_refs.js +40 -0
  103. package/dist/lib/database/migrations/0018_create_ticket_refs.js.map +1 -0
  104. package/dist/lib/database/migrations/0019_gc_artifact_cleanup.d.ts +9 -0
  105. package/dist/lib/database/migrations/0019_gc_artifact_cleanup.js +23 -0
  106. package/dist/lib/database/migrations/0019_gc_artifact_cleanup.js.map +1 -0
  107. package/dist/lib/database/migrations/0020_transition_map.d.ts +2 -0
  108. package/dist/lib/database/migrations/0020_transition_map.js +27 -0
  109. package/dist/lib/database/migrations/0020_transition_map.js.map +1 -0
  110. package/dist/lib/database/migrations/index.js +8 -0
  111. package/dist/lib/database/migrations/index.js.map +1 -1
  112. package/dist/lib/execution/config.d.ts +10 -0
  113. package/dist/lib/execution/config.js +24 -0
  114. package/dist/lib/execution/config.js.map +1 -1
  115. package/dist/lib/execution/devcontainer.js +1 -1
  116. package/dist/lib/execution/devcontainer.js.map +1 -1
  117. package/dist/lib/execution/preflight.d.ts +51 -0
  118. package/dist/lib/execution/preflight.js +278 -0
  119. package/dist/lib/execution/preflight.js.map +1 -0
  120. package/dist/lib/execution/runners/docker-management.d.ts +9 -0
  121. package/dist/lib/execution/runners/docker-management.js +14 -3
  122. package/dist/lib/execution/runners/docker-management.js.map +1 -1
  123. package/dist/lib/execution/runners/prompt-builder.d.ts +6 -0
  124. package/dist/lib/execution/runners/prompt-builder.js +53 -10
  125. package/dist/lib/execution/runners/prompt-builder.js.map +1 -1
  126. package/dist/lib/execution/runners/shared.d.ts +1 -1
  127. package/dist/lib/execution/runners/shared.js +1 -1
  128. package/dist/lib/execution/runners/shared.js.map +1 -1
  129. package/dist/lib/execution/session-utils.d.ts +39 -0
  130. package/dist/lib/execution/session-utils.js +111 -0
  131. package/dist/lib/execution/session-utils.js.map +1 -1
  132. package/dist/lib/execution/spawner.d.ts +11 -1
  133. package/dist/lib/execution/spawner.js +46 -17
  134. package/dist/lib/execution/spawner.js.map +1 -1
  135. package/dist/lib/execution/storage.js +2 -1
  136. package/dist/lib/execution/storage.js.map +1 -1
  137. package/dist/lib/execution/ticket-refs.d.ts +71 -0
  138. package/dist/lib/execution/ticket-refs.js +125 -0
  139. package/dist/lib/execution/ticket-refs.js.map +1 -0
  140. package/dist/lib/execution/types.d.ts +7 -2
  141. package/dist/lib/execution/types.js +5 -3
  142. package/dist/lib/execution/types.js.map +1 -1
  143. package/dist/lib/external-issues/utils.d.ts +25 -0
  144. package/dist/lib/external-issues/utils.js +32 -0
  145. package/dist/lib/external-issues/utils.js.map +1 -0
  146. package/dist/lib/gc/index.d.ts +179 -0
  147. package/dist/lib/gc/index.js +655 -0
  148. package/dist/lib/gc/index.js.map +1 -0
  149. package/dist/lib/mcp/tools/action.js +1 -1
  150. package/dist/lib/mcp/tools/action.js.map +1 -1
  151. package/dist/lib/mcp/tools/ticket.js +1 -1
  152. package/dist/lib/mcp/tools/ticket.js.map +1 -1
  153. package/dist/lib/orchestrate/actions.js +30 -0
  154. package/dist/lib/orchestrate/actions.js.map +1 -1
  155. package/dist/lib/orchestrate/poller.js +3 -3
  156. package/dist/lib/orchestrate/poller.js.map +1 -1
  157. package/dist/lib/orchestrate/presets.js +2 -1
  158. package/dist/lib/orchestrate/presets.js.map +1 -1
  159. package/dist/lib/orchestrate/types.d.ts +1 -1
  160. package/dist/lib/orchestrate/types.js +1 -0
  161. package/dist/lib/orchestrate/types.js.map +1 -1
  162. package/dist/lib/pmo/index.js +1 -1
  163. package/dist/lib/pmo/index.js.map +1 -1
  164. package/dist/lib/pmo/markdown.js +1 -1
  165. package/dist/lib/pmo/markdown.js.map +1 -1
  166. package/dist/lib/pmo/schema.d.ts +3 -1
  167. package/dist/lib/pmo/schema.js +26 -2
  168. package/dist/lib/pmo/schema.js.map +1 -1
  169. package/dist/lib/pmo/storage/actions.js +1 -1
  170. package/dist/lib/pmo/storage/actions.js.map +1 -1
  171. package/dist/lib/pmo/storage/base.js +37 -15
  172. package/dist/lib/pmo/storage/base.js.map +1 -1
  173. package/dist/lib/pmo/storage/projects.js +2 -1
  174. package/dist/lib/pmo/storage/projects.js.map +1 -1
  175. package/dist/lib/pmo/storage/statuses.js +1 -1
  176. package/dist/lib/pmo/storage/statuses.js.map +1 -1
  177. package/dist/lib/pmo/storage/subtasks.js +1 -1
  178. package/dist/lib/pmo/storage/subtasks.js.map +1 -1
  179. package/dist/lib/pmo/storage/templates.js +1 -1
  180. package/dist/lib/pmo/storage/templates.js.map +1 -1
  181. package/dist/lib/pmo/storage/tickets.js +2 -1
  182. package/dist/lib/pmo/storage/tickets.js.map +1 -1
  183. package/dist/lib/pmo/storage/workflow-rules.js +1 -1
  184. package/dist/lib/pmo/storage/workflow-rules.js.map +1 -1
  185. package/dist/lib/pmo/utils.d.ts +6 -189
  186. package/dist/lib/pmo/utils.js +6 -306
  187. package/dist/lib/pmo/utils.js.map +1 -1
  188. package/dist/lib/prompt-json.d.ts +31 -0
  189. package/dist/lib/prompt-json.js.map +1 -1
  190. package/dist/lib/providers/auto-mapper.d.ts +45 -0
  191. package/dist/lib/providers/auto-mapper.js +115 -0
  192. package/dist/lib/providers/auto-mapper.js.map +1 -0
  193. package/dist/lib/providers/state-intents.d.ts +20 -0
  194. package/dist/lib/providers/state-intents.js +61 -7
  195. package/dist/lib/providers/state-intents.js.map +1 -1
  196. package/dist/lib/providers/state-resolution.d.ts +15 -11
  197. package/dist/lib/providers/state-resolution.js +54 -48
  198. package/dist/lib/providers/state-resolution.js.map +1 -1
  199. package/dist/lib/providers/transition-map.d.ts +59 -0
  200. package/dist/lib/providers/transition-map.js +113 -0
  201. package/dist/lib/providers/transition-map.js.map +1 -0
  202. package/dist/lib/session/heartbeat.js +1 -1
  203. package/dist/lib/session/heartbeat.js.map +1 -1
  204. package/dist/lib/session/index.d.ts +3 -1
  205. package/dist/lib/session/index.js +3 -1
  206. package/dist/lib/session/index.js.map +1 -1
  207. package/dist/lib/session/tmux-watchdog.d.ts +157 -0
  208. package/dist/lib/session/tmux-watchdog.js +424 -0
  209. package/dist/lib/session/tmux-watchdog.js.map +1 -0
  210. package/dist/lib/session/watcher.d.ts +22 -4
  211. package/dist/lib/session/watcher.js +66 -8
  212. package/dist/lib/session/watcher.js.map +1 -1
  213. package/dist/lib/sync/daemon-process.d.ts +9 -0
  214. package/dist/lib/sync/daemon-process.js +184 -0
  215. package/dist/lib/sync/daemon-process.js.map +1 -0
  216. package/dist/lib/sync/daemon.d.ts +39 -0
  217. package/dist/lib/sync/daemon.js +91 -0
  218. package/dist/lib/sync/daemon.js.map +1 -0
  219. package/dist/lib/sync/engine.d.ts +38 -0
  220. package/dist/lib/sync/engine.js +145 -0
  221. package/dist/lib/sync/engine.js.map +1 -0
  222. package/dist/lib/sync/merge-queue.d.ts +116 -0
  223. package/dist/lib/sync/merge-queue.js +321 -0
  224. package/dist/lib/sync/merge-queue.js.map +1 -0
  225. package/dist/lib/sync/reconciler.d.ts +44 -0
  226. package/dist/lib/sync/reconciler.js +88 -0
  227. package/dist/lib/sync/reconciler.js.map +1 -0
  228. package/dist/lib/utils/text.d.ts +44 -0
  229. package/dist/lib/utils/text.js +72 -0
  230. package/dist/lib/utils/text.js.map +1 -0
  231. package/dist/lib/work-lifecycle/post-execution.js +1 -1
  232. package/dist/lib/work-lifecycle/post-execution.js.map +1 -1
  233. package/dist/lib/work-lifecycle/settings.d.ts +138 -0
  234. package/dist/lib/work-lifecycle/settings.js +213 -0
  235. package/dist/lib/work-lifecycle/settings.js.map +1 -0
  236. package/dist/lib/work-lifecycle/transition.d.ts +73 -0
  237. package/dist/lib/work-lifecycle/transition.js +124 -0
  238. package/dist/lib/work-lifecycle/transition.js.map +1 -0
  239. package/oclif.manifest.json +3235 -3380
  240. package/package.json +1 -1
  241. package/dist/commands/action/create.d.ts +0 -26
  242. package/dist/commands/action/create.js +0 -245
  243. package/dist/commands/action/create.js.map +0 -1
  244. package/dist/commands/action/delete.d.ts +0 -18
  245. package/dist/commands/action/delete.js +0 -78
  246. package/dist/commands/action/delete.js.map +0 -1
  247. package/dist/commands/action/index.js +0 -103
  248. package/dist/commands/action/index.js.map +0 -1
  249. package/dist/commands/action/list.d.ts +0 -15
  250. package/dist/commands/action/list.js +0 -90
  251. package/dist/commands/action/list.js.map +0 -1
  252. package/dist/commands/action/run.d.ts +0 -20
  253. package/dist/commands/action/run.js +0 -188
  254. package/dist/commands/action/run.js.map +0 -1
  255. package/dist/commands/action/show.d.ts +0 -17
  256. package/dist/commands/action/show.js +0 -78
  257. package/dist/commands/action/show.js.map +0 -1
  258. package/dist/commands/action/update.d.ts +0 -27
  259. package/dist/commands/action/update.js +0 -288
  260. package/dist/commands/action/update.js.map +0 -1
@@ -6,13 +6,14 @@
6
6
  * that can't self-report (OOM kills, zombie processes, container crashes).
7
7
  *
8
8
  * Architecture:
9
- * 1. Poll: Check all running executions for heartbeat timeout
10
- * 2. Update: Record heartbeats for alive agents (tmux pane inspection)
11
- * 3. Detect: Find stale executions that exceeded the timeout
12
- * 4. Act: Mark failed, kill containers, fire events
9
+ * Phase 0: Tmux server health check detect full server crashes (PRLT-1115)
10
+ * Phase 1: Record heartbeats for alive agents (tmux pane inspection)
11
+ * Phase 2: Detect stale executions that exceeded the timeout
12
+ * Phase 3: Act on stale executions — mark failed, kill containers, fire events
13
13
  */
14
14
  import { ExecutionStorage } from '../execution/storage.js';
15
15
  import { recordAllHeartbeats, detectStaleExecutions, killContainer, } from './heartbeat.js';
16
+ import { TmuxWatchdog, formatCrashNotification, sendDesktopNotification, } from './tmux-watchdog.js';
16
17
  // =============================================================================
17
18
  // Session Watcher
18
19
  // =============================================================================
@@ -22,18 +23,40 @@ export class SessionWatcher {
22
23
  intervalMinutes;
23
24
  timeoutMinutes;
24
25
  autoKill;
26
+ autoRecover;
25
27
  log;
26
28
  onStaleDetected;
29
+ onCrashDetected;
27
30
  timer = null;
28
31
  running = false;
32
+ watchdog;
33
+ isFirstCycle = true;
29
34
  constructor(options) {
30
35
  this.db = options.db;
31
36
  this.storage = new ExecutionStorage(options.db);
32
37
  this.intervalMinutes = options.intervalMinutes ?? 5;
33
38
  this.timeoutMinutes = options.timeoutMinutes ?? 15;
34
39
  this.autoKill = options.autoKill ?? true;
40
+ this.autoRecover = options.autoRecover ?? true;
35
41
  this.log = options.log ?? (() => { });
36
42
  this.onStaleDetected = options.onStaleDetected;
43
+ this.onCrashDetected = options.onCrashDetected;
44
+ this.watchdog = new TmuxWatchdog({
45
+ storage: this.storage,
46
+ autoRecover: this.autoRecover,
47
+ log: this.log,
48
+ onCrashDetected: async (event) => {
49
+ // Send desktop notification
50
+ const notification = formatCrashNotification(event);
51
+ this.log(notification);
52
+ sendDesktopNotification('prlt: tmux server crash', `${event.affectedExecutions.length} agent(s) affected. ` +
53
+ `${event.recoveredSessions.length} recovered.`);
54
+ // Fire user callback
55
+ if (this.onCrashDetected) {
56
+ await this.onCrashDetected(event);
57
+ }
58
+ },
59
+ });
37
60
  }
38
61
  /**
39
62
  * Run a single watch cycle.
@@ -45,7 +68,25 @@ export class SessionWatcher {
45
68
  heartbeatsUpdated: 0,
46
69
  staleExecutions: [],
47
70
  containersKilled: 0,
71
+ crashEvents: [],
72
+ crashRecoveries: 0,
48
73
  };
74
+ // Phase 0: Tmux server health check (PRLT-1115)
75
+ // Detect full server crashes before doing individual heartbeat checks.
76
+ // On the first cycle, seed the watchdog state without triggering crash detection.
77
+ if (this.isFirstCycle) {
78
+ const activeExecs = [
79
+ ...this.storage.listExecutions({ status: 'running' }),
80
+ ...this.storage.listExecutions({ status: 'starting' }),
81
+ ];
82
+ this.watchdog.seedServerState(activeExecs);
83
+ this.isFirstCycle = false;
84
+ }
85
+ else {
86
+ const watchdogResult = await this.watchdog.checkAndRecover();
87
+ result.crashEvents = watchdogResult.crashEvents;
88
+ result.crashRecoveries = watchdogResult.totalRecovered;
89
+ }
49
90
  // Phase 1: Record heartbeats for all active executions
50
91
  // This is the "push" side — we check tmux panes and update heartbeats
51
92
  const heartbeats = recordAllHeartbeats(this.storage);
@@ -88,7 +129,8 @@ export class SessionWatcher {
88
129
  if (this.running)
89
130
  return;
90
131
  this.running = true;
91
- this.log(`[watcher] Starting session watcher (interval: ${this.intervalMinutes}m, timeout: ${this.timeoutMinutes}m, auto-kill: ${this.autoKill})`);
132
+ this.log(`[watcher] Starting session watcher (interval: ${this.intervalMinutes}m, timeout: ${this.timeoutMinutes}m, ` +
133
+ `auto-kill: ${this.autoKill}, auto-recover: ${this.autoRecover})`);
92
134
  // Run initial cycle
93
135
  void this.runCycleWithErrorHandling();
94
136
  // Start polling
@@ -124,14 +166,30 @@ export class SessionWatcher {
124
166
  intervalMinutes: this.intervalMinutes,
125
167
  timeoutMinutes: this.timeoutMinutes,
126
168
  autoKill: this.autoKill,
169
+ autoRecover: this.autoRecover,
127
170
  };
128
171
  }
172
+ /**
173
+ * Get the tmux watchdog instance (for testing/diagnostics).
174
+ */
175
+ getWatchdog() {
176
+ return this.watchdog;
177
+ }
129
178
  async runCycleWithErrorHandling() {
130
179
  try {
131
180
  const result = await this.runCycle();
132
- if (result.staleExecutions.length > 0) {
133
- this.log(`[watcher] Cycle complete: ${result.checked} checked, ${result.heartbeatsUpdated} heartbeats, ` +
134
- `${result.staleExecutions.length} stale, ${result.containersKilled} killed`);
181
+ if (result.staleExecutions.length > 0 || result.crashEvents.length > 0) {
182
+ const parts = [
183
+ `${result.checked} checked`,
184
+ `${result.heartbeatsUpdated} heartbeats`,
185
+ `${result.staleExecutions.length} stale`,
186
+ `${result.containersKilled} killed`,
187
+ ];
188
+ if (result.crashEvents.length > 0) {
189
+ parts.push(`${result.crashEvents.length} crash(es)`);
190
+ parts.push(`${result.crashRecoveries} recovered`);
191
+ }
192
+ this.log(`[watcher] Cycle complete: ${parts.join(', ')}`);
135
193
  }
136
194
  }
137
195
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../../src/lib/session/watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../../src/lib/session/watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Daemon Process
3
+ *
4
+ * This is the background process spawned by `prlt sync start`.
5
+ * It runs a sync cycle and merge queue cycle on a configurable interval.
6
+ *
7
+ * Args: [hqPath, intervalSeconds]
8
+ */
9
+ export {};
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Daemon Process
3
+ *
4
+ * This is the background process spawned by `prlt sync start`.
5
+ * It runs a sync cycle and merge queue cycle on a configurable interval.
6
+ *
7
+ * Args: [hqPath, intervalSeconds]
8
+ */
9
+ import * as fs from 'node:fs';
10
+ import { openWorkspaceDatabase } from '../database/index.js';
11
+ import { getPMOContext } from '../pmo/pmo-context.js';
12
+ import { runSyncCycle } from './engine.js';
13
+ import { runMergeQueueCycle } from './merge-queue.js';
14
+ import { removeDaemonPid, getDaemonLogPath } from './daemon.js';
15
+ import { GCScheduler, collectGCCandidates, executeGC, } from '../gc/index.js';
16
+ const args = process.argv.slice(2);
17
+ const hqPath = args[0];
18
+ const intervalSeconds = parseInt(args[1] || '60', 10);
19
+ if (!hqPath) {
20
+ console.error('Usage: daemon-process <hqPath> [intervalSeconds]');
21
+ process.exit(1);
22
+ }
23
+ const logPath = getDaemonLogPath(hqPath);
24
+ function log(msg) {
25
+ const timestamp = new Date().toISOString();
26
+ const line = `[${timestamp}] ${msg}\n`;
27
+ fs.appendFileSync(logPath, line);
28
+ }
29
+ async function getProjectId() {
30
+ const context = await getPMOContext();
31
+ const projects = await context.storage.listProjects();
32
+ await context.storage.close();
33
+ if (projects.length === 0) {
34
+ throw new Error('No projects found');
35
+ }
36
+ return projects[0].id;
37
+ }
38
+ // GC scheduler with 1-hour grace period — persists across daemon cycles
39
+ const gcScheduler = new GCScheduler(60 * 60 * 1000);
40
+ /** Map ticket priority strings to numeric values (lower = higher priority). */
41
+ function priorityToNumber(priority) {
42
+ switch (priority) {
43
+ case 'P0': return 0;
44
+ case 'P1': return 1;
45
+ case 'P2': return 2;
46
+ case 'P3': return 3;
47
+ default: return 3;
48
+ }
49
+ }
50
+ async function cycle() {
51
+ let db;
52
+ try {
53
+ db = openWorkspaceDatabase(hqPath);
54
+ const context = await getPMOContext();
55
+ const projectId = await getProjectId();
56
+ const storage = context.storage;
57
+ // Phase 1: Reconciliation — sync ticket state with PR state
58
+ const report = await runSyncCycle(db, storage, projectId, {
59
+ cwd: hqPath,
60
+ log,
61
+ });
62
+ if (report.applied.length > 0) {
63
+ log(`Applied ${report.applied.length} correction(s)`);
64
+ }
65
+ if (report.failed.length > 0) {
66
+ log(`Failed ${report.failed.length} correction(s)`);
67
+ }
68
+ // Phase 2: Merge Queue — sequential rebase-test-merge pipeline
69
+ try {
70
+ // Build priority map from tickets for queue ordering
71
+ const branchPriorities = new Map();
72
+ const startedTickets = await storage.listTickets(projectId, { statusCategory: 'started' });
73
+ for (const ticket of startedTickets) {
74
+ if (ticket.branch) {
75
+ branchPriorities.set(ticket.branch, priorityToNumber(ticket.priority));
76
+ }
77
+ }
78
+ const mqResult = runMergeQueueCycle({
79
+ hqPath,
80
+ cwd: hqPath,
81
+ log,
82
+ branchPriorities,
83
+ });
84
+ if (mqResult.action !== 'none' && mqResult.action !== 'paused') {
85
+ log(`Merge queue: ${mqResult.action}${mqResult.prNumber ? ` PR #${mqResult.prNumber}` : ''}${mqResult.reason ? ` — ${mqResult.reason}` : ''}`);
86
+ }
87
+ }
88
+ catch (mqErr) {
89
+ const mqMsg = mqErr instanceof Error ? mqErr.message : String(mqErr);
90
+ log(`Merge queue error: ${mqMsg}`);
91
+ }
92
+ // Phase 3: Garbage Collection — schedule cleanup for merged PRs, run ready cleanups
93
+ try {
94
+ // Schedule GC for any tickets that just moved to Done (PR merged)
95
+ const mergedActions = report.applied.filter(a => a.type === 'move_to_done');
96
+ if (mergedActions.length > 0) {
97
+ const completedTickets = await storage.listTickets(projectId, { statusCategory: 'completed' });
98
+ for (const action of mergedActions) {
99
+ const ticket = completedTickets.find(t => t.id === action.ticketId);
100
+ if (ticket?.branch) {
101
+ gcScheduler.schedule(ticket.branch);
102
+ log(`GC: Scheduled cleanup for branch ${ticket.branch} (1hr grace period)`);
103
+ }
104
+ }
105
+ }
106
+ // Process any ready cleanups (grace period expired)
107
+ const readyBranches = gcScheduler.getReady();
108
+ if (readyBranches.length > 0) {
109
+ log(`GC: Processing ${readyBranches.length} cleanup(s) past grace period`);
110
+ const candidates = collectGCCandidates({
111
+ hqPath,
112
+ staleDays: 7,
113
+ log,
114
+ });
115
+ // Only clean up the branches that are ready
116
+ const readySet = new Set(readyBranches);
117
+ const readyCandidates = candidates.filter(c => readySet.has(c.branch));
118
+ if (readyCandidates.length > 0) {
119
+ const result = executeGC(readyCandidates, {
120
+ hqPath,
121
+ execute: true,
122
+ log,
123
+ });
124
+ if (result.worktreesRemoved.length > 0) {
125
+ log(`GC: Removed ${result.worktreesRemoved.length} worktree(s), ${result.containersRemoved.length} container(s), ${result.branchesPruned.length} branch(es)`);
126
+ }
127
+ if (result.errors.length > 0) {
128
+ log(`GC: ${result.errors.length} error(s): ${result.errors.join('; ')}`);
129
+ }
130
+ }
131
+ // Mark as completed regardless of whether cleanup was needed
132
+ for (const branch of readyBranches) {
133
+ gcScheduler.complete(branch);
134
+ }
135
+ }
136
+ }
137
+ catch (gcErr) {
138
+ const gcMsg = gcErr instanceof Error ? gcErr.message : String(gcErr);
139
+ log(`GC error: ${gcMsg}`);
140
+ }
141
+ await context.storage.close();
142
+ }
143
+ catch (err) {
144
+ const msg = err instanceof Error ? err.message : String(err);
145
+ log(`Error: ${msg}`);
146
+ }
147
+ finally {
148
+ if (db) {
149
+ try {
150
+ db.close();
151
+ }
152
+ catch { }
153
+ }
154
+ }
155
+ }
156
+ // Signal handling
157
+ process.on('SIGTERM', () => {
158
+ log('Received SIGTERM — shutting down');
159
+ removeDaemonPid(hqPath);
160
+ process.exit(0);
161
+ });
162
+ process.on('SIGINT', () => {
163
+ log('Received SIGINT — shutting down');
164
+ removeDaemonPid(hqPath);
165
+ process.exit(0);
166
+ });
167
+ // Main loop
168
+ log(`Daemon started (PID ${process.pid}, interval ${intervalSeconds}s)`);
169
+ async function run() {
170
+ // Run initial cycle immediately
171
+ await cycle();
172
+ // Then schedule periodic runs
173
+ setInterval(() => {
174
+ cycle().catch(err => {
175
+ log(`Unhandled error in cycle: ${err}`);
176
+ });
177
+ }, intervalSeconds * 1000);
178
+ }
179
+ run().catch(err => {
180
+ log(`Fatal: ${err}`);
181
+ removeDaemonPid(hqPath);
182
+ process.exit(1);
183
+ });
184
+ //# sourceMappingURL=daemon-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-process.js","sourceRoot":"","sources":["../../../src/lib/sync/daemon-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Sync Daemon
3
+ *
4
+ * Manages a background process that periodically runs the sync engine.
5
+ * Uses a PID file in the HQ directory to track the daemon process.
6
+ */
7
+ export interface DaemonInfo {
8
+ pid: number;
9
+ startedAt: string;
10
+ intervalSeconds: number;
11
+ }
12
+ /**
13
+ * Get the path to the daemon PID file.
14
+ */
15
+ export declare function getDaemonPidPath(hqPath: string): string;
16
+ /**
17
+ * Get the path to the daemon log file.
18
+ */
19
+ export declare function getDaemonLogPath(hqPath: string): string;
20
+ /**
21
+ * Read daemon info from PID file.
22
+ */
23
+ export declare function getDaemonInfo(hqPath: string): DaemonInfo | null;
24
+ /**
25
+ * Write daemon info to PID file.
26
+ */
27
+ export declare function writeDaemonInfo(hqPath: string, info: DaemonInfo): void;
28
+ /**
29
+ * Remove daemon PID file.
30
+ */
31
+ export declare function removeDaemonPid(hqPath: string): void;
32
+ /**
33
+ * Check if a daemon process is alive by PID.
34
+ */
35
+ export declare function isDaemonRunning(hqPath: string): boolean;
36
+ /**
37
+ * Stop the daemon process.
38
+ */
39
+ export declare function stopDaemon(hqPath: string): boolean;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Sync Daemon
3
+ *
4
+ * Manages a background process that periodically runs the sync engine.
5
+ * Uses a PID file in the HQ directory to track the daemon process.
6
+ */
7
+ import * as fs from 'node:fs';
8
+ import * as path from 'node:path';
9
+ const DAEMON_PID_FILE = 'sync-daemon.pid';
10
+ const DAEMON_LOG_FILE = 'sync-daemon.log';
11
+ /**
12
+ * Get the path to the daemon PID file.
13
+ */
14
+ export function getDaemonPidPath(hqPath) {
15
+ return path.join(hqPath, '.proletariat', DAEMON_PID_FILE);
16
+ }
17
+ /**
18
+ * Get the path to the daemon log file.
19
+ */
20
+ export function getDaemonLogPath(hqPath) {
21
+ return path.join(hqPath, '.proletariat', DAEMON_LOG_FILE);
22
+ }
23
+ /**
24
+ * Read daemon info from PID file.
25
+ */
26
+ export function getDaemonInfo(hqPath) {
27
+ const pidPath = getDaemonPidPath(hqPath);
28
+ try {
29
+ const content = fs.readFileSync(pidPath, 'utf-8');
30
+ return JSON.parse(content);
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ /**
37
+ * Write daemon info to PID file.
38
+ */
39
+ export function writeDaemonInfo(hqPath, info) {
40
+ const pidPath = getDaemonPidPath(hqPath);
41
+ fs.writeFileSync(pidPath, JSON.stringify(info, null, 2));
42
+ }
43
+ /**
44
+ * Remove daemon PID file.
45
+ */
46
+ export function removeDaemonPid(hqPath) {
47
+ const pidPath = getDaemonPidPath(hqPath);
48
+ try {
49
+ fs.unlinkSync(pidPath);
50
+ }
51
+ catch {
52
+ // File may not exist
53
+ }
54
+ }
55
+ /**
56
+ * Check if a daemon process is alive by PID.
57
+ */
58
+ export function isDaemonRunning(hqPath) {
59
+ const info = getDaemonInfo(hqPath);
60
+ if (!info)
61
+ return false;
62
+ try {
63
+ // Sending signal 0 checks if process exists without killing it
64
+ process.kill(info.pid, 0);
65
+ return true;
66
+ }
67
+ catch {
68
+ // Process doesn't exist — clean up stale PID file
69
+ removeDaemonPid(hqPath);
70
+ return false;
71
+ }
72
+ }
73
+ /**
74
+ * Stop the daemon process.
75
+ */
76
+ export function stopDaemon(hqPath) {
77
+ const info = getDaemonInfo(hqPath);
78
+ if (!info)
79
+ return false;
80
+ try {
81
+ process.kill(info.pid, 'SIGTERM');
82
+ removeDaemonPid(hqPath);
83
+ return true;
84
+ }
85
+ catch {
86
+ // Process may already be dead
87
+ removeDaemonPid(hqPath);
88
+ return false;
89
+ }
90
+ }
91
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../src/lib/sync/daemon.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAEjC,MAAM,eAAe,GAAG,iBAAiB,CAAA;AACzC,MAAM,eAAe,GAAG,iBAAiB,CAAA;AAQzC;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,eAAe,CAAC,CAAA;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,eAAe,CAAC,CAAA;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACxC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAA;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,IAAgB;IAC9D,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACxC,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AAC1D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACxC,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,qBAAqB;IACvB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAA;IAEvB,IAAI,CAAC;QACH,+DAA+D;QAC/D,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;QACzB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;QAClD,eAAe,CAAC,MAAM,CAAC,CAAA;QACvB,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAA;IAEvB,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;QACjC,eAAe,CAAC,MAAM,CAAC,CAAA;QACvB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;QAC9B,eAAe,CAAC,MAAM,CAAC,CAAA;QACvB,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Sync Engine
3
+ *
4
+ * Orchestrates the reconciliation process: gathers ticket state and PR state,
5
+ * runs the reconciler, and applies corrective actions through providers.
6
+ *
7
+ * This is the "run once" engine. The daemon wraps this with a polling loop.
8
+ */
9
+ import type Database from 'better-sqlite3';
10
+ import type { ProviderStorage } from '../providers/types.js';
11
+ import type { PMOStorage } from '../pmo/types.js';
12
+ import { type ReconcileAction, type ReconcileResult } from './reconciler.js';
13
+ export interface SyncEngineOptions {
14
+ /** Working directory for git/gh operations */
15
+ cwd?: string;
16
+ /** Callback for logging */
17
+ log?: (msg: string) => void;
18
+ /** If true, don't actually move tickets — just report what would happen */
19
+ dryRun?: boolean;
20
+ }
21
+ export interface SyncReport {
22
+ result: ReconcileResult;
23
+ applied: ReconcileAction[];
24
+ skipped: ReconcileAction[];
25
+ failed: Array<{
26
+ action: ReconcileAction;
27
+ error: string;
28
+ }>;
29
+ }
30
+ /**
31
+ * Run a single reconciliation cycle.
32
+ *
33
+ * 1. List all tickets in started/review states
34
+ * 2. For each, check PR status
35
+ * 3. Run reconciler to determine actions
36
+ * 4. Apply actions through providers
37
+ */
38
+ export declare function runSyncCycle(db: Database.Database, storage: PMOStorage & ProviderStorage, projectId: string, options?: SyncEngineOptions): Promise<SyncReport>;