@proletariat/cli 0.3.71 → 0.3.72
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.
- package/dist/commands/action/create.d.ts +6 -2
- package/dist/commands/action/create.js +107 -40
- package/dist/commands/action/create.js.map +1 -1
- package/dist/commands/action/list.d.ts +1 -1
- package/dist/commands/action/list.js +12 -10
- package/dist/commands/action/list.js.map +1 -1
- package/dist/commands/action/run.js +2 -2
- package/dist/commands/action/run.js.map +1 -1
- package/dist/commands/action/show.js +24 -4
- package/dist/commands/action/show.js.map +1 -1
- package/dist/commands/action/update.d.ts +6 -2
- package/dist/commands/action/update.js +130 -52
- package/dist/commands/action/update.js.map +1 -1
- package/dist/commands/work/ready.js +4 -2
- package/dist/commands/work/ready.js.map +1 -1
- package/dist/commands/work/spawn.js +2 -2
- package/dist/commands/work/spawn.js.map +1 -1
- package/dist/commands/work/start.js +67 -23
- package/dist/commands/work/start.js.map +1 -1
- package/dist/commands/workflow/setup.d.ts +24 -0
- package/dist/commands/workflow/setup.js +346 -0
- package/dist/commands/workflow/setup.js.map +1 -0
- package/dist/commands/workflow-rule/create.d.ts +19 -0
- package/dist/commands/workflow-rule/create.js +140 -0
- package/dist/commands/workflow-rule/create.js.map +1 -0
- package/dist/commands/workflow-rule/delete.d.ts +18 -0
- package/dist/commands/workflow-rule/delete.js +72 -0
- package/dist/commands/workflow-rule/delete.js.map +1 -0
- package/dist/commands/workflow-rule/index.d.ts +16 -0
- package/dist/commands/workflow-rule/index.js +83 -0
- package/dist/commands/workflow-rule/index.js.map +1 -0
- package/dist/commands/workflow-rule/list.d.ts +17 -0
- package/dist/commands/workflow-rule/list.js +72 -0
- package/dist/commands/workflow-rule/list.js.map +1 -0
- package/dist/commands/workflow-rule/update.d.ts +22 -0
- package/dist/commands/workflow-rule/update.js +84 -0
- package/dist/commands/workflow-rule/update.js.map +1 -0
- package/dist/hooks/init.js +2 -4
- package/dist/hooks/init.js.map +1 -1
- package/dist/lib/database/drizzle-schema.d.ts +269 -4
- package/dist/lib/database/drizzle-schema.js +22 -2
- package/dist/lib/database/drizzle-schema.js.map +1 -1
- package/dist/lib/database/migrations/0003_actions_redesign.d.ts +15 -0
- package/dist/lib/database/migrations/0003_actions_redesign.js +105 -0
- package/dist/lib/database/migrations/0003_actions_redesign.js.map +1 -0
- package/dist/lib/database/migrations/0004_workflow_rules.d.ts +2 -0
- package/dist/lib/database/migrations/0004_workflow_rules.js +25 -0
- package/dist/lib/database/migrations/0004_workflow_rules.js.map +1 -0
- package/dist/lib/database/migrations/index.js +4 -0
- package/dist/lib/database/migrations/index.js.map +1 -1
- package/dist/lib/events/events.d.ts +13 -1
- package/dist/lib/execution/storage.d.ts +7 -1
- package/dist/lib/execution/storage.js +14 -6
- package/dist/lib/execution/storage.js.map +1 -1
- package/dist/lib/pmo/schema.d.ts +3 -1
- package/dist/lib/pmo/schema.js +25 -3
- package/dist/lib/pmo/schema.js.map +1 -1
- package/dist/lib/pmo/storage/actions.d.ts +5 -3
- package/dist/lib/pmo/storage/actions.js +89 -23
- package/dist/lib/pmo/storage/actions.js.map +1 -1
- package/dist/lib/pmo/storage/base.d.ts +5 -0
- package/dist/lib/pmo/storage/base.js +203 -20
- package/dist/lib/pmo/storage/base.js.map +1 -1
- package/dist/lib/pmo/storage/index.d.ts +9 -2
- package/dist/lib/pmo/storage/index.js +28 -3
- package/dist/lib/pmo/storage/index.js.map +1 -1
- package/dist/lib/pmo/storage/types.d.ts +19 -2
- package/dist/lib/pmo/storage/workflow-rules.d.ts +35 -0
- package/dist/lib/pmo/storage/workflow-rules.js +183 -0
- package/dist/lib/pmo/storage/workflow-rules.js.map +1 -0
- package/dist/lib/pmo/sync-manager.js +6 -0
- package/dist/lib/pmo/sync-manager.js.map +1 -1
- package/dist/lib/pmo/types.d.ts +59 -4
- package/dist/lib/pmo/types.js.map +1 -1
- package/dist/lib/telemetry/analytics.d.ts +25 -7
- package/dist/lib/telemetry/analytics.js +123 -58
- package/dist/lib/telemetry/analytics.js.map +1 -1
- package/dist/lib/work-lifecycle/action-chaining.d.ts +61 -0
- package/dist/lib/work-lifecycle/action-chaining.js +211 -0
- package/dist/lib/work-lifecycle/action-chaining.js.map +1 -0
- package/dist/lib/work-lifecycle/index.d.ts +3 -0
- package/dist/lib/work-lifecycle/index.js +3 -0
- package/dist/lib/work-lifecycle/index.js.map +1 -1
- package/dist/lib/work-lifecycle/post-execution.d.ts +54 -0
- package/dist/lib/work-lifecycle/post-execution.js +68 -0
- package/dist/lib/work-lifecycle/post-execution.js.map +1 -0
- package/dist/lib/work-lifecycle/rule-evaluator.d.ts +38 -0
- package/dist/lib/work-lifecycle/rule-evaluator.js +102 -0
- package/dist/lib/work-lifecycle/rule-evaluator.js.map +1 -0
- package/oclif.manifest.json +3198 -2707
- package/package.json +1 -1
|
@@ -12,7 +12,14 @@
|
|
|
12
12
|
* Privacy:
|
|
13
13
|
* - Anonymous machine ID (UUID) stored in ~/.proletariat/telemetry.json
|
|
14
14
|
* - No file paths, usernames, or ticket content ever sent
|
|
15
|
-
* - Events are
|
|
15
|
+
* - Events are written to a local queue file and flushed on the next run
|
|
16
|
+
*
|
|
17
|
+
* Write-ahead log:
|
|
18
|
+
* - trackEvent() writes events to ~/.proletariat/telemetry-queue.json synchronously
|
|
19
|
+
* - On the next command run (or during this run's shutdown if Statsig initialized in time),
|
|
20
|
+
* queued events are flushed to Statsig and the queue is cleared
|
|
21
|
+
* - Events are delayed by at most one command invocation — acceptable for analytics
|
|
22
|
+
* - This adds zero latency and ensures no events are lost regardless of Statsig init timing
|
|
16
23
|
*/
|
|
17
24
|
import * as fs from 'node:fs';
|
|
18
25
|
import * as path from 'node:path';
|
|
@@ -20,16 +27,13 @@ import * as crypto from 'node:crypto';
|
|
|
20
27
|
import { getMachineConfigDir, ensureMachineConfigDir } from '../machine-config.js';
|
|
21
28
|
// Statsig client SDK key (public — safe to embed in open source repos)
|
|
22
29
|
const STATSIG_CLIENT_KEY = 'client-kvxMxRhn9NFSmH8orl7e2W9nYTfWVS7Kjf7yRTdIecc';
|
|
23
|
-
//
|
|
24
|
-
const
|
|
30
|
+
// Cap the queue size to prevent unbounded growth if events never flush
|
|
31
|
+
const MAX_QUEUE_SIZE = 1000;
|
|
25
32
|
// Module-level state
|
|
26
33
|
let statsigClient = null;
|
|
27
34
|
let telemetryConfig = null;
|
|
28
35
|
let cliVersion = null;
|
|
29
36
|
let initPromise = null;
|
|
30
|
-
// Events logged before the Statsig client finishes initializing.
|
|
31
|
-
// These are replayed once init completes (in shutdownAnalytics).
|
|
32
|
-
let pendingEvents = [];
|
|
33
37
|
// ─── Telemetry Config ────────────────────────────────────────────────────────
|
|
34
38
|
function getTelemetryConfigPath() {
|
|
35
39
|
return path.join(getMachineConfigDir(), 'telemetry.json');
|
|
@@ -158,16 +162,106 @@ function showTelemetryNotice() {
|
|
|
158
162
|
export function getMachineId() {
|
|
159
163
|
return readTelemetryConfig().machineId;
|
|
160
164
|
}
|
|
165
|
+
// ─── Event Queue (Write-Ahead Log) ───────────────────────────────────────────
|
|
166
|
+
function getQueuePath() {
|
|
167
|
+
return path.join(getMachineConfigDir(), 'telemetry-queue.json');
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Append an event to the on-disk queue. Synchronous — adds zero async latency.
|
|
171
|
+
*/
|
|
172
|
+
function writeEventToQueue(event) {
|
|
173
|
+
try {
|
|
174
|
+
ensureMachineConfigDir();
|
|
175
|
+
const queuePath = getQueuePath();
|
|
176
|
+
let queue = [];
|
|
177
|
+
if (fs.existsSync(queuePath)) {
|
|
178
|
+
try {
|
|
179
|
+
const raw = fs.readFileSync(queuePath, 'utf-8');
|
|
180
|
+
const parsed = JSON.parse(raw);
|
|
181
|
+
if (Array.isArray(parsed))
|
|
182
|
+
queue = parsed;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// Corrupted file — start fresh
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
queue.push(event);
|
|
189
|
+
// Cap queue size to prevent unbounded growth
|
|
190
|
+
if (queue.length > MAX_QUEUE_SIZE) {
|
|
191
|
+
queue = queue.slice(queue.length - MAX_QUEUE_SIZE);
|
|
192
|
+
}
|
|
193
|
+
// Atomic write via temp file + rename
|
|
194
|
+
const tempPath = `${queuePath}.tmp.${process.pid}`;
|
|
195
|
+
fs.writeFileSync(tempPath, JSON.stringify(queue), 'utf-8');
|
|
196
|
+
fs.renameSync(tempPath, queuePath);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Never let queue errors affect the CLI
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Atomically read and clear the queue file.
|
|
204
|
+
* Uses rename to claim the file so concurrent processes don't double-send.
|
|
205
|
+
*/
|
|
206
|
+
function readAndClearQueue() {
|
|
207
|
+
const queuePath = getQueuePath();
|
|
208
|
+
const claimPath = `${queuePath}.flush.${process.pid}`;
|
|
209
|
+
try {
|
|
210
|
+
// Atomic rename — only one process can claim the file
|
|
211
|
+
fs.renameSync(queuePath, claimPath);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
// File doesn't exist or another process already claimed it
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
const raw = fs.readFileSync(claimPath, 'utf-8');
|
|
219
|
+
const parsed = JSON.parse(raw);
|
|
220
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return [];
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
try {
|
|
227
|
+
fs.unlinkSync(claimPath);
|
|
228
|
+
}
|
|
229
|
+
catch { /* ignore */ }
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Flush queued events to Statsig. Requires an initialized Statsig client.
|
|
234
|
+
* Called during shutdown or at the start of the next command run.
|
|
235
|
+
*/
|
|
236
|
+
export function flushQueuedEvents() {
|
|
237
|
+
if (!statsigClient)
|
|
238
|
+
return;
|
|
239
|
+
const events = readAndClearQueue();
|
|
240
|
+
for (const event of events) {
|
|
241
|
+
try {
|
|
242
|
+
statsigClient.logEvent(event.name, event.value, event.metadata);
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
// Drop individual events silently
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
161
249
|
// ─── Statsig Client ──────────────────────────────────────────────────────────
|
|
162
250
|
/**
|
|
163
|
-
* Initialize the Statsig SDK
|
|
251
|
+
* Initialize the Statsig SDK and flush any queued events from previous runs.
|
|
252
|
+
* Called from the init hook. The Statsig init is fire-and-forget — event
|
|
253
|
+
* tracking does not depend on it (events go to the disk queue instead).
|
|
254
|
+
* Statsig is still needed for feature flags.
|
|
255
|
+
*
|
|
164
256
|
* No-op if telemetry is disabled.
|
|
165
257
|
*/
|
|
166
258
|
export function initAnalytics(version) {
|
|
167
259
|
cliVersion = version;
|
|
168
260
|
if (!isTelemetryEnabled())
|
|
169
|
-
return
|
|
261
|
+
return;
|
|
170
262
|
showTelemetryNotice();
|
|
263
|
+
// Start Statsig init in background — not needed for event logging,
|
|
264
|
+
// but enables feature flags and allows queue flush if init completes in time
|
|
171
265
|
initPromise = (async () => {
|
|
172
266
|
try {
|
|
173
267
|
const { StatsigClient: StatsigClientClass } = await import('@statsig/js-client');
|
|
@@ -177,17 +271,20 @@ export function initAnalytics(version) {
|
|
|
177
271
|
// Share Statsig client with feature-flags for synchronous gate checks
|
|
178
272
|
const { setStatsigClient } = await import('./feature-flags.js');
|
|
179
273
|
setStatsigClient(client);
|
|
274
|
+
// Statsig is ready — flush any events queued from previous runs
|
|
275
|
+
flushQueuedEvents();
|
|
180
276
|
}
|
|
181
277
|
catch {
|
|
182
278
|
// If Statsig can't initialize, fail silently — analytics should never break the CLI
|
|
183
279
|
statsigClient = null;
|
|
184
280
|
}
|
|
185
281
|
})();
|
|
186
|
-
return initPromise;
|
|
187
282
|
}
|
|
188
283
|
// ─── Event Tracking ──────────────────────────────────────────────────────────
|
|
189
284
|
/**
|
|
190
|
-
* Track an analytics event.
|
|
285
|
+
* Track an analytics event. Writes to a local disk queue synchronously —
|
|
286
|
+
* never blocks on network I/O. Events are flushed to Statsig on the next
|
|
287
|
+
* command run (or during this run's shutdown if Statsig initialized in time).
|
|
191
288
|
*
|
|
192
289
|
* @param eventName - Event name (e.g., 'command_run')
|
|
193
290
|
* @param value - Optional numeric or string value
|
|
@@ -203,13 +300,12 @@ export function trackEvent(eventName, value, metadata) {
|
|
|
203
300
|
: cliVersion
|
|
204
301
|
? { cli_version: cliVersion }
|
|
205
302
|
: null;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
303
|
+
writeEventToQueue({
|
|
304
|
+
name: eventName,
|
|
305
|
+
value,
|
|
306
|
+
metadata: stringMetadata,
|
|
307
|
+
timestamp: new Date().toISOString(),
|
|
308
|
+
});
|
|
213
309
|
}
|
|
214
310
|
catch {
|
|
215
311
|
// Never let analytics errors affect the CLI
|
|
@@ -273,54 +369,23 @@ export function trackMCPToolCalled(options) {
|
|
|
273
369
|
}
|
|
274
370
|
// ─── Shutdown ────────────────────────────────────────────────────────────────
|
|
275
371
|
/**
|
|
276
|
-
*
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (!statsigClient || pendingEvents.length === 0)
|
|
280
|
-
return;
|
|
281
|
-
for (const event of pendingEvents) {
|
|
282
|
-
try {
|
|
283
|
-
statsigClient.logEvent(event.name, event.value, event.metadata);
|
|
284
|
-
}
|
|
285
|
-
catch {
|
|
286
|
-
// Drop individual events silently
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
pendingEvents = [];
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Flush pending events and shut down the Statsig client.
|
|
293
|
-
* Called from the postrun hook. Caps total wait at SHUTDOWN_TIMEOUT_MS
|
|
294
|
-
* so analytics never adds more than 500ms to CLI exit time.
|
|
372
|
+
* Flush queued events (if Statsig is ready) and shut down the Statsig client.
|
|
373
|
+
* No timeout, no waiting for init — events are safely on disk if Statsig
|
|
374
|
+
* didn't initialize in time, and will be flushed on the next command run.
|
|
295
375
|
*/
|
|
296
376
|
export async function shutdownAnalytics() {
|
|
297
|
-
//
|
|
298
|
-
|
|
299
|
-
|
|
377
|
+
// Abandon any in-progress init — events are on disk, no need to wait
|
|
378
|
+
initPromise = null;
|
|
379
|
+
// If Statsig initialized during this run, flush queued events and shut down
|
|
380
|
+
if (statsigClient) {
|
|
381
|
+
flushQueuedEvents();
|
|
300
382
|
try {
|
|
301
|
-
|
|
302
|
-
initPromise,
|
|
303
|
-
new Promise((resolve) => setTimeout(resolve, SHUTDOWN_TIMEOUT_MS)),
|
|
304
|
-
]);
|
|
383
|
+
statsigClient.shutdown();
|
|
305
384
|
}
|
|
306
385
|
catch {
|
|
307
|
-
//
|
|
386
|
+
// Never let shutdown errors affect the CLI
|
|
308
387
|
}
|
|
309
|
-
initPromise = null;
|
|
310
|
-
}
|
|
311
|
-
// Replay any events that were buffered while init was in progress
|
|
312
|
-
flushPendingEvents();
|
|
313
|
-
if (!statsigClient)
|
|
314
|
-
return;
|
|
315
|
-
try {
|
|
316
|
-
statsigClient.shutdown();
|
|
317
|
-
}
|
|
318
|
-
catch {
|
|
319
|
-
// Never let shutdown errors affect the CLI
|
|
320
|
-
}
|
|
321
|
-
finally {
|
|
322
388
|
statsigClient = null;
|
|
323
|
-
// Clear feature-flags module reference
|
|
324
389
|
try {
|
|
325
390
|
const { setStatsigClient } = await import('./feature-flags.js');
|
|
326
391
|
setStatsigClient(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/lib/telemetry/analytics.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/lib/telemetry/analytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAElF,uEAAuE;AACvE,MAAM,kBAAkB,GAAG,oDAAoD,CAAA;AAE/E,uEAAuE;AACvE,MAAM,cAAc,GAAG,IAAI,CAAA;AA4C3B,qBAAqB;AACrB,IAAI,aAAa,GAAiC,IAAI,CAAA;AACtD,IAAI,eAAe,GAA2B,IAAI,CAAA;AAClD,IAAI,UAAU,GAAkB,IAAI,CAAA;AACpC,IAAI,WAAW,GAAyB,IAAI,CAAA;AAE5C,gFAAgF;AAEhF,SAAS,sBAAsB;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,gBAAgB,CAAC,CAAA;AAC3D,CAAC;AAED,SAAS,mBAAmB;IAC1B,IAAI,eAAe;QAAE,OAAO,eAAe,CAAA;IAE3C,MAAM,UAAU,GAAG,sBAAsB,EAAE,CAAA;IAE3C,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;YACpD,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoB,CAAA;YACxD,OAAO,eAAe,CAAA;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;QACtC,CAAC;IACH,CAAC;IAED,8CAA8C;IAC9C,eAAe,GAAG;QAChB,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,KAAK;QAClB,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE;QAC9B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAA;IAED,oBAAoB,CAAC,eAAe,CAAC,CAAA;IACrC,OAAO,eAAe,CAAA;AACxB,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAuB;IACnD,sBAAsB,EAAE,CAAA;IACxB,MAAM,UAAU,GAAG,sBAAsB,EAAE,CAAA;IAC3C,MAAM,QAAQ,GAAG,GAAG,UAAU,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAA;IAEnD,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;QACpE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;gBAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,2DAA2D;IAC3D,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,MAAM;QAAE,OAAO,KAAK,CAAA;IACzF,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,MAAM;QAAE,OAAO,KAAK,CAAA;IAE/G,uBAAuB;IACvB,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAA;IACpC,OAAO,MAAM,CAAC,OAAO,CAAA;AACvB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAA;IACpC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAA;IACrB,MAAM,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC3C,eAAe,GAAG,MAAM,CAAA;IACxB,oBAAoB,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAA;IACpC,MAAM,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,MAAM,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC3C,eAAe,GAAG,MAAM,CAAA;IACxB,oBAAoB,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAMhC,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAA;IAEpC,8BAA8B;IAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,MAAM,EAAE,CAAC;QAC5E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA;IACnG,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,MAAM,EAAE,CAAC;QAClG,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAA;IAC9G,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA;AACrF,CAAC;AAED,gFAAgF;AAEhF;;;GAGG;AACH,SAAS,mBAAmB;IAC1B,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAA;IACpC,IAAI,MAAM,CAAC,WAAW;QAAE,OAAM;IAC9B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC1B,kEAAkE;QAClE,MAAM,CAAC,WAAW,GAAG,IAAI,CAAA;QACzB,oBAAoB,CAAC,MAAM,CAAC,CAAA;QAC5B,OAAM;IACR,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAA;IACjF,OAAO,CAAC,GAAG,CAAC,wFAAwF,CAAC,CAAA;IACrG,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAA;IAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAA;IACvC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAEf,MAAM,CAAC,WAAW,GAAG,IAAI,CAAA;IACzB,eAAe,GAAG,MAAM,CAAA;IACxB,oBAAoB,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC;AAED,gFAAgF;AAEhF;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,mBAAmB,EAAE,CAAC,SAAS,CAAA;AACxC,CAAC;AAED,gFAAgF;AAEhF,SAAS,YAAY;IACnB,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,sBAAsB,CAAC,CAAA;AACjE,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,KAAkB;IAC3C,IAAI,CAAC;QACH,sBAAsB,EAAE,CAAA;QACxB,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;QAChC,IAAI,KAAK,GAAkB,EAAE,CAAA;QAE7B,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;gBAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;oBAAE,KAAK,GAAG,MAAM,CAAA;YAC3C,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;YACjC,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAEjB,6CAA6C;QAC7C,IAAI,KAAK,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;YAClC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,cAAc,CAAC,CAAA;QACpD,CAAC;QAED,sCAAsC;QACtC,MAAM,QAAQ,GAAG,GAAG,SAAS,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAA;QAClD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAA;QAC1D,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;IAC1C,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB;IACxB,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,SAAS,GAAG,GAAG,SAAS,UAAU,OAAO,CAAC,GAAG,EAAE,CAAA;IAErD,IAAI,CAAC;QACH,sDAAsD;QACtD,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,2DAA2D;QAC3D,OAAO,EAAE,CAAA;IACX,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9B,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC,aAAa;QAAE,OAAM;IAE1B,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAA;IAClC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,UAAU,GAAG,OAAO,CAAA;IAEpB,IAAI,CAAC,kBAAkB,EAAE;QAAE,OAAM;IAEjC,mBAAmB,EAAE,CAAA;IAErB,mEAAmE;IACnE,6EAA6E;IAC7E,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;YAChF,MAAM,MAAM,GAAG,IAAI,kBAAkB,CACnC,kBAAkB,EAClB,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,CAC7D,CAAA;YACD,MAAM,MAAM,CAAC,eAAe,EAAE,CAAA;YAC9B,aAAa,GAAG,MAAM,CAAA;YAEtB,sEAAsE;YACtE,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;YAC/D,gBAAgB,CAAC,MAAM,CAAC,CAAA;YAExB,gEAAgE;YAChE,iBAAiB,EAAE,CAAA;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,oFAAoF;YACpF,aAAa,GAAG,IAAI,CAAA;QACtB,CAAC;IACH,CAAC,CAAC,EAAE,CAAA;AACN,CAAC;AAED,gFAAgF;AAEhF;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,SAAiB,EAAE,KAA8B,EAAE,QAAyC;IACrH,IAAI,CAAC,kBAAkB,EAAE;QAAE,OAAM;IAEjC,IAAI,CAAC;QACH,mEAAmE;QACnE,MAAM,cAAc,GAAkC,QAAQ;YAC5D,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CACzF;YACH,CAAC,CAAC,UAAU;gBACV,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE;gBAC7B,CAAC,CAAC,IAAI,CAAA;QAEV,iBAAiB,CAAC;YAChB,IAAI,EAAE,SAAS;YACf,KAAK;YACL,QAAQ,EAAE,cAAc;YACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAA;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;IAC9C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAK/B;IACC,UAAU,CAAC,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE;QAC5C,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,UAAU,EAAE,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;KAC5C,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAKjC;IACC,UAAU,CAAC,eAAe,EAAE,IAAI,EAAE;QAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;KACrC,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAIxC;IACC,UAAU,CAAC,sBAAsB,EAAE,IAAI,EAAE;QACvC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,YAAY,EAAE,OAAO,CAAC,WAAW;KAClC,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAGlC;IACC,UAAU,CAAC,gBAAgB,EAAE,OAAO,CAAC,UAAU,EAAE;QAC/C,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;KACtC,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAE9B;IACC,UAAU,CAAC,YAAY,EAAE,IAAI,EAAE;QAC7B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAGlC;IACC,UAAU,CAAC,iBAAiB,EAAE,IAAI,EAAE;QAClC,SAAS,EAAE,OAAO,CAAC,QAAQ;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;KACjC,CAAC,CAAA;AACJ,CAAC;AAED,gFAAgF;AAEhF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,qEAAqE;IACrE,WAAW,GAAG,IAAI,CAAA;IAElB,4EAA4E;IAC5E,IAAI,aAAa,EAAE,CAAC;QAClB,iBAAiB,EAAE,CAAA;QAEnB,IAAI,CAAC;YACH,aAAa,CAAC,QAAQ,EAAE,CAAA;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,2CAA2C;QAC7C,CAAC;QAED,aAAa,GAAG,IAAI,CAAA;QACpB,IAAI,CAAC;YACH,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;YAC/D,gBAAgB,CAAC,IAAI,CAAC,CAAA;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Chaining Handler
|
|
3
|
+
*
|
|
4
|
+
* Listens for workflow_rule:matched events on the EventBus and automatically
|
|
5
|
+
* spawns the next agent action when an on_enter rule fires.
|
|
6
|
+
*
|
|
7
|
+
* Example chain:
|
|
8
|
+
* implement completes → lifecycle hook moves to Review →
|
|
9
|
+
* on_enter rule fires merge → ticket moves to Done
|
|
10
|
+
*
|
|
11
|
+
* Safety guards:
|
|
12
|
+
* - Max chain depth of 5 per ticket to prevent infinite loops
|
|
13
|
+
* - Skips if an agent is already running for the ticket
|
|
14
|
+
* - Only fires on_enter rules (manual rules are user-initiated)
|
|
15
|
+
* - Respects the enabled flag on rules
|
|
16
|
+
*/
|
|
17
|
+
import type Database from 'better-sqlite3';
|
|
18
|
+
import type { SQLiteStorage } from '../pmo/storage-sqlite.js';
|
|
19
|
+
export declare class ActionChainingHandler {
|
|
20
|
+
private unsubscribers;
|
|
21
|
+
private chainDepths;
|
|
22
|
+
private db;
|
|
23
|
+
private storage;
|
|
24
|
+
private pmoPath;
|
|
25
|
+
private log;
|
|
26
|
+
constructor(db: Database.Database, storage: SQLiteStorage, pmoPath: string, log?: (msg: string) => void);
|
|
27
|
+
/**
|
|
28
|
+
* Start listening for workflow rule matches.
|
|
29
|
+
*/
|
|
30
|
+
start(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Stop listening for events and clean up.
|
|
33
|
+
*/
|
|
34
|
+
stop(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Handle a workflow rule match by spawning the next action in the chain.
|
|
37
|
+
*/
|
|
38
|
+
private handleRuleMatched;
|
|
39
|
+
/**
|
|
40
|
+
* Spawn an agent to execute the chained action.
|
|
41
|
+
* Lazily resolves workspace info and agent selection.
|
|
42
|
+
*/
|
|
43
|
+
private spawnChainedAction;
|
|
44
|
+
/**
|
|
45
|
+
* Get the current chain depth for a ticket (for testing/debugging).
|
|
46
|
+
*/
|
|
47
|
+
getChainDepth(ticketId: string): number;
|
|
48
|
+
/**
|
|
49
|
+
* Reset chain depth for a ticket (e.g., when a ticket is manually moved).
|
|
50
|
+
*/
|
|
51
|
+
resetChainDepth(ticketId: string): void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Initialize and start the action chaining handler.
|
|
55
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
56
|
+
*/
|
|
57
|
+
export declare function initActionChaining(db: Database.Database, storage: SQLiteStorage, pmoPath: string, log?: (msg: string) => void): ActionChainingHandler;
|
|
58
|
+
/**
|
|
59
|
+
* Stop the action chaining handler (primarily for testing).
|
|
60
|
+
*/
|
|
61
|
+
export declare function stopActionChaining(): void;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Chaining Handler
|
|
3
|
+
*
|
|
4
|
+
* Listens for workflow_rule:matched events on the EventBus and automatically
|
|
5
|
+
* spawns the next agent action when an on_enter rule fires.
|
|
6
|
+
*
|
|
7
|
+
* Example chain:
|
|
8
|
+
* implement completes → lifecycle hook moves to Review →
|
|
9
|
+
* on_enter rule fires merge → ticket moves to Done
|
|
10
|
+
*
|
|
11
|
+
* Safety guards:
|
|
12
|
+
* - Max chain depth of 5 per ticket to prevent infinite loops
|
|
13
|
+
* - Skips if an agent is already running for the ticket
|
|
14
|
+
* - Only fires on_enter rules (manual rules are user-initiated)
|
|
15
|
+
* - Respects the enabled flag on rules
|
|
16
|
+
*/
|
|
17
|
+
import { getEventBus } from '../events/event-bus.js';
|
|
18
|
+
import { PMO_TABLES } from '../pmo/schema.js';
|
|
19
|
+
import { ExecutionStorage } from '../execution/storage.js';
|
|
20
|
+
import { trackEvent } from '../telemetry/analytics.js';
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// Constants
|
|
23
|
+
// =============================================================================
|
|
24
|
+
/** Maximum chain depth per ticket to prevent infinite loops. */
|
|
25
|
+
const MAX_CHAIN_DEPTH = 5;
|
|
26
|
+
// =============================================================================
|
|
27
|
+
// Handler
|
|
28
|
+
// =============================================================================
|
|
29
|
+
export class ActionChainingHandler {
|
|
30
|
+
unsubscribers = [];
|
|
31
|
+
chainDepths = new Map();
|
|
32
|
+
db;
|
|
33
|
+
storage;
|
|
34
|
+
pmoPath;
|
|
35
|
+
log;
|
|
36
|
+
constructor(db, storage, pmoPath, log) {
|
|
37
|
+
this.db = db;
|
|
38
|
+
this.storage = storage;
|
|
39
|
+
this.pmoPath = pmoPath;
|
|
40
|
+
this.log = log ?? (() => { });
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Start listening for workflow rule matches.
|
|
44
|
+
*/
|
|
45
|
+
start() {
|
|
46
|
+
const bus = getEventBus();
|
|
47
|
+
this.unsubscribers.push(bus.on('workflow_rule:matched', (event) => {
|
|
48
|
+
void this.handleRuleMatched(event);
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Stop listening for events and clean up.
|
|
53
|
+
*/
|
|
54
|
+
stop() {
|
|
55
|
+
for (const unsub of this.unsubscribers) {
|
|
56
|
+
unsub();
|
|
57
|
+
}
|
|
58
|
+
this.unsubscribers = [];
|
|
59
|
+
this.chainDepths.clear();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Handle a workflow rule match by spawning the next action in the chain.
|
|
63
|
+
*/
|
|
64
|
+
async handleRuleMatched(event) {
|
|
65
|
+
const { ticketId, actionId, ruleId, trigger, toState } = event;
|
|
66
|
+
// Only fire on_enter rules — manual rules are user-initiated
|
|
67
|
+
if (trigger !== 'on_enter')
|
|
68
|
+
return;
|
|
69
|
+
// Check chain depth to prevent infinite loops
|
|
70
|
+
const depth = this.chainDepths.get(ticketId) ?? 0;
|
|
71
|
+
if (depth >= MAX_CHAIN_DEPTH) {
|
|
72
|
+
this.log(`[action-chain] Depth limit reached for ${ticketId} (depth=${depth}, max=${MAX_CHAIN_DEPTH}). Stopping chain.`);
|
|
73
|
+
trackEvent('action_chain_blocked', null, {
|
|
74
|
+
ticket_id: ticketId,
|
|
75
|
+
action_id: actionId,
|
|
76
|
+
rule_id: ruleId,
|
|
77
|
+
reason: 'max_depth',
|
|
78
|
+
depth: String(depth),
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Check if an agent is already running for this ticket
|
|
83
|
+
const executionStorage = new ExecutionStorage(this.db);
|
|
84
|
+
const runningExec = executionStorage.getRunningExecution(ticketId);
|
|
85
|
+
if (runningExec) {
|
|
86
|
+
this.log(`[action-chain] Agent already running for ${ticketId} (execution=${runningExec.id}). Skipping chain.`);
|
|
87
|
+
trackEvent('action_chain_blocked', null, {
|
|
88
|
+
ticket_id: ticketId,
|
|
89
|
+
action_id: actionId,
|
|
90
|
+
rule_id: ruleId,
|
|
91
|
+
reason: 'agent_running',
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Look up the action
|
|
96
|
+
const action = this.db
|
|
97
|
+
.prepare(`SELECT * FROM ${PMO_TABLES.actions} WHERE id = ?`)
|
|
98
|
+
.get(actionId);
|
|
99
|
+
if (!action) {
|
|
100
|
+
this.log(`[action-chain] Action ${actionId} not found. Skipping chain for ${ticketId}.`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// Increment chain depth before spawning
|
|
104
|
+
this.chainDepths.set(ticketId, depth + 1);
|
|
105
|
+
this.log(`[action-chain] Firing action "${action.name}" for ${ticketId} (rule=${ruleId}, state=${toState}, depth=${depth + 1})`);
|
|
106
|
+
// Spawn the agent
|
|
107
|
+
try {
|
|
108
|
+
await this.spawnChainedAction(ticketId, event.projectId, action);
|
|
109
|
+
trackEvent('action_chain_fired', null, {
|
|
110
|
+
ticket_id: ticketId,
|
|
111
|
+
action_id: actionId,
|
|
112
|
+
action_name: action.name,
|
|
113
|
+
rule_id: ruleId,
|
|
114
|
+
to_state: toState,
|
|
115
|
+
chain_depth: String(depth + 1),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
120
|
+
this.log(`[action-chain] Failed to spawn action "${action.name}" for ${ticketId}: ${errorMsg}`);
|
|
121
|
+
trackEvent('action_chain_error', null, {
|
|
122
|
+
ticket_id: ticketId,
|
|
123
|
+
action_id: actionId,
|
|
124
|
+
rule_id: ruleId,
|
|
125
|
+
error: errorMsg,
|
|
126
|
+
});
|
|
127
|
+
// Roll back chain depth on failure so it can be retried
|
|
128
|
+
this.chainDepths.set(ticketId, depth);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Spawn an agent to execute the chained action.
|
|
133
|
+
* Lazily resolves workspace info and agent selection.
|
|
134
|
+
*/
|
|
135
|
+
async spawnChainedAction(ticketId, projectId, action) {
|
|
136
|
+
// Lazy imports to avoid circular dependencies and reduce startup cost
|
|
137
|
+
const { getWorkspaceInfo } = await import('../agents/commands.js');
|
|
138
|
+
const { spawnAgentForTicket, getAvailableAgents } = await import('../execution/spawner.js');
|
|
139
|
+
// Get workspace info (may throw if not in a workspace)
|
|
140
|
+
const workspaceInfo = getWorkspaceInfo();
|
|
141
|
+
// Get execution storage for agent availability check
|
|
142
|
+
const executionStorage = new ExecutionStorage(this.db);
|
|
143
|
+
// Get available agents
|
|
144
|
+
const availableAgents = getAvailableAgents(workspaceInfo, executionStorage);
|
|
145
|
+
if (availableAgents.length === 0) {
|
|
146
|
+
this.log(`[action-chain] No agents available for ${ticketId}. Chain paused.`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Select the first available agent
|
|
150
|
+
const agentName = availableAgents[0];
|
|
151
|
+
// Get the ticket
|
|
152
|
+
const ticket = await this.storage.getTicket(ticketId);
|
|
153
|
+
if (!ticket) {
|
|
154
|
+
this.log(`[action-chain] Ticket ${ticketId} not found. Skipping.`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Ensure projectId is set on ticket
|
|
158
|
+
if (!ticket.projectId) {
|
|
159
|
+
ticket.projectId = projectId;
|
|
160
|
+
}
|
|
161
|
+
// Spawn the agent with the action's configuration
|
|
162
|
+
// Note: chained actions always run in background mode
|
|
163
|
+
const result = await spawnAgentForTicket(ticket, agentName, this.storage, executionStorage, workspaceInfo, this.db, this.pmoPath, {
|
|
164
|
+
displayMode: 'background',
|
|
165
|
+
log: (msg) => this.log(`[action-chain] ${msg}`),
|
|
166
|
+
});
|
|
167
|
+
if (result.success) {
|
|
168
|
+
this.log(`[action-chain] Spawned ${agentName} for ${ticketId} → action "${action.name}" (execution=${result.executionId})`);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
throw new Error(result.error || 'Unknown spawn error');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get the current chain depth for a ticket (for testing/debugging).
|
|
176
|
+
*/
|
|
177
|
+
getChainDepth(ticketId) {
|
|
178
|
+
return this.chainDepths.get(ticketId) ?? 0;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Reset chain depth for a ticket (e.g., when a ticket is manually moved).
|
|
182
|
+
*/
|
|
183
|
+
resetChainDepth(ticketId) {
|
|
184
|
+
this.chainDepths.delete(ticketId);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// =============================================================================
|
|
188
|
+
// Singleton
|
|
189
|
+
// =============================================================================
|
|
190
|
+
let _handler;
|
|
191
|
+
/**
|
|
192
|
+
* Initialize and start the action chaining handler.
|
|
193
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
194
|
+
*/
|
|
195
|
+
export function initActionChaining(db, storage, pmoPath, log) {
|
|
196
|
+
if (!_handler) {
|
|
197
|
+
_handler = new ActionChainingHandler(db, storage, pmoPath, log);
|
|
198
|
+
_handler.start();
|
|
199
|
+
}
|
|
200
|
+
return _handler;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Stop the action chaining handler (primarily for testing).
|
|
204
|
+
*/
|
|
205
|
+
export function stopActionChaining() {
|
|
206
|
+
if (_handler) {
|
|
207
|
+
_handler.stop();
|
|
208
|
+
_handler = undefined;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=action-chaining.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-chaining.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/action-chaining.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,3 +8,6 @@
|
|
|
8
8
|
export type { WorkEventSource, WorkStartedEvent, WorkStatusChangedEvent, WorkPRCreatedEvent, WorkCompletedEvent, } from './events.js';
|
|
9
9
|
export { WorkLifecycleAdapter, initWorkLifecycleAdapter, stopWorkLifecycleAdapter, } from './adapter.js';
|
|
10
10
|
export { initHookManager, stopHookManager, } from './hooks/index.js';
|
|
11
|
+
export { handlePostExecutionTransition, type PostExecutionContext, type PostExecutionResult, } from './post-execution.js';
|
|
12
|
+
export { WorkflowRuleEvaluator, initWorkflowRuleEvaluator, stopWorkflowRuleEvaluator, } from './rule-evaluator.js';
|
|
13
|
+
export { ActionChainingHandler, initActionChaining, stopActionChaining, } from './action-chaining.js';
|
|
@@ -7,4 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { WorkLifecycleAdapter, initWorkLifecycleAdapter, stopWorkLifecycleAdapter, } from './adapter.js';
|
|
9
9
|
export { initHookManager, stopHookManager, } from './hooks/index.js';
|
|
10
|
+
export { handlePostExecutionTransition, } from './post-execution.js';
|
|
11
|
+
export { WorkflowRuleEvaluator, initWorkflowRuleEvaluator, stopWorkflowRuleEvaluator, } from './rule-evaluator.js';
|
|
12
|
+
export { ActionChainingHandler, initActionChaining, stopActionChaining, } from './action-chaining.js';
|
|
10
13
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,6BAA6B,GAG9B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-Execution Transition Hook
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic ticket state transitions after an action execution completes.
|
|
5
|
+
* Primary use case: when the implement action completes and a PR was created,
|
|
6
|
+
* automatically move the ticket from In Progress to Review.
|
|
7
|
+
*
|
|
8
|
+
* This hook replaces the need for a separate "create-pr" action. The implement
|
|
9
|
+
* action's endPrompt handles PR creation via `prlt work ready --pr`, and this
|
|
10
|
+
* hook ensures the state transition happens systematically.
|
|
11
|
+
*/
|
|
12
|
+
import Database from 'better-sqlite3';
|
|
13
|
+
import type { StateCategory } from '../pmo/types.js';
|
|
14
|
+
export interface PostExecutionContext {
|
|
15
|
+
ticketId: string;
|
|
16
|
+
actionId?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface PostExecutionResult {
|
|
19
|
+
transitioned: boolean;
|
|
20
|
+
fromState?: string;
|
|
21
|
+
toState?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Minimal storage interface for post-execution transitions. */
|
|
24
|
+
export interface PostExecutionStorage {
|
|
25
|
+
getTicket: (id: string) => Promise<{
|
|
26
|
+
id: string;
|
|
27
|
+
projectId?: string;
|
|
28
|
+
statusName?: string;
|
|
29
|
+
statusCategory?: StateCategory | null;
|
|
30
|
+
metadata?: Record<string, string> | null;
|
|
31
|
+
} | null>;
|
|
32
|
+
getProjectBoard: (projectId: string) => Promise<{
|
|
33
|
+
columns: Array<{
|
|
34
|
+
name: string;
|
|
35
|
+
}>;
|
|
36
|
+
} | null>;
|
|
37
|
+
moveTicket: (projectId: string, ticketId: string, columnName: string) => Promise<unknown>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if a completed execution should trigger an automatic state transition.
|
|
41
|
+
*
|
|
42
|
+
* When an execution completes and the ticket:
|
|
43
|
+
* 1. Is in a "started" category (e.g., In Progress)
|
|
44
|
+
* 2. Has a PR URL in its metadata
|
|
45
|
+
*
|
|
46
|
+
* Then automatically move the ticket to the Review column.
|
|
47
|
+
* If no PR was created, the ticket stays in its current state.
|
|
48
|
+
*
|
|
49
|
+
* @param context - Execution context with ticket and optional action info
|
|
50
|
+
* @param storage - PMO storage instance for ticket operations
|
|
51
|
+
* @param db - Database for work column settings
|
|
52
|
+
* @returns Result indicating whether a transition occurred
|
|
53
|
+
*/
|
|
54
|
+
export declare function handlePostExecutionTransition(context: PostExecutionContext, storage: PostExecutionStorage, db: Database.Database): Promise<PostExecutionResult>;
|