@proletariat/cli 0.3.102 → 0.3.103

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.
@@ -1,22 +1,61 @@
1
1
  /**
2
2
  * Work Lifecycle Hook Manager
3
3
  *
4
+ * The single hook execution system for the entire application.
4
5
  * Subscribes to work lifecycle events on the global EventBus and
5
- * executes matching hook configurations from the database.
6
+ * executes matching hook configurations from the database with
7
+ * mode-aware behavior (auto/confirm/notify/off).
6
8
  *
7
- * Hooks are fire-and-forget: execution failures are logged but never
8
- * block the caller or break the event emission chain.
9
+ * Used by both the interactive CLI (with default auto mode) and
10
+ * the orchestrate daemon (with full mode/callback support).
11
+ *
12
+ * Hooks are fire-and-forget when triggered via EventBus: execution
13
+ * failures are logged but never block the caller or break the event
14
+ * emission chain.
9
15
  */
10
16
  import type Database from 'better-sqlite3';
17
+ import { type HookExecutionResult, type HookActionHandler, type WorkHookConfig } from './types.js';
18
+ /**
19
+ * Options for creating a HookManager.
20
+ */
21
+ export interface HookManagerOptions {
22
+ /** Database connection */
23
+ db: Database.Database;
24
+ /** Logger function */
25
+ log?: (msg: string) => void;
26
+ /** Callback for confirm-mode hooks (returns true to approve) */
27
+ onConfirm?: (hookName: string, event: string, action: string) => Promise<boolean>;
28
+ /** Callback for notifications (notify-mode hooks) */
29
+ onNotify?: (hookName: string, event: string, action: string, result: HookExecutionResult) => void;
30
+ /**
31
+ * Built-in action handlers (e.g., merge-pr, spawn-agent).
32
+ * When a hook's action resolves to a key in this map, the handler
33
+ * is called instead of shell/webhook/log execution.
34
+ */
35
+ actionHandlers?: Record<string, HookActionHandler>;
36
+ }
37
+ interface PendingConfirmation {
38
+ hookName: string;
39
+ event: string;
40
+ action: string;
41
+ ctx: Record<string, unknown>;
42
+ config?: Record<string, unknown>;
43
+ }
11
44
  /**
12
45
  * HookManager loads hook configs from the database and subscribes to
13
46
  * the global EventBus. When a hookable event fires, it finds all
14
- * enabled hooks for that event and executes them.
47
+ * enabled hooks for that event and executes them with mode-aware behavior.
15
48
  */
16
49
  export declare class HookManager {
17
50
  private unsubscribers;
18
51
  private hookStorage;
19
- constructor(db: Database.Database);
52
+ private db;
53
+ private log;
54
+ private onConfirm?;
55
+ private onNotify?;
56
+ private actionHandlers;
57
+ private _pendingConfirmations;
58
+ constructor(options: HookManagerOptions);
20
59
  /**
21
60
  * Start listening for hookable events on the global EventBus.
22
61
  * For each event, looks up enabled hooks and executes them.
@@ -27,17 +66,63 @@ export declare class HookManager {
27
66
  */
28
67
  stop(): void;
29
68
  /**
30
- * Handle a hookable event by executing all matching enabled hooks.
31
- * Hook failures are swallowed to avoid breaking the event chain.
69
+ * Fire an event explicitly (used by orchestrate daemon and `prlt hook fire`).
70
+ * Returns the execution results for all matching hooks.
71
+ */
72
+ fireEvent(event: string, eventData: Record<string, unknown>): Promise<HookExecutionResult[]>;
73
+ /**
74
+ * Get pending confirmations for hooks in confirm mode.
75
+ */
76
+ getPendingConfirmations(): PendingConfirmation[];
77
+ /**
78
+ * Approve a pending confirmation and execute it.
79
+ */
80
+ approveConfirmation(index: number): Promise<HookExecutionResult | null>;
81
+ /**
82
+ * Deny a pending confirmation.
83
+ */
84
+ denyConfirmation(index: number): boolean;
85
+ /**
86
+ * Build a context object from raw event data.
87
+ * Normalizes common field names for built-in action handlers.
88
+ *
89
+ * Public so it can be tested in isolation.
90
+ */
91
+ static buildContext(eventName: string, data: Record<string, unknown>): Record<string, unknown>;
92
+ /**
93
+ * Resolve the action name from a hook config and a set of known action handlers.
94
+ *
95
+ * - If the action_value contains `--action <name>`, extracts the name
96
+ * - If the action_value is a known built-in action, uses it directly
97
+ * - Otherwise uses the raw action_value (shell command)
98
+ *
99
+ * Public so it can be tested in isolation.
100
+ */
101
+ static resolveActionName(hook: WorkHookConfig, knownActions?: Record<string, unknown>): string;
102
+ /**
103
+ * Handle an event by finding and executing all matching enabled hooks.
104
+ * Supports mode-aware execution: auto, confirm, notify, off.
32
105
  */
33
106
  private handleEvent;
107
+ /**
108
+ * Execute a hook action — either via a built-in handler or the standard executor.
109
+ */
110
+ private executeHookAction;
111
+ /**
112
+ * Execute an action by name (used for approved confirmations).
113
+ */
114
+ private executeActionByName;
34
115
  }
35
116
  /**
36
117
  * Initialize and start the hook manager.
37
118
  * Safe to call multiple times — subsequent calls are no-ops.
119
+ *
120
+ * When called with just a db (interactive CLI), hooks default to auto mode.
121
+ * Pass additional options for mode-aware execution (orchestrate daemon).
38
122
  */
39
- export declare function initHookManager(db: Database.Database): HookManager;
123
+ export declare function initHookManager(db: Database.Database, options?: Omit<HookManagerOptions, 'db'>): HookManager;
40
124
  /**
41
125
  * Stop the hook manager (primarily for testing).
42
126
  */
43
127
  export declare function stopHookManager(): void;
128
+ export {};
@@ -1,26 +1,47 @@
1
1
  /**
2
2
  * Work Lifecycle Hook Manager
3
3
  *
4
+ * The single hook execution system for the entire application.
4
5
  * Subscribes to work lifecycle events on the global EventBus and
5
- * executes matching hook configurations from the database.
6
+ * executes matching hook configurations from the database with
7
+ * mode-aware behavior (auto/confirm/notify/off).
6
8
  *
7
- * Hooks are fire-and-forget: execution failures are logged but never
8
- * block the caller or break the event emission chain.
9
+ * Used by both the interactive CLI (with default auto mode) and
10
+ * the orchestrate daemon (with full mode/callback support).
11
+ *
12
+ * Hooks are fire-and-forget when triggered via EventBus: execution
13
+ * failures are logged but never block the caller or break the event
14
+ * emission chain.
9
15
  */
16
+ import { execSync } from 'node:child_process';
10
17
  import { getEventBus } from '../../events/event-bus.js';
11
18
  import { WorkHookStorage } from './storage.js';
12
19
  import { executeHook } from './executor.js';
13
- import { HOOKABLE_EVENTS } from './types.js';
20
+ import { HOOKABLE_EVENTS, } from './types.js';
21
+ // =============================================================================
22
+ // Manager
23
+ // =============================================================================
14
24
  /**
15
25
  * HookManager loads hook configs from the database and subscribes to
16
26
  * the global EventBus. When a hookable event fires, it finds all
17
- * enabled hooks for that event and executes them.
27
+ * enabled hooks for that event and executes them with mode-aware behavior.
18
28
  */
19
29
  export class HookManager {
20
30
  unsubscribers = [];
21
31
  hookStorage;
22
- constructor(db) {
23
- this.hookStorage = new WorkHookStorage(db);
32
+ db;
33
+ log;
34
+ onConfirm;
35
+ onNotify;
36
+ actionHandlers;
37
+ _pendingConfirmations = [];
38
+ constructor(options) {
39
+ this.db = options.db;
40
+ this.hookStorage = new WorkHookStorage(options.db);
41
+ this.log = options.log ?? (() => { });
42
+ this.onConfirm = options.onConfirm;
43
+ this.onNotify = options.onNotify;
44
+ this.actionHandlers = options.actionHandlers ?? {};
24
45
  }
25
46
  /**
26
47
  * Start listening for hookable events on the global EventBus.
@@ -30,7 +51,7 @@ export class HookManager {
30
51
  const bus = getEventBus();
31
52
  for (const eventName of HOOKABLE_EVENTS) {
32
53
  this.unsubscribers.push(bus.on(eventName, (payload) => {
33
- this.handleEvent(eventName, payload);
54
+ void this.handleEvent(eventName, payload);
34
55
  }));
35
56
  }
36
57
  }
@@ -42,27 +63,231 @@ export class HookManager {
42
63
  unsub();
43
64
  }
44
65
  this.unsubscribers = [];
66
+ this._pendingConfirmations = [];
67
+ }
68
+ /**
69
+ * Fire an event explicitly (used by orchestrate daemon and `prlt hook fire`).
70
+ * Returns the execution results for all matching hooks.
71
+ */
72
+ async fireEvent(event, eventData) {
73
+ return this.handleEvent(event, eventData);
74
+ }
75
+ /**
76
+ * Get pending confirmations for hooks in confirm mode.
77
+ */
78
+ getPendingConfirmations() {
79
+ return [...this._pendingConfirmations];
80
+ }
81
+ /**
82
+ * Approve a pending confirmation and execute it.
83
+ */
84
+ async approveConfirmation(index) {
85
+ if (index < 0 || index >= this._pendingConfirmations.length)
86
+ return null;
87
+ const pending = this._pendingConfirmations.splice(index, 1)[0];
88
+ const result = this.executeActionByName(pending.action, pending.ctx, pending.config);
89
+ this.log(`[hooks] Approved: ${pending.hookName} → ${pending.action} (${result.success ? 'success' : 'failed'})`);
90
+ return result;
91
+ }
92
+ /**
93
+ * Deny a pending confirmation.
94
+ */
95
+ denyConfirmation(index) {
96
+ if (index < 0 || index >= this._pendingConfirmations.length)
97
+ return false;
98
+ const pending = this._pendingConfirmations.splice(index, 1)[0];
99
+ this.log(`[hooks] Denied: ${pending.hookName} → ${pending.action}`);
100
+ return true;
101
+ }
102
+ // ===========================================================================
103
+ // Testable Utilities (public for PRLT-1223 test suite)
104
+ // ===========================================================================
105
+ /**
106
+ * Build a context object from raw event data.
107
+ * Normalizes common field names for built-in action handlers.
108
+ *
109
+ * Public so it can be tested in isolation.
110
+ */
111
+ static buildContext(eventName, data) {
112
+ return {
113
+ event: eventName,
114
+ ticket: (data.ticketId ?? data.workItemId ?? data.ticket),
115
+ pr: (data.prNumber ?? data.pr),
116
+ branch: data.branch,
117
+ agent: (data.agentName ?? data.agent ?? data.sessionId),
118
+ container: data.containerId,
119
+ executionId: data.executionId,
120
+ prUrl: data.prUrl,
121
+ projectId: data.projectId,
122
+ ...data,
123
+ };
45
124
  }
46
125
  /**
47
- * Handle a hookable event by executing all matching enabled hooks.
48
- * Hook failures are swallowed to avoid breaking the event chain.
126
+ * Resolve the action name from a hook config and a set of known action handlers.
127
+ *
128
+ * - If the action_value contains `--action <name>`, extracts the name
129
+ * - If the action_value is a known built-in action, uses it directly
130
+ * - Otherwise uses the raw action_value (shell command)
131
+ *
132
+ * Public so it can be tested in isolation.
49
133
  */
50
- handleEvent(eventName, eventData) {
134
+ static resolveActionName(hook, knownActions = {}) {
135
+ // If the action_value contains --action, extract the action name
136
+ const actionMatch = hook.actionValue.match(/--action\s+(\S+)/);
137
+ if (actionMatch)
138
+ return actionMatch[1];
139
+ // If it's a known built-in action name directly
140
+ if (knownActions[hook.actionValue])
141
+ return hook.actionValue;
142
+ // Otherwise it's a raw shell command — use the action_value as-is
143
+ return hook.actionValue;
144
+ }
145
+ // ===========================================================================
146
+ // Private
147
+ // ===========================================================================
148
+ /**
149
+ * Handle an event by finding and executing all matching enabled hooks.
150
+ * Supports mode-aware execution: auto, confirm, notify, off.
151
+ */
152
+ async handleEvent(eventName, eventData) {
153
+ const results = [];
51
154
  try {
52
155
  const hooks = this.hookStorage.list({ event: eventName, enabled: true });
53
156
  if (hooks.length === 0)
54
- return;
157
+ return results;
158
+ // Build context from the payload
159
+ const ctx = HookManager.buildContext(eventName, eventData);
55
160
  for (const hook of hooks) {
56
- try {
57
- executeHook(hook, eventName, eventData);
161
+ const mode = hook.mode || 'auto';
162
+ const actionName = HookManager.resolveActionName(hook, this.actionHandlers);
163
+ // --- off: skip silently ---
164
+ if (mode === 'off') {
165
+ results.push({
166
+ hookId: hook.id,
167
+ hookName: hook.name,
168
+ action: actionName,
169
+ success: true,
170
+ durationMs: 0,
171
+ skipped: true,
172
+ });
173
+ continue;
174
+ }
175
+ // --- confirm: require approval ---
176
+ if (mode === 'confirm') {
177
+ if (this.onConfirm) {
178
+ const approved = await this.onConfirm(hook.name, eventName, actionName);
179
+ if (!approved) {
180
+ this.log(`[hooks] Skipped (not confirmed): ${hook.name} → ${actionName}`);
181
+ results.push({
182
+ hookId: hook.id,
183
+ hookName: hook.name,
184
+ action: actionName,
185
+ success: true,
186
+ durationMs: 0,
187
+ skipped: true,
188
+ });
189
+ continue;
190
+ }
191
+ // Approved — fall through to execution
192
+ }
193
+ else {
194
+ // No confirm handler — queue for later approval
195
+ this._pendingConfirmations.push({
196
+ hookName: hook.name,
197
+ event: eventName,
198
+ action: actionName,
199
+ ctx,
200
+ config: hook.config ?? undefined,
201
+ });
202
+ this.log(`[hooks] Queued for confirmation: ${hook.name} → ${actionName}`);
203
+ results.push({
204
+ hookId: hook.id,
205
+ hookName: hook.name,
206
+ action: actionName,
207
+ success: true,
208
+ durationMs: 0,
209
+ awaitingConfirmation: true,
210
+ });
211
+ continue;
212
+ }
58
213
  }
59
- catch {
60
- // Hook execution errors are non-fatal
214
+ // --- auto / notify / confirmed: execute ---
215
+ const result = this.executeHookAction(hook, eventName, eventData, ctx);
216
+ results.push(result);
217
+ this.log(`[hooks] ${hook.name} → ${actionName}: ${result.success ? 'success' : `failed: ${result.error}`} (${result.durationMs}ms)`);
218
+ // For notify mode, also fire the notification callback
219
+ if (mode === 'notify' && this.onNotify) {
220
+ this.onNotify(hook.name, eventName, actionName, result);
61
221
  }
62
222
  }
63
223
  }
64
- catch {
65
- // Storage errors are non-fatal
224
+ catch (err) {
225
+ this.log(`[hooks] Error handling event ${eventName}: ${err instanceof Error ? err.message : String(err)}`);
226
+ }
227
+ return results;
228
+ }
229
+ /**
230
+ * Execute a hook action — either via a built-in handler or the standard executor.
231
+ */
232
+ executeHookAction(hook, eventName, eventData, ctx) {
233
+ const actionName = HookManager.resolveActionName(hook, this.actionHandlers);
234
+ // Try built-in action handler first
235
+ if (this.actionHandlers[actionName]) {
236
+ const handlerResult = this.actionHandlers[actionName](ctx, hook.config ?? undefined);
237
+ return {
238
+ hookId: hook.id,
239
+ hookName: hook.name,
240
+ action: handlerResult.action,
241
+ success: handlerResult.success,
242
+ error: handlerResult.error,
243
+ durationMs: handlerResult.durationMs,
244
+ skipped: handlerResult.skipped,
245
+ };
246
+ }
247
+ // For shell/webhook/log hooks, use the standard executor
248
+ const result = executeHook(hook, eventName, eventData);
249
+ return {
250
+ ...result,
251
+ action: actionName,
252
+ };
253
+ }
254
+ /**
255
+ * Execute an action by name (used for approved confirmations).
256
+ */
257
+ executeActionByName(actionName, ctx, config) {
258
+ // Try built-in action handler first
259
+ if (this.actionHandlers[actionName]) {
260
+ const handlerResult = this.actionHandlers[actionName](ctx, config);
261
+ return {
262
+ hookId: '',
263
+ hookName: '',
264
+ action: handlerResult.action,
265
+ success: handlerResult.success,
266
+ error: handlerResult.error,
267
+ durationMs: handlerResult.durationMs,
268
+ skipped: handlerResult.skipped,
269
+ };
270
+ }
271
+ // Fallback to shell execution
272
+ const start = Date.now();
273
+ try {
274
+ const env = {
275
+ ...process.env,
276
+ PRLT_HOOK_EVENT: ctx.event ?? '',
277
+ PRLT_HOOK_TICKET: ctx.ticket ?? '',
278
+ PRLT_HOOK_PR: ctx.pr ? String(ctx.pr) : '',
279
+ PRLT_HOOK_BRANCH: ctx.branch ?? '',
280
+ PRLT_HOOK_AGENT: ctx.agent ?? '',
281
+ };
282
+ execSync(actionName, { env, timeout: 30_000, stdio: 'pipe' });
283
+ return { hookId: '', hookName: '', action: actionName, success: true, durationMs: Date.now() - start };
284
+ }
285
+ catch (err) {
286
+ return {
287
+ hookId: '', hookName: '', action: actionName, success: false,
288
+ error: err instanceof Error ? err.message : String(err),
289
+ durationMs: Date.now() - start,
290
+ };
66
291
  }
67
292
  }
68
293
  }
@@ -73,10 +298,13 @@ let _manager;
73
298
  /**
74
299
  * Initialize and start the hook manager.
75
300
  * Safe to call multiple times — subsequent calls are no-ops.
301
+ *
302
+ * When called with just a db (interactive CLI), hooks default to auto mode.
303
+ * Pass additional options for mode-aware execution (orchestrate daemon).
76
304
  */
77
- export function initHookManager(db) {
305
+ export function initHookManager(db, options) {
78
306
  if (!_manager) {
79
- _manager = new HookManager(db);
307
+ _manager = new HookManager({ db, ...options });
80
308
  _manager.start();
81
309
  }
82
310
  return _manager;
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../../src/lib/work-lifecycle/hooks/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAsB,MAAM,YAAY,CAAA;AAEhE;;;;GAIG;AACH,MAAM,OAAO,WAAW;IACd,aAAa,GAAsB,EAAE,CAAA;IACrC,WAAW,CAAiB;IAEpC,YAAY,EAAqB;QAC/B,IAAI,CAAC,WAAW,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,CAAA;IAC5C,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;QAEzB,KAAK,MAAM,SAAS,IAAI,eAAe,EAAE,CAAC;YACxC,IAAI,CAAC,aAAa,CAAC,IAAI,CACrB,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;gBAC5B,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,OAA6C,CAAC,CAAA;YAC5E,CAAC,CAAC,CACH,CAAA;QACH,CAAC;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,WAAW,CAAC,SAAwB,EAAE,SAAkC;QAC9E,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;YACxE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAM;YAE9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;gBACzC,CAAC;gBAAC,MAAM,CAAC;oBACP,sCAAsC;gBACxC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;QACjC,CAAC;IACH,CAAC;CACF;AAED,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF,IAAI,QAAiC,CAAA;AAErC;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,EAAqB;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,IAAI,WAAW,CAAC,EAAE,CAAC,CAAA;QAC9B,QAAQ,CAAC,KAAK,EAAE,CAAA;IAClB,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,EAAE,CAAA;QACf,QAAQ,GAAG,SAAS,CAAA;IACtB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../../src/lib/work-lifecycle/hooks/manager.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,7 @@ export declare class WorkHookStorage {
24
24
  constructor(db: Database.Database);
25
25
  /**
26
26
  * List all hooks, optionally filtered by event name or enabled status.
27
+ * Returns hooks ordered by priority (ascending), then creation time.
27
28
  */
28
29
  list(options?: {
29
30
  event?: HookableEvent;
@@ -36,6 +36,15 @@ export function ensureHooksTable(db) {
36
36
  * Convert a database row to a WorkHookConfig.
37
37
  */
38
38
  function rowToConfig(row) {
39
+ let config = null;
40
+ if (row.config) {
41
+ try {
42
+ config = JSON.parse(row.config);
43
+ }
44
+ catch {
45
+ // Invalid JSON — ignore
46
+ }
47
+ }
39
48
  return {
40
49
  id: row.id,
41
50
  name: row.name,
@@ -45,6 +54,9 @@ function rowToConfig(row) {
45
54
  enabled: row.enabled === 1,
46
55
  description: row.description,
47
56
  createdAt: row.created_at,
57
+ mode: row.mode || 'auto',
58
+ priority: row.priority ?? 0,
59
+ config,
48
60
  };
49
61
  }
50
62
  /**
@@ -58,21 +70,31 @@ export class WorkHookStorage {
58
70
  }
59
71
  /**
60
72
  * List all hooks, optionally filtered by event name or enabled status.
73
+ * Returns hooks ordered by priority (ascending), then creation time.
61
74
  */
62
75
  list(options) {
63
- let sql = `SELECT * FROM ${HOOKS_TABLE} WHERE 1=1`;
64
76
  const params = [];
77
+ let where = ' WHERE 1=1';
65
78
  if (options?.event) {
66
- sql += ' AND event = ?';
79
+ where += ' AND event = ?';
67
80
  params.push(options.event);
68
81
  }
69
82
  if (options?.enabled !== undefined) {
70
- sql += ' AND enabled = ?';
83
+ where += ' AND enabled = ?';
71
84
  params.push(options.enabled ? 1 : 0);
72
85
  }
73
- sql += ' ORDER BY created_at ASC';
74
- const rows = this.db.prepare(sql).all(...params);
75
- return rows.map(rowToConfig);
86
+ // Try extended query with mode/priority/config columns first
87
+ try {
88
+ const sql = `SELECT id, name, event, action_type, action_value, enabled, description, created_at, mode, priority, config FROM ${HOOKS_TABLE}${where} ORDER BY priority ASC, created_at ASC`;
89
+ const rows = this.db.prepare(sql).all(...params);
90
+ return rows.map(rowToConfig);
91
+ }
92
+ catch {
93
+ // Fallback without mode/priority/config (pre-migration)
94
+ const sql = `SELECT id, name, event, action_type, action_value, enabled, description, created_at FROM ${HOOKS_TABLE}${where} ORDER BY created_at ASC`;
95
+ const rows = this.db.prepare(sql).all(...params);
96
+ return rows.map(rowToConfig);
97
+ }
76
98
  }
77
99
  /**
78
100
  * Get a single hook by ID.
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../src/lib/work-lifecycle/hooks/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAIxC,iCAAiC;AACjC,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAA;AAE3C,qCAAqC;AACrC,MAAM,CAAC,MAAM,kBAAkB,GAAG;+BACH,WAAW;;;;;;;;;;CAUzC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;2DAC0B,WAAW;6DACT,WAAW;CACvE,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAqB;IACpD,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAC3B,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;AAC5B,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,GAAgB;IACnC,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,KAAK,EAAE,GAAG,CAAC,KAAsB;QACjC,UAAU,EAAE,GAAG,CAAC,WAA6B;QAC7C,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,CAAC;QAC1B,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,eAAe;IACN;IAApB,YAAoB,EAAqB;QAArB,OAAE,GAAF,EAAE,CAAmB;QACvC,gBAAgB,CAAC,EAAE,CAAC,CAAA;IACtB,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,OAAsD;QACzD,IAAI,GAAG,GAAG,iBAAiB,WAAW,YAAY,CAAA;QAClD,MAAM,MAAM,GAAc,EAAE,CAAA;QAE5B,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;YACnB,GAAG,IAAI,gBAAgB,CAAA;YACvB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC5B,CAAC;QACD,IAAI,OAAO,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;YACnC,GAAG,IAAI,kBAAkB,CAAA;YACzB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACtC,CAAC;QAED,GAAG,IAAI,0BAA0B,CAAA;QAEjC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAkB,CAAA;QACjE,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IAC9B,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,EAAU;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iBAAiB,WAAW,eAAe,CAAC,CAAC,GAAG,CAAC,EAAE,CAA4B,CAAA;QAC3G,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACtC,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,IAAY;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iBAAiB,WAAW,iBAAiB,CAAC,CAAC,GAAG,CAAC,IAAI,CAA4B,CAAA;QAC/G,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACtC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAMN;QACC,MAAM,EAAE,GAAG,UAAU,EAAE,CAAA;QACvB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;oBACA,WAAW;;KAE1B,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,CAAA;QAExG,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,CAAE,CAAA;IAC1B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,EAAU;QACf,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,eAAe,WAAW,eAAe,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACjF,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAA;IAC3B,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,EAAU,EAAE,OAAgB;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,WAAW,+BAA+B,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAC7G,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAA;IAC3B,CAAC;CACF"}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../src/lib/work-lifecycle/hooks/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAIxC,iCAAiC;AACjC,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAA;AAE3C,qCAAqC;AACrC,MAAM,CAAC,MAAM,kBAAkB,GAAG;+BACH,WAAW;;;;;;;;;;CAUzC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;2DAC0B,WAAW;6DACT,WAAW;CACvE,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAqB;IACpD,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAC3B,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;AAC5B,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,GAAgB;IACnC,IAAI,MAAM,GAAmC,IAAI,CAAA;IACjD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAA4B,CAAA;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC;IAED,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,KAAK,EAAE,GAAG,CAAC,KAAsB;QACjC,UAAU,EAAE,GAAG,CAAC,WAA6B;QAC7C,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,CAAC;QAC1B,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,IAAI,EAAG,GAAG,CAAC,IAAiB,IAAI,MAAM;QACtC,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,CAAC;QAC3B,MAAM;KACP,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,eAAe;IACN;IAApB,YAAoB,EAAqB;QAArB,OAAE,GAAF,EAAE,CAAmB;QACvC,gBAAgB,CAAC,EAAE,CAAC,CAAA;IACtB,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,OAAsD;QACzD,MAAM,MAAM,GAAc,EAAE,CAAA;QAC5B,IAAI,KAAK,GAAG,YAAY,CAAA;QAExB,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;YACnB,KAAK,IAAI,gBAAgB,CAAA;YACzB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC5B,CAAC;QACD,IAAI,OAAO,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;YACnC,KAAK,IAAI,kBAAkB,CAAA;YAC3B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACtC,CAAC;QAED,6DAA6D;QAC7D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,oHAAoH,WAAW,GAAG,KAAK,wCAAwC,CAAA;YAC3L,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAkB,CAAA;YACjE,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;YACxD,MAAM,GAAG,GAAG,4FAA4F,WAAW,GAAG,KAAK,0BAA0B,CAAA;YACrJ,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAkB,CAAA;YACjE,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,EAAU;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iBAAiB,WAAW,eAAe,CAAC,CAAC,GAAG,CAAC,EAAE,CAA4B,CAAA;QAC3G,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACtC,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,IAAY;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iBAAiB,WAAW,iBAAiB,CAAC,CAAC,GAAG,CAAC,IAAI,CAA4B,CAAA;QAC/G,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACtC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAMN;QACC,MAAM,EAAE,GAAG,UAAU,EAAE,CAAA;QACvB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;oBACA,WAAW;;KAE1B,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,CAAA;QAExG,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,CAAE,CAAA;IAC1B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,EAAU;QACf,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,eAAe,WAAW,eAAe,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACjF,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAA;IAC3B,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,EAAU,EAAE,OAAgB;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,WAAW,+BAA+B,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAC7G,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAA;IAC3B,CAAC;CACF"}
@@ -22,6 +22,17 @@ export declare const HOOKABLE_EVENTS: HookableEvent[];
22
22
  * - log: Write a message to stdout (useful for notifications/debugging)
23
23
  */
24
24
  export type HookActionType = 'shell' | 'webhook' | 'log';
25
+ /**
26
+ * Automation mode for a hook.
27
+ *
28
+ * - auto: fires immediately, no human needed
29
+ * - confirm: pauses, waits for approval before executing
30
+ * - notify: fires immediately but also sends a notification
31
+ * - off: disabled, skipped silently
32
+ */
33
+ export type HookMode = 'auto' | 'confirm' | 'notify' | 'off';
34
+ /** All valid hook modes. */
35
+ export declare const HOOK_MODES: HookMode[];
25
36
  /**
26
37
  * Persisted hook configuration stored in the database.
27
38
  */
@@ -42,6 +53,12 @@ export interface WorkHookConfig {
42
53
  description: string | null;
43
54
  /** When the hook was created */
44
55
  createdAt: string;
56
+ /** Automation mode (auto/confirm/notify/off) */
57
+ mode: HookMode;
58
+ /** Execution priority (lower = higher priority) */
59
+ priority: number;
60
+ /** Optional JSON config for built-in actions */
61
+ config: Record<string, unknown> | null;
45
62
  }
46
63
  /**
47
64
  * Row shape from the database (snake_case columns).
@@ -55,15 +72,35 @@ export interface WorkHookRow {
55
72
  enabled: number;
56
73
  description: string | null;
57
74
  created_at: string;
75
+ mode: string | null;
76
+ priority: number | null;
77
+ config: string | null;
58
78
  }
79
+ /**
80
+ * Handler function for built-in actions injected into HookManager.
81
+ * Receives event context and optional per-hook config, returns an execution result.
82
+ */
83
+ export type HookActionHandler = (ctx: Record<string, unknown>, config?: Record<string, unknown>) => {
84
+ action: string;
85
+ success: boolean;
86
+ error?: string;
87
+ durationMs: number;
88
+ skipped?: boolean;
89
+ };
59
90
  /**
60
91
  * Result of executing a single hook.
61
92
  */
62
93
  export interface HookExecutionResult {
63
94
  hookId: string;
64
95
  hookName: string;
96
+ /** The resolved action name (built-in action or raw command) */
97
+ action: string;
65
98
  success: boolean;
66
99
  error?: string;
67
100
  /** Duration in ms */
68
101
  durationMs: number;
102
+ /** True when hook was skipped (mode=off or confirm denied) */
103
+ skipped?: boolean;
104
+ /** True when hook is queued for confirmation */
105
+ awaitingConfirmation?: boolean;
69
106
  }
@@ -26,4 +26,6 @@ export const HOOKABLE_EVENTS = [
26
26
  'on_agent_idle',
27
27
  'on_version_published',
28
28
  ];
29
+ /** All valid hook modes. */
30
+ export const HOOK_MODES = ['auto', 'confirm', 'notify', 'off'];
29
31
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/lib/work-lifecycle/hooks/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA+BH,+CAA+C;AAC/C,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C,cAAc;IACd,qBAAqB;IACrB,iBAAiB;IACjB,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,eAAe;IACf,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,mBAAmB;IACnB,iBAAiB;IACjB,kBAAkB;IAClB,eAAe;IACf,oBAAoB;IACpB,eAAe;IACf,sBAAsB;CACvB,CAAA"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/lib/work-lifecycle/hooks/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA+BH,+CAA+C;AAC/C,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C,cAAc;IACd,qBAAqB;IACrB,iBAAiB;IACjB,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,eAAe;IACf,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,mBAAmB;IACnB,iBAAiB;IACjB,kBAAkB;IAClB,eAAe;IACf,oBAAoB;IACpB,eAAe;IACf,sBAAsB;CACvB,CAAA;AAqBD,4BAA4B;AAC5B,MAAM,CAAC,MAAM,UAAU,GAAe,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA"}
@@ -7,7 +7,8 @@
7
7
  */
8
8
  export type { WorkEventSource, WorkStartedEvent, WorkStatusChangedEvent, WorkPRCreatedEvent, WorkCompletedEvent, } from './events.js';
9
9
  export { WorkLifecycleAdapter, initWorkLifecycleAdapter, stopWorkLifecycleAdapter, } from './adapter.js';
10
- export { initHookManager, stopHookManager, } from './hooks/index.js';
10
+ export { initHookManager, stopHookManager, HookManager, } from './hooks/index.js';
11
+ export type { HookManagerOptions } from './hooks/index.js';
11
12
  export { handlePostExecutionTransition, type PostExecutionContext, type PostExecutionResult, } from './post-execution.js';
12
13
  export { validateCommits, tryValidateCommits, type CommitValidationResult, } from '../execution/commit-validation.js';
13
14
  export { WorkflowRuleEvaluator, initWorkflowRuleEvaluator, stopWorkflowRuleEvaluator, } from './rule-evaluator.js';