@proletariat/cli 0.3.105 → 0.3.110

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 (240) hide show
  1. package/dist/commands/agent/cleanup.js +13 -1
  2. package/dist/commands/agent/cleanup.js.map +1 -1
  3. package/dist/commands/claude/index.js +2 -2
  4. package/dist/commands/claude/index.js.map +1 -1
  5. package/dist/commands/feedback/list.js +4 -9
  6. package/dist/commands/feedback/list.js.map +1 -1
  7. package/dist/commands/feedback/submit.js +4 -9
  8. package/dist/commands/feedback/submit.js.map +1 -1
  9. package/dist/commands/feedback/view.js +4 -9
  10. package/dist/commands/feedback/view.js.map +1 -1
  11. package/dist/commands/gc.d.ts +1 -0
  12. package/dist/commands/gc.js +34 -1
  13. package/dist/commands/gc.js.map +1 -1
  14. package/dist/commands/notify/connect.d.ts +34 -0
  15. package/dist/commands/notify/connect.js +166 -0
  16. package/dist/commands/notify/connect.js.map +1 -0
  17. package/dist/commands/notify/disconnect.d.ts +16 -0
  18. package/dist/commands/notify/disconnect.js +45 -0
  19. package/dist/commands/notify/disconnect.js.map +1 -0
  20. package/dist/commands/notify/list.d.ts +15 -0
  21. package/dist/commands/notify/list.js +101 -0
  22. package/dist/commands/notify/list.js.map +1 -0
  23. package/dist/commands/notify/rules/add.d.ts +26 -0
  24. package/dist/commands/notify/rules/add.js +95 -0
  25. package/dist/commands/notify/rules/add.js.map +1 -0
  26. package/dist/commands/notify/rules/list.d.ts +14 -0
  27. package/dist/commands/notify/rules/list.js +82 -0
  28. package/dist/commands/notify/rules/list.js.map +1 -0
  29. package/dist/commands/notify/rules/remove.d.ts +16 -0
  30. package/dist/commands/notify/rules/remove.js +44 -0
  31. package/dist/commands/notify/rules/remove.js.map +1 -0
  32. package/dist/commands/notify/test.d.ts +16 -0
  33. package/dist/commands/notify/test.js +63 -0
  34. package/dist/commands/notify/test.js.map +1 -0
  35. package/dist/commands/orchestrate/index.js +11 -6
  36. package/dist/commands/orchestrate/index.js.map +1 -1
  37. package/dist/commands/orchestrate/machine.d.ts +29 -0
  38. package/dist/commands/orchestrate/machine.js +230 -0
  39. package/dist/commands/orchestrate/machine.js.map +1 -0
  40. package/dist/commands/pr/checks.js +4 -8
  41. package/dist/commands/pr/checks.js.map +1 -1
  42. package/dist/commands/pr/close.js +4 -8
  43. package/dist/commands/pr/close.js.map +1 -1
  44. package/dist/commands/pr/create.js +4 -8
  45. package/dist/commands/pr/create.js.map +1 -1
  46. package/dist/commands/pr/index.js +1 -1
  47. package/dist/commands/pr/index.js.map +1 -1
  48. package/dist/commands/pr/link.js +4 -8
  49. package/dist/commands/pr/link.js.map +1 -1
  50. package/dist/commands/pr/list.js +5 -9
  51. package/dist/commands/pr/list.js.map +1 -1
  52. package/dist/commands/pr/merge.d.ts +5 -0
  53. package/dist/commands/pr/merge.js +35 -11
  54. package/dist/commands/pr/merge.js.map +1 -1
  55. package/dist/commands/pr/status.js +5 -4
  56. package/dist/commands/pr/status.js.map +1 -1
  57. package/dist/commands/qa/index.js +2 -2
  58. package/dist/commands/qa/index.js.map +1 -1
  59. package/dist/commands/repo/create.js +4 -8
  60. package/dist/commands/repo/create.js.map +1 -1
  61. package/dist/commands/session/list.js +81 -41
  62. package/dist/commands/session/list.js.map +1 -1
  63. package/dist/commands/session/poke.d.ts +1 -11
  64. package/dist/commands/session/poke.js +20 -78
  65. package/dist/commands/session/poke.js.map +1 -1
  66. package/dist/commands/session/prune.js +3 -0
  67. package/dist/commands/session/prune.js.map +1 -1
  68. package/dist/commands/ticket/move.d.ts +12 -0
  69. package/dist/commands/ticket/move.js +75 -2
  70. package/dist/commands/ticket/move.js.map +1 -1
  71. package/dist/commands/work/drop.js +2 -2
  72. package/dist/commands/work/drop.js.map +1 -1
  73. package/dist/commands/work/ready.js +3 -3
  74. package/dist/commands/work/ready.js.map +1 -1
  75. package/dist/commands/work/rebase.js +4 -8
  76. package/dist/commands/work/rebase.js.map +1 -1
  77. package/dist/commands/work/run.d.ts +58 -0
  78. package/dist/commands/work/run.js +411 -0
  79. package/dist/commands/work/run.js.map +1 -0
  80. package/dist/commands/work/ship.d.ts +6 -0
  81. package/dist/commands/work/ship.js +93 -51
  82. package/dist/commands/work/ship.js.map +1 -1
  83. package/dist/commands/work/start.d.ts +1 -0
  84. package/dist/commands/work/start.js +126 -13
  85. package/dist/commands/work/start.js.map +1 -1
  86. package/dist/lib/agents/commands.d.ts +6 -0
  87. package/dist/lib/agents/commands.js +55 -2
  88. package/dist/lib/agents/commands.js.map +1 -1
  89. package/dist/lib/database/credential-store.js +2 -3
  90. package/dist/lib/database/credential-store.js.map +1 -1
  91. package/dist/lib/database/db-safety.d.ts +25 -0
  92. package/dist/lib/database/db-safety.js +35 -0
  93. package/dist/lib/database/db-safety.js.map +1 -1
  94. package/dist/lib/database/driver.js +6 -12
  95. package/dist/lib/database/driver.js.map +1 -1
  96. package/dist/lib/database/drizzle-schema.d.ts +3 -3
  97. package/dist/lib/database/drizzle.js +3 -3
  98. package/dist/lib/database/drizzle.js.map +1 -1
  99. package/dist/lib/database/index.d.ts +1 -1
  100. package/dist/lib/database/index.js +1 -1
  101. package/dist/lib/database/index.js.map +1 -1
  102. package/dist/lib/database/migrations/0021_notification_system.d.ts +2 -0
  103. package/dist/lib/database/migrations/0021_notification_system.js +39 -0
  104. package/dist/lib/database/migrations/0021_notification_system.js.map +1 -0
  105. package/dist/lib/database/migrations/0022_hook_mode_tiers.d.ts +11 -0
  106. package/dist/lib/database/migrations/0022_hook_mode_tiers.js +53 -0
  107. package/dist/lib/database/migrations/0022_hook_mode_tiers.js.map +1 -0
  108. package/dist/lib/database/migrations/index.js +4 -0
  109. package/dist/lib/database/migrations/index.js.map +1 -1
  110. package/dist/lib/database/pmo-bootstrap.js +6 -2
  111. package/dist/lib/database/pmo-bootstrap.js.map +1 -1
  112. package/dist/lib/database/workspace.js +5 -13
  113. package/dist/lib/database/workspace.js.map +1 -1
  114. package/dist/lib/events/emitting-runner.js +10 -0
  115. package/dist/lib/events/emitting-runner.js.map +1 -1
  116. package/dist/lib/execution/cc-version.d.ts +62 -0
  117. package/dist/lib/execution/cc-version.js +103 -0
  118. package/dist/lib/execution/cc-version.js.map +1 -0
  119. package/dist/lib/execution/devcontainer.js +2 -1
  120. package/dist/lib/execution/devcontainer.js.map +1 -1
  121. package/dist/lib/execution/runners/devcontainer.js +4 -1
  122. package/dist/lib/execution/runners/devcontainer.js.map +1 -1
  123. package/dist/lib/execution/runners/docker-management.js +10 -46
  124. package/dist/lib/execution/runners/docker-management.js.map +1 -1
  125. package/dist/lib/execution/runners/orchestrator.js +13 -39
  126. package/dist/lib/execution/runners/orchestrator.js.map +1 -1
  127. package/dist/lib/execution/session-utils.d.ts +88 -1
  128. package/dist/lib/execution/session-utils.js +120 -46
  129. package/dist/lib/execution/session-utils.js.map +1 -1
  130. package/dist/lib/execution/storage.js +20 -2
  131. package/dist/lib/execution/storage.js.map +1 -1
  132. package/dist/lib/flags/resolver.d.ts +8 -1
  133. package/dist/lib/flags/resolver.js +35 -2
  134. package/dist/lib/flags/resolver.js.map +1 -1
  135. package/dist/lib/gc/cascade.d.ts +99 -0
  136. package/dist/lib/gc/cascade.js +357 -0
  137. package/dist/lib/gc/cascade.js.map +1 -0
  138. package/dist/lib/gc/config.d.ts +69 -0
  139. package/dist/lib/gc/config.js +134 -0
  140. package/dist/lib/gc/config.js.map +1 -0
  141. package/dist/lib/gc/index.d.ts +36 -0
  142. package/dist/lib/gc/index.js +209 -1
  143. package/dist/lib/gc/index.js.map +1 -1
  144. package/dist/lib/init/index.js +10 -1
  145. package/dist/lib/init/index.js.map +1 -1
  146. package/dist/lib/machine-db.d.ts +144 -0
  147. package/dist/lib/machine-db.js +338 -0
  148. package/dist/lib/machine-db.js.map +1 -0
  149. package/dist/lib/machine-orchestrator.d.ts +35 -0
  150. package/dist/lib/machine-orchestrator.js +139 -0
  151. package/dist/lib/machine-orchestrator.js.map +1 -0
  152. package/dist/lib/notifications/dispatcher.d.ts +29 -0
  153. package/dist/lib/notifications/dispatcher.js +281 -0
  154. package/dist/lib/notifications/dispatcher.js.map +1 -0
  155. package/dist/lib/notifications/index.d.ts +13 -0
  156. package/dist/lib/notifications/index.js +18 -0
  157. package/dist/lib/notifications/index.js.map +1 -0
  158. package/dist/lib/notifications/manager.d.ts +46 -0
  159. package/dist/lib/notifications/manager.js +200 -0
  160. package/dist/lib/notifications/manager.js.map +1 -0
  161. package/dist/lib/notifications/storage.d.ts +60 -0
  162. package/dist/lib/notifications/storage.js +182 -0
  163. package/dist/lib/notifications/storage.js.map +1 -0
  164. package/dist/lib/notifications/types.d.ts +126 -0
  165. package/dist/lib/notifications/types.js +16 -0
  166. package/dist/lib/notifications/types.js.map +1 -0
  167. package/dist/lib/orchestrate/actions.d.ts +8 -0
  168. package/dist/lib/orchestrate/actions.js +339 -88
  169. package/dist/lib/orchestrate/actions.js.map +1 -1
  170. package/dist/lib/orchestrate/config-loader.js +9 -35
  171. package/dist/lib/orchestrate/config-loader.js.map +1 -1
  172. package/dist/lib/orchestrate/engine.d.ts +53 -1
  173. package/dist/lib/orchestrate/engine.js +74 -3
  174. package/dist/lib/orchestrate/engine.js.map +1 -1
  175. package/dist/lib/orchestrate/escalation.d.ts +87 -0
  176. package/dist/lib/orchestrate/escalation.js +63 -0
  177. package/dist/lib/orchestrate/escalation.js.map +1 -0
  178. package/dist/lib/orchestrate/index.d.ts +2 -0
  179. package/dist/lib/orchestrate/index.js +1 -0
  180. package/dist/lib/orchestrate/index.js.map +1 -1
  181. package/dist/lib/orchestrate/llm-agent.d.ts +101 -0
  182. package/dist/lib/orchestrate/llm-agent.js +295 -0
  183. package/dist/lib/orchestrate/llm-agent.js.map +1 -0
  184. package/dist/lib/orchestrate/presets.d.ts +4 -3
  185. package/dist/lib/orchestrate/presets.js +13 -8
  186. package/dist/lib/orchestrate/presets.js.map +1 -1
  187. package/dist/lib/orchestrate/prompt-chain.d.ts +166 -0
  188. package/dist/lib/orchestrate/prompt-chain.js +308 -0
  189. package/dist/lib/orchestrate/prompt-chain.js.map +1 -0
  190. package/dist/lib/orchestrate/types.d.ts +7 -1
  191. package/dist/lib/orchestrate/types.js +1 -0
  192. package/dist/lib/orchestrate/types.js.map +1 -1
  193. package/dist/lib/pmo/base-command.js +1 -1
  194. package/dist/lib/pmo/base-command.js.map +1 -1
  195. package/dist/lib/pmo/find-pmo.d.ts +8 -0
  196. package/dist/lib/pmo/find-pmo.js +63 -2
  197. package/dist/lib/pmo/find-pmo.js.map +1 -1
  198. package/dist/lib/pmo/index.d.ts +1 -1
  199. package/dist/lib/pmo/index.js +1 -1
  200. package/dist/lib/pmo/index.js.map +1 -1
  201. package/dist/lib/pmo/pmo-context.js +1 -1
  202. package/dist/lib/pmo/pmo-context.js.map +1 -1
  203. package/dist/lib/pmo/storage/index.js +2 -1
  204. package/dist/lib/pmo/storage/index.js.map +1 -1
  205. package/dist/lib/pr/index.d.ts +32 -0
  206. package/dist/lib/pr/index.js +45 -0
  207. package/dist/lib/pr/index.js.map +1 -1
  208. package/dist/lib/prompt-command.d.ts +61 -1
  209. package/dist/lib/prompt-command.js +167 -1
  210. package/dist/lib/prompt-command.js.map +1 -1
  211. package/dist/lib/prompt-json.d.ts +129 -2
  212. package/dist/lib/prompt-json.js +157 -0
  213. package/dist/lib/prompt-json.js.map +1 -1
  214. package/dist/lib/registry/index.js +0 -1
  215. package/dist/lib/registry/index.js.map +1 -1
  216. package/dist/lib/runtime-command.d.ts +3 -1
  217. package/dist/lib/runtime-command.js +4 -2
  218. package/dist/lib/runtime-command.js.map +1 -1
  219. package/dist/lib/signal-handler.d.ts +8 -0
  220. package/dist/lib/signal-handler.js +33 -0
  221. package/dist/lib/signal-handler.js.map +1 -1
  222. package/dist/lib/themes.js +8 -1
  223. package/dist/lib/themes.js.map +1 -1
  224. package/dist/lib/work-lifecycle/container-cleanup-hook.d.ts +17 -7
  225. package/dist/lib/work-lifecycle/container-cleanup-hook.js +64 -11
  226. package/dist/lib/work-lifecycle/container-cleanup-hook.js.map +1 -1
  227. package/dist/lib/work-lifecycle/hooks/executor.d.ts +22 -2
  228. package/dist/lib/work-lifecycle/hooks/executor.js +46 -8
  229. package/dist/lib/work-lifecycle/hooks/executor.js.map +1 -1
  230. package/dist/lib/work-lifecycle/hooks/manager.d.ts +62 -3
  231. package/dist/lib/work-lifecycle/hooks/manager.js +285 -4
  232. package/dist/lib/work-lifecycle/hooks/manager.js.map +1 -1
  233. package/dist/lib/work-lifecycle/hooks/types.d.ts +36 -5
  234. package/dist/lib/work-lifecycle/hooks/types.js +1 -1
  235. package/dist/lib/work-lifecycle/hooks/types.js.map +1 -1
  236. package/dist/lib/workspace-resolution.d.ts +73 -0
  237. package/dist/lib/workspace-resolution.js +188 -0
  238. package/dist/lib/workspace-resolution.js.map +1 -0
  239. package/oclif.manifest.json +1787 -1099
  240. package/package.json +1 -1
@@ -1,21 +1,31 @@
1
1
  /**
2
- * Container Cleanup Lifecycle Hook
2
+ * Agent Cleanup Lifecycle Hook
3
3
  *
4
4
  * Subscribes to agent lifecycle events on the global EventBus and
5
- * automatically cleans up Docker containers when agents complete work.
5
+ * automatically runs the full cascading cleanup when agents stop.
6
6
  *
7
- * This is a triggered cleanup (not TTL-based): containers are removed
8
- * when the agent:stopped event fires or when stale executions are detected.
7
+ * This is Tier 1 of the cleanup system: event-driven cleanup that handles
8
+ * the ~90% case when agents stop normally (manual stop, completion, error).
9
+ *
10
+ * The cascade order follows the ticket spec:
11
+ * 1. CC/Claude session → 2. Tmux → 3. Container → 4. Worktree
12
+ * 5. Agent directory → 6. Git branch → 7. Execution records → 8. DB status
9
13
  */
10
14
  /**
11
15
  * ContainerCleanupHook listens for agent completion events and
12
- * removes the associated Docker container.
16
+ * runs the full cascading cleanup.
13
17
  *
14
18
  * Cleanup is fire-and-forget: failures are logged but never block
15
19
  * the event emission chain.
16
20
  */
17
21
  export declare class ContainerCleanupHook {
18
22
  private unsubscribers;
23
+ private hqPath;
24
+ /**
25
+ * Set the HQ path for full cascade cleanup (branch deletion, DB ops).
26
+ * If not set, only container-level cleanup runs.
27
+ */
28
+ setHqPath(hqPath: string): void;
19
29
  /**
20
30
  * Start listening for agent lifecycle events.
21
31
  */
@@ -25,7 +35,7 @@ export declare class ContainerCleanupHook {
25
35
  */
26
36
  stop(): void;
27
37
  /**
28
- * Handle agent:stopped by cleaning up the agent's container.
38
+ * Handle agent:stopped by running cascading cleanup.
29
39
  * Extracts agent name from the session ID or event data.
30
40
  */
31
41
  private handleAgentStopped;
@@ -34,7 +44,7 @@ export declare class ContainerCleanupHook {
34
44
  * Initialize and start the container cleanup hook.
35
45
  * Safe to call multiple times — subsequent calls are no-ops.
36
46
  */
37
- export declare function initContainerCleanupHook(): ContainerCleanupHook;
47
+ export declare function initContainerCleanupHook(hqPath?: string): ContainerCleanupHook;
38
48
  /**
39
49
  * Stop the container cleanup hook (primarily for testing).
40
50
  */
@@ -1,29 +1,42 @@
1
1
  /**
2
- * Container Cleanup Lifecycle Hook
2
+ * Agent Cleanup Lifecycle Hook
3
3
  *
4
4
  * Subscribes to agent lifecycle events on the global EventBus and
5
- * automatically cleans up Docker containers when agents complete work.
5
+ * automatically runs the full cascading cleanup when agents stop.
6
6
  *
7
- * This is a triggered cleanup (not TTL-based): containers are removed
8
- * when the agent:stopped event fires or when stale executions are detected.
7
+ * This is Tier 1 of the cleanup system: event-driven cleanup that handles
8
+ * the ~90% case when agents stop normally (manual stop, completion, error).
9
+ *
10
+ * The cascade order follows the ticket spec:
11
+ * 1. CC/Claude session → 2. Tmux → 3. Container → 4. Worktree
12
+ * 5. Agent directory → 6. Git branch → 7. Execution records → 8. DB status
9
13
  */
10
14
  import { getEventBus } from '../events/event-bus.js';
11
15
  import { cleanupAgentContainer } from '../execution/container-cleanup.js';
16
+ import { executeCascade } from '../gc/cascade.js';
12
17
  /**
13
18
  * ContainerCleanupHook listens for agent completion events and
14
- * removes the associated Docker container.
19
+ * runs the full cascading cleanup.
15
20
  *
16
21
  * Cleanup is fire-and-forget: failures are logged but never block
17
22
  * the event emission chain.
18
23
  */
19
24
  export class ContainerCleanupHook {
20
25
  unsubscribers = [];
26
+ hqPath;
27
+ /**
28
+ * Set the HQ path for full cascade cleanup (branch deletion, DB ops).
29
+ * If not set, only container-level cleanup runs.
30
+ */
31
+ setHqPath(hqPath) {
32
+ this.hqPath = hqPath;
33
+ }
21
34
  /**
22
35
  * Start listening for agent lifecycle events.
23
36
  */
24
37
  start() {
25
38
  const bus = getEventBus();
26
- // Clean up container when an agent is stopped
39
+ // Clean up agent resources when stopped
27
40
  this.unsubscribers.push(bus.on('agent:stopped', (payload) => {
28
41
  this.handleAgentStopped(payload);
29
42
  }));
@@ -38,7 +51,7 @@ export class ContainerCleanupHook {
38
51
  this.unsubscribers = [];
39
52
  }
40
53
  /**
41
- * Handle agent:stopped by cleaning up the agent's container.
54
+ * Handle agent:stopped by running cascading cleanup.
42
55
  * Extracts agent name from the session ID or event data.
43
56
  */
44
57
  handleAgentStopped(eventData) {
@@ -48,15 +61,36 @@ export class ContainerCleanupHook {
48
61
  const sessionId = eventData.sessionId;
49
62
  if (!sessionId)
50
63
  return;
64
+ // Skip if this is from stale-cleanup to avoid recursive loops
65
+ const runner = eventData.runner;
66
+ if (runner === 'cascade-cleanup')
67
+ return;
51
68
  // Extract agent name from session ID
52
69
  // Format: TKT-123-implement-agent-name or similar
53
70
  const agentName = extractAgentNameFromSessionId(sessionId);
54
- if (!agentName)
71
+ if (!agentName) {
72
+ // Fall back to container-only cleanup if we can't extract agent name
73
+ cleanupAgentContainer(agentName ?? sessionId);
55
74
  return;
56
- cleanupAgentContainer(agentName);
75
+ }
76
+ // If we have hqPath, run the full cascade
77
+ if (this.hqPath) {
78
+ const target = {
79
+ agentName,
80
+ sessionId,
81
+ hqPath: this.hqPath,
82
+ };
83
+ // Try to resolve container ID from agent name
84
+ target.containerId = findContainerIdForAgent(agentName);
85
+ executeCascade(target, { execute: true });
86
+ }
87
+ else {
88
+ // Minimal cleanup: just remove the container (backward compatible)
89
+ cleanupAgentContainer(agentName);
90
+ }
57
91
  }
58
92
  catch {
59
- // Container cleanup errors are non-fatal
93
+ // Cleanup errors are non-fatal
60
94
  }
61
95
  }
62
96
  }
@@ -71,6 +105,20 @@ function extractAgentNameFromSessionId(sessionId) {
71
105
  const match = sessionId.match(/^(?:TKT-\d+|[A-Z]+-\d+)-\w+-(.+)$/);
72
106
  return match ? match[1] : null;
73
107
  }
108
+ /**
109
+ * Find the Docker container ID for an agent by name.
110
+ * Returns null if no container is found.
111
+ */
112
+ function findContainerIdForAgent(agentName) {
113
+ try {
114
+ const { execSync } = require('node:child_process');
115
+ const output = execSync(`docker ps -a --filter "name=prlt-agent-${agentName}" --format "{{.ID}}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 5000 }).trim();
116
+ return output || undefined;
117
+ }
118
+ catch {
119
+ return undefined;
120
+ }
121
+ }
74
122
  // =============================================================================
75
123
  // Singleton
76
124
  // =============================================================================
@@ -79,11 +127,16 @@ let _hook;
79
127
  * Initialize and start the container cleanup hook.
80
128
  * Safe to call multiple times — subsequent calls are no-ops.
81
129
  */
82
- export function initContainerCleanupHook() {
130
+ export function initContainerCleanupHook(hqPath) {
83
131
  if (!_hook) {
84
132
  _hook = new ContainerCleanupHook();
133
+ if (hqPath)
134
+ _hook.setHqPath(hqPath);
85
135
  _hook.start();
86
136
  }
137
+ else if (hqPath) {
138
+ _hook.setHqPath(hqPath);
139
+ }
87
140
  return _hook;
88
141
  }
89
142
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"container-cleanup-hook.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/container-cleanup-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AAEzE;;;;;;GAMG;AACH,MAAM,OAAO,oBAAoB;IACvB,aAAa,GAAsB,EAAE,CAAA;IAE7C;;OAEG;IACH,KAAK;QACH,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;QAEzB,8CAA8C;QAC9C,IAAI,CAAC,aAAa,CAAC,IAAI,CACrB,GAAG,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE;YAClC,IAAI,CAAC,kBAAkB,CAAC,OAA6C,CAAC,CAAA;QACxE,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAED;;OAEG;IACH,IAAI;QACF,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvC,KAAK,EAAE,CAAA;QACT,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;IACzB,CAAC;IAED;;;OAGG;IACK,kBAAkB,CAAC,SAAkC;QAC3D,IAAI,CAAC;YACH,2DAA2D;YAC3D,+CAA+C;YAC/C,MAAM,SAAS,GAAG,SAAS,CAAC,SAA+B,CAAA;YAC3D,IAAI,CAAC,SAAS;gBAAE,OAAM;YAEtB,qCAAqC;YACrC,kDAAkD;YAClD,MAAM,SAAS,GAAG,6BAA6B,CAAC,SAAS,CAAC,CAAA;YAC1D,IAAI,CAAC,SAAS;gBAAE,OAAM;YAEtB,qBAAqB,CAAC,SAAS,CAAC,CAAA;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,yCAAyC;QAC3C,CAAC;IACH,CAAC;CACF;AAED;;;;GAIG;AACH,SAAS,6BAA6B,CAAC,SAAiB;IACtD,qDAAqD;IACrD,iEAAiE;IACjE,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAA;IAClE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAChC,CAAC;AAED,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF,IAAI,KAAuC,CAAA;AAE3C;;;GAGG;AACH,MAAM,UAAU,wBAAwB;IACtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,oBAAoB,EAAE,CAAA;QAClC,KAAK,CAAC,KAAK,EAAE,CAAA;IACf,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB;IACtC,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,CAAC,IAAI,EAAE,CAAA;QACZ,KAAK,GAAG,SAAS,CAAA;IACnB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"container-cleanup-hook.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/container-cleanup-hook.ts"],"names":[],"mappings":"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"}
@@ -5,10 +5,30 @@
5
5
  * work lifecycle events fire. Each action type has its own execution logic.
6
6
  *
7
7
  * Shell commands receive event data as environment variables prefixed with
8
- * PRLT_HOOK_. Webhook actions POST event data as JSON. Log actions print
9
- * interpolated messages to stdout.
8
+ * PRLT_HOOK_. A PRLT_HOOK_JSON variable carries the full payload as valid
9
+ * JSON so hooks can parse it reliably. Webhook actions POST event data as
10
+ * JSON. Log actions print interpolated messages to stdout.
10
11
  */
11
12
  import type { WorkHookConfig, HookExecutionResult } from './types.js';
13
+ /**
14
+ * JSON replacer that converts Date objects to ISO-8601 strings.
15
+ * Prevents [object Object] or invalid serialisation for non-primitive values.
16
+ */
17
+ export declare function safeJsonReplacer(_key: string, value: unknown): unknown;
18
+ /**
19
+ * Safely serialise event data to a JSON string.
20
+ * Returns a valid JSON string even when the payload contains Date objects
21
+ * or other non-primitive values. On serialisation failure returns a
22
+ * minimal fallback so hooks always receive parseable JSON.
23
+ */
24
+ export declare function safeJsonStringify(eventName: string, eventData: Record<string, unknown>): string;
25
+ /**
26
+ * Build environment variables from event data for shell hook execution.
27
+ * All keys are uppercased and prefixed with PRLT_HOOK_.
28
+ *
29
+ * PRLT_HOOK_JSON contains the full event payload as valid JSON.
30
+ */
31
+ export declare function buildEnvVars(eventName: string, eventData: Record<string, unknown>): Record<string, string>;
12
32
  /**
13
33
  * Execute a single hook action and return the result.
14
34
  */
@@ -5,17 +5,45 @@
5
5
  * work lifecycle events fire. Each action type has its own execution logic.
6
6
  *
7
7
  * Shell commands receive event data as environment variables prefixed with
8
- * PRLT_HOOK_. Webhook actions POST event data as JSON. Log actions print
9
- * interpolated messages to stdout.
8
+ * PRLT_HOOK_. A PRLT_HOOK_JSON variable carries the full payload as valid
9
+ * JSON so hooks can parse it reliably. Webhook actions POST event data as
10
+ * JSON. Log actions print interpolated messages to stdout.
10
11
  */
11
12
  import { execSync } from 'node:child_process';
13
+ /**
14
+ * JSON replacer that converts Date objects to ISO-8601 strings.
15
+ * Prevents [object Object] or invalid serialisation for non-primitive values.
16
+ */
17
+ export function safeJsonReplacer(_key, value) {
18
+ if (value instanceof Date)
19
+ return value.toISOString();
20
+ return value;
21
+ }
22
+ /**
23
+ * Safely serialise event data to a JSON string.
24
+ * Returns a valid JSON string even when the payload contains Date objects
25
+ * or other non-primitive values. On serialisation failure returns a
26
+ * minimal fallback so hooks always receive parseable JSON.
27
+ */
28
+ export function safeJsonStringify(eventName, eventData) {
29
+ try {
30
+ return JSON.stringify({ event: eventName, ...eventData }, safeJsonReplacer);
31
+ }
32
+ catch {
33
+ // Fallback: emit at least the event name so consumers always get valid JSON
34
+ return JSON.stringify({ event: eventName, error: 'payload_serialization_failed' });
35
+ }
36
+ }
12
37
  /**
13
38
  * Build environment variables from event data for shell hook execution.
14
39
  * All keys are uppercased and prefixed with PRLT_HOOK_.
40
+ *
41
+ * PRLT_HOOK_JSON contains the full event payload as valid JSON.
15
42
  */
16
- function buildEnvVars(eventName, eventData) {
43
+ export function buildEnvVars(eventName, eventData) {
17
44
  const env = {
18
45
  PRLT_HOOK_EVENT: eventName,
46
+ PRLT_HOOK_JSON: safeJsonStringify(eventName, eventData),
19
47
  };
20
48
  for (const [key, value] of Object.entries(eventData)) {
21
49
  if (value === null || value === undefined)
@@ -24,6 +52,15 @@ function buildEnvVars(eventName, eventData) {
24
52
  if (value instanceof Date) {
25
53
  env[envKey] = value.toISOString();
26
54
  }
55
+ else if (typeof value === 'object') {
56
+ // Serialize objects/arrays as JSON instead of [object Object]
57
+ try {
58
+ env[envKey] = JSON.stringify(value, safeJsonReplacer);
59
+ }
60
+ catch {
61
+ env[envKey] = String(value);
62
+ }
63
+ }
27
64
  else {
28
65
  env[envKey] = String(value);
29
66
  }
@@ -63,16 +100,17 @@ export function executeHook(hook, eventName, eventData) {
63
100
  break;
64
101
  }
65
102
  case 'webhook': {
66
- // Fire-and-forget POST to the configured URL
103
+ // Fire-and-forget POST to the configured URL.
104
+ // Uses safeJsonReplacer so Date objects become ISO strings.
67
105
  const body = JSON.stringify({
68
106
  event: eventName,
69
107
  data: eventData,
70
108
  hook: { id: hook.id, name: hook.name },
71
109
  timestamp: new Date().toISOString(),
72
- });
73
- // Use synchronous fetch via execSync to keep it simple
74
- // This avoids async complexity in the event handler
75
- execSync(`curl -s -X POST -H "Content-Type: application/json" -d '${body.replace(/'/g, "'\\''")}' '${hook.actionValue}'`, { timeout: 10_000, stdio: 'pipe' });
110
+ }, safeJsonReplacer);
111
+ // Pass JSON via stdin to avoid shell-escaping issues that
112
+ // caused invalid JSON on abnormal termination (PRLT-1260).
113
+ execSync(`curl -s -X POST -H "Content-Type: application/json" -d @- '${hook.actionValue.replace(/'/g, "'\\''")}' `, { input: body, timeout: 10_000, stdio: ['pipe', 'pipe', 'pipe'] });
76
114
  break;
77
115
  }
78
116
  case 'log': {
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../src/lib/work-lifecycle/hooks/executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../src/lib/work-lifecycle/hooks/executor.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  * The single hook execution system for the entire application.
5
5
  * Subscribes to work lifecycle events on the global EventBus and
6
6
  * executes matching hook configurations from the database with
7
- * mode-aware behavior (auto/confirm/notify/off).
7
+ * mode-aware behavior (auto/confirm/notify/llm/human/off).
8
8
  *
9
9
  * Used by both the interactive CLI (with default auto mode) and
10
10
  * the orchestrate daemon (with full mode/callback support).
@@ -14,7 +14,8 @@
14
14
  * emission chain.
15
15
  */
16
16
  import type Database from 'better-sqlite3';
17
- import { type HookExecutionResult, type HookActionHandler, type WorkHookConfig } from './types.js';
17
+ import { type HookExecutionResult, type HookActionHandler, type WorkHookConfig, type LlmDecision } from './types.js';
18
+ import { type EscalationContext, type EscalationReason, type PendingLlmDecision, type PendingHumanEscalation } from '../../orchestrate/escalation.js';
18
19
  /**
19
20
  * Options for creating a HookManager.
20
21
  */
@@ -27,6 +28,25 @@ export interface HookManagerOptions {
27
28
  onConfirm?: (hookName: string, event: string, action: string) => Promise<boolean>;
28
29
  /** Callback for notifications (notify-mode hooks) */
29
30
  onNotify?: (hookName: string, event: string, action: string, result: HookExecutionResult) => void;
31
+ /**
32
+ * Callback for LLM-mode hooks (Tier 2).
33
+ * Receives escalation context, returns LLM decision: approve/deny/escalate.
34
+ * If not provided, LLM decisions are queued in pendingLlmDecisions.
35
+ */
36
+ onLlmDecision?: (context: EscalationContext) => Promise<LlmDecision>;
37
+ /**
38
+ * Callback for human-mode hooks (Tier 3).
39
+ * Called when a hook needs human approval — either directly (mode=human/confirm)
40
+ * or via escalation from LLM tier.
41
+ * Returns true to approve, false to deny.
42
+ * If not provided, human escalations are queued in pendingHumanEscalations.
43
+ */
44
+ onHumanEscalation?: (context: EscalationContext, reason: EscalationReason) => Promise<boolean>;
45
+ /**
46
+ * Timeout in ms for LLM decisions before auto-escalating to human.
47
+ * Defaults to DEFAULT_LLM_TIMEOUT_MS (5 minutes).
48
+ */
49
+ llmTimeoutMs?: number;
30
50
  /**
31
51
  * Built-in action handlers (e.g., merge-pr, spawn-agent).
32
52
  * When a hook's action resolves to a key in this map, the handler
@@ -53,8 +73,13 @@ export declare class HookManager {
53
73
  private log;
54
74
  private onConfirm?;
55
75
  private onNotify?;
76
+ private onLlmDecision?;
77
+ private onHumanEscalation?;
78
+ private llmTimeoutMs;
56
79
  private actionHandlers;
57
80
  private _pendingConfirmations;
81
+ private _pendingLlmDecisions;
82
+ private _pendingHumanEscalations;
58
83
  constructor(options: HookManagerOptions);
59
84
  /**
60
85
  * Start listening for hookable events on the global EventBus.
@@ -82,6 +107,40 @@ export declare class HookManager {
82
107
  * Deny a pending confirmation.
83
108
  */
84
109
  denyConfirmation(index: number): boolean;
110
+ /**
111
+ * Get pending LLM decisions for hooks in llm mode.
112
+ */
113
+ getPendingLlmDecisions(): PendingLlmDecision[];
114
+ /**
115
+ * Approve a pending LLM decision and execute it.
116
+ */
117
+ approveLlmDecision(index: number): Promise<HookExecutionResult | null>;
118
+ /**
119
+ * Deny a pending LLM decision.
120
+ */
121
+ denyLlmDecision(index: number): boolean;
122
+ /**
123
+ * Escalate a pending LLM decision to human tier.
124
+ * Removes from LLM queue and adds to human escalation queue.
125
+ */
126
+ escalateLlmDecision(index: number): boolean;
127
+ /**
128
+ * Check for timed-out LLM decisions and auto-escalate them to human tier.
129
+ * Returns the number of decisions that were escalated.
130
+ */
131
+ escalateTimedOutLlmDecisions(): number;
132
+ /**
133
+ * Get pending human escalations.
134
+ */
135
+ getPendingHumanEscalations(): PendingHumanEscalation[];
136
+ /**
137
+ * Approve a pending human escalation and execute it.
138
+ */
139
+ approveHumanEscalation(index: number): Promise<HookExecutionResult | null>;
140
+ /**
141
+ * Deny a pending human escalation.
142
+ */
143
+ denyHumanEscalation(index: number): boolean;
85
144
  /**
86
145
  * Build a context object from raw event data.
87
146
  * Normalizes common field names for built-in action handlers.
@@ -101,7 +160,7 @@ export declare class HookManager {
101
160
  static resolveActionName(hook: WorkHookConfig, knownActions?: Record<string, unknown>): string;
102
161
  /**
103
162
  * Handle an event by finding and executing all matching enabled hooks.
104
- * Supports mode-aware execution: auto, confirm, notify, off.
163
+ * Supports mode-aware execution: auto, confirm, notify, llm, human, off.
105
164
  */
106
165
  private handleEvent;
107
166
  /**