@exaudeus/workrail 3.73.1 → 3.73.2
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/console-ui/assets/{index-txIYXGHx.js → index-CfI4I3OX.js} +1 -1
- package/dist/console-ui/index.html +1 -1
- package/dist/manifest.json +67 -51
- package/dist/mcp/handlers/v2-advance-core/index.d.ts +1 -0
- package/dist/mcp/handlers/v2-advance-core/index.js +3 -3
- package/dist/mcp/handlers/v2-advance-core/outcome-success.js +4 -18
- package/dist/mcp/handlers/v2-advance-events.d.ts +1 -1
- package/dist/mcp/handlers/v2-advance-events.js +1 -1
- package/dist/mcp/handlers/v2-execution/advance.d.ts +1 -0
- package/dist/mcp/handlers/v2-execution/advance.js +3 -3
- package/dist/mcp/handlers/v2-execution/continue-advance.d.ts +1 -0
- package/dist/mcp/handlers/v2-execution/continue-advance.js +2 -1
- package/dist/mcp/handlers/v2-execution/index.js +3 -1
- package/dist/mcp/server.js +6 -4
- package/dist/mcp/types.d.ts +2 -0
- package/dist/trigger/delivery-action.d.ts +1 -0
- package/dist/trigger/delivery-action.js +1 -1
- package/dist/trigger/delivery-pipeline.d.ts +13 -2
- package/dist/trigger/delivery-pipeline.js +58 -3
- package/dist/trigger/trigger-router.js +6 -3
- package/dist/v2/durable-core/constants.d.ts +1 -0
- package/dist/v2/durable-core/constants.js +1 -0
- package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +202 -0
- package/dist/v2/durable-core/schemas/session/events.d.ts +56 -0
- package/dist/v2/durable-core/schemas/session/events.js +8 -0
- package/dist/v2/infra/local/git-snapshot/index.d.ts +6 -0
- package/dist/v2/infra/local/git-snapshot/index.js +39 -0
- package/dist/v2/ports/git-snapshot.port.d.ts +10 -0
- package/dist/v2/ports/git-snapshot.port.js +9 -0
- package/dist/v2/projections/session-metrics.js +17 -2
- package/docs/design/engine-boundary-discovery.md +123 -0
- package/docs/design/engine-boundary-review-findings.md +72 -0
- package/docs/ideas/backlog.md +46 -0
- package/package.json +1 -1
|
@@ -39,11 +39,16 @@ const fs = __importStar(require("node:fs/promises"));
|
|
|
39
39
|
const path = __importStar(require("node:path"));
|
|
40
40
|
const workflow_runner_js_1 = require("../daemon/workflow-runner.js");
|
|
41
41
|
const delivery_action_js_1 = require("./delivery-action.js");
|
|
42
|
-
|
|
42
|
+
const constants_js_1 = require("../v2/durable-core/constants.js");
|
|
43
|
+
const index_js_1 = require("../v2/durable-core/ids/index.js");
|
|
44
|
+
const session_index_js_1 = require("../v2/durable-core/session-index.js");
|
|
45
|
+
const sorted_event_log_js_1 = require("../v2/durable-core/sorted-event-log.js");
|
|
46
|
+
const neverthrow_1 = require("neverthrow");
|
|
47
|
+
async function runDeliveryPipeline(stages, result, trigger, execFn, triggerId, deps) {
|
|
43
48
|
const ctx = {};
|
|
44
49
|
try {
|
|
45
50
|
for (const stage of stages) {
|
|
46
|
-
const outcome = await stage.run(result, trigger, execFn, ctx);
|
|
51
|
+
const outcome = await stage.run(result, trigger, execFn, ctx, deps);
|
|
47
52
|
if (outcome.kind === 'stop') {
|
|
48
53
|
console.log(`[DeliveryPipeline] Stage "${stage.name}" stopped pipeline: triggerId=${triggerId} reason=${outcome.reason}`);
|
|
49
54
|
return;
|
|
@@ -96,9 +101,12 @@ const gitDeliveryStage = {
|
|
|
96
101
|
switch (deliveryResult._tag) {
|
|
97
102
|
case 'committed':
|
|
98
103
|
console.log(`[DeliveryPipeline] Delivery committed: triggerId=${trigger.id} sha=${deliveryResult.sha}`);
|
|
104
|
+
ctx.commitSha = deliveryResult.sha;
|
|
99
105
|
break;
|
|
100
106
|
case 'pr_opened':
|
|
101
|
-
console.log(`[DeliveryPipeline] Delivery PR opened: triggerId=${trigger.id} url=${deliveryResult.url}`);
|
|
107
|
+
console.log(`[DeliveryPipeline] Delivery PR opened: triggerId=${trigger.id} url=${deliveryResult.url} sha=${deliveryResult.sha}`);
|
|
108
|
+
ctx.commitSha = deliveryResult.sha;
|
|
109
|
+
ctx.prUrl = deliveryResult.url;
|
|
102
110
|
break;
|
|
103
111
|
case 'skipped':
|
|
104
112
|
console.log(`[DeliveryPipeline] Delivery skipped: triggerId=${trigger.id} reason=${deliveryResult.reason}`);
|
|
@@ -111,6 +119,52 @@ const gitDeliveryStage = {
|
|
|
111
119
|
return { kind: 'continue' };
|
|
112
120
|
},
|
|
113
121
|
};
|
|
122
|
+
const recordCommitShasStage = {
|
|
123
|
+
name: 'recordCommitShas',
|
|
124
|
+
async run(result, _trigger, _execFn, ctx, deps) {
|
|
125
|
+
const { sessionId } = result;
|
|
126
|
+
if (!sessionId || !ctx.commitSha || !deps) {
|
|
127
|
+
return { kind: 'continue' };
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const sid = (0, index_js_1.asSessionId)(sessionId);
|
|
131
|
+
const shas = [ctx.commitSha];
|
|
132
|
+
const prUrl = ctx.prUrl;
|
|
133
|
+
await deps.gate.withHealthySessionLock(sid, (lock) => deps.sessionStore.load(sid).andThen((truth) => {
|
|
134
|
+
const sortedResult = (0, sorted_event_log_js_1.asSortedEventLog)(truth.events);
|
|
135
|
+
if (sortedResult.isErr()) {
|
|
136
|
+
return (0, neverthrow_1.okAsync)(undefined);
|
|
137
|
+
}
|
|
138
|
+
const index = (0, session_index_js_1.buildSessionIndex)(sortedResult.value);
|
|
139
|
+
const runCompleted = truth.events.find(e => e.kind === 'run_completed');
|
|
140
|
+
const runId = runCompleted?.scope.runId;
|
|
141
|
+
if (!runId) {
|
|
142
|
+
return (0, neverthrow_1.okAsync)(undefined);
|
|
143
|
+
}
|
|
144
|
+
const event = {
|
|
145
|
+
v: 1,
|
|
146
|
+
eventId: deps.idFactory.mintEventId(),
|
|
147
|
+
eventIndex: index.nextEventIndex,
|
|
148
|
+
sessionId,
|
|
149
|
+
kind: constants_js_1.EVENT_KIND.DELIVERY_RECORDED,
|
|
150
|
+
dedupeKey: `delivery-recorded:${sessionId}:${runId}`,
|
|
151
|
+
scope: { runId },
|
|
152
|
+
data: { shas, ...(prUrl ? { prUrl } : {}) },
|
|
153
|
+
timestampMs: Date.now(),
|
|
154
|
+
};
|
|
155
|
+
return deps.sessionStore.append(lock, { events: [event], snapshotPins: [] });
|
|
156
|
+
})).match(() => {
|
|
157
|
+
console.log(`[DeliveryPipeline] Commit SHAs recorded: sessionId=${sessionId} shas=${shas.join(',')}`);
|
|
158
|
+
}, (err) => {
|
|
159
|
+
console.warn(`[DeliveryPipeline] Could not record commit SHAs: sessionId=${sessionId} err=${JSON.stringify(err)}`);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
console.warn(`[DeliveryPipeline] Unexpected error in recordCommitShasStage: ${err instanceof Error ? err.message : String(err)}`);
|
|
164
|
+
}
|
|
165
|
+
return { kind: 'continue' };
|
|
166
|
+
},
|
|
167
|
+
};
|
|
114
168
|
const cleanupWorktreeStage = {
|
|
115
169
|
name: 'cleanupWorktree',
|
|
116
170
|
async run(result, trigger, execFn, _ctx) {
|
|
@@ -143,6 +197,7 @@ const deleteSidecarStage = {
|
|
|
143
197
|
exports.DEFAULT_DELIVERY_PIPELINE = [
|
|
144
198
|
parseHandoffStage,
|
|
145
199
|
gitDeliveryStage,
|
|
200
|
+
recordCommitShasStage,
|
|
146
201
|
cleanupWorktreeStage,
|
|
147
202
|
deleteSidecarStage,
|
|
148
203
|
];
|
|
@@ -118,7 +118,7 @@ function validateHmac(rawBody, secret, headerValue) {
|
|
|
118
118
|
}
|
|
119
119
|
return crypto.timingSafeEqual(Buffer.from(expected, 'utf8'), Buffer.from(received, 'utf8'));
|
|
120
120
|
}
|
|
121
|
-
async function maybeRunDelivery(triggerId, trigger, result, execFn) {
|
|
121
|
+
async function maybeRunDelivery(triggerId, trigger, result, execFn, deps) {
|
|
122
122
|
if (result._tag !== 'success')
|
|
123
123
|
return;
|
|
124
124
|
if (result.lastStepNotes === undefined) {
|
|
@@ -131,7 +131,7 @@ async function maybeRunDelivery(triggerId, trigger, result, execFn) {
|
|
|
131
131
|
}
|
|
132
132
|
if (trigger.autoCommit !== true)
|
|
133
133
|
return;
|
|
134
|
-
await (0, delivery_pipeline_js_1.runDeliveryPipeline)(delivery_pipeline_js_1.DEFAULT_DELIVERY_PIPELINE, result, trigger, execFn, triggerId);
|
|
134
|
+
await (0, delivery_pipeline_js_1.runDeliveryPipeline)(delivery_pipeline_js_1.DEFAULT_DELIVERY_PIPELINE, result, trigger, execFn, triggerId, deps);
|
|
135
135
|
}
|
|
136
136
|
class Semaphore {
|
|
137
137
|
constructor(max) {
|
|
@@ -340,7 +340,10 @@ class TriggerRouter {
|
|
|
340
340
|
(0, assert_never_js_1.assertNever)(result);
|
|
341
341
|
}
|
|
342
342
|
this.notificationService?.notify(result, workflowTrigger.goal);
|
|
343
|
-
|
|
343
|
+
const deliveryDeps = this.ctx.v2
|
|
344
|
+
? { gate: this.ctx.v2.gate, sessionStore: this.ctx.v2.sessionStore, idFactory: this.ctx.v2.idFactory }
|
|
345
|
+
: undefined;
|
|
346
|
+
await maybeRunDelivery(trigger.id, trigger, originalResult, this.execFn, deliveryDeps);
|
|
344
347
|
});
|
|
345
348
|
return { _tag: 'enqueued', triggerId: trigger.id };
|
|
346
349
|
}
|
|
@@ -38,6 +38,7 @@ export declare const EVENT_KIND: {
|
|
|
38
38
|
readonly DIVERGENCE_RECORDED: "divergence_recorded";
|
|
39
39
|
readonly DECISION_TRACE_APPENDED: "decision_trace_appended";
|
|
40
40
|
readonly RUN_COMPLETED: "run_completed";
|
|
41
|
+
readonly DELIVERY_RECORDED: "delivery_recorded";
|
|
41
42
|
};
|
|
42
43
|
export type EventKindV1 = typeof EVENT_KIND[keyof typeof EVENT_KIND];
|
|
43
44
|
export declare const OUTPUT_CHANNEL: {
|
|
@@ -2567,6 +2567,62 @@ export declare const SessionContentsV1Schema: z.ZodObject<{
|
|
|
2567
2567
|
durationMs?: number | undefined;
|
|
2568
2568
|
};
|
|
2569
2569
|
timestampMs: number;
|
|
2570
|
+
}>, z.ZodObject<{
|
|
2571
|
+
v: z.ZodLiteral<1>;
|
|
2572
|
+
eventId: z.ZodString;
|
|
2573
|
+
eventIndex: z.ZodNumber;
|
|
2574
|
+
sessionId: z.ZodString;
|
|
2575
|
+
dedupeKey: z.ZodString;
|
|
2576
|
+
timestampMs: z.ZodNumber;
|
|
2577
|
+
} & {
|
|
2578
|
+
kind: z.ZodLiteral<"delivery_recorded">;
|
|
2579
|
+
scope: z.ZodObject<{
|
|
2580
|
+
runId: z.ZodString;
|
|
2581
|
+
}, "strip", z.ZodTypeAny, {
|
|
2582
|
+
runId: string;
|
|
2583
|
+
}, {
|
|
2584
|
+
runId: string;
|
|
2585
|
+
}>;
|
|
2586
|
+
data: z.ZodObject<{
|
|
2587
|
+
shas: z.ZodArray<z.ZodString, "many">;
|
|
2588
|
+
prUrl: z.ZodOptional<z.ZodString>;
|
|
2589
|
+
}, "strip", z.ZodTypeAny, {
|
|
2590
|
+
shas: string[];
|
|
2591
|
+
prUrl?: string | undefined;
|
|
2592
|
+
}, {
|
|
2593
|
+
shas: string[];
|
|
2594
|
+
prUrl?: string | undefined;
|
|
2595
|
+
}>;
|
|
2596
|
+
}, "strip", z.ZodTypeAny, {
|
|
2597
|
+
kind: "delivery_recorded";
|
|
2598
|
+
v: 1;
|
|
2599
|
+
sessionId: string;
|
|
2600
|
+
eventIndex: number;
|
|
2601
|
+
eventId: string;
|
|
2602
|
+
dedupeKey: string;
|
|
2603
|
+
scope: {
|
|
2604
|
+
runId: string;
|
|
2605
|
+
};
|
|
2606
|
+
data: {
|
|
2607
|
+
shas: string[];
|
|
2608
|
+
prUrl?: string | undefined;
|
|
2609
|
+
};
|
|
2610
|
+
timestampMs: number;
|
|
2611
|
+
}, {
|
|
2612
|
+
kind: "delivery_recorded";
|
|
2613
|
+
v: 1;
|
|
2614
|
+
sessionId: string;
|
|
2615
|
+
eventIndex: number;
|
|
2616
|
+
eventId: string;
|
|
2617
|
+
dedupeKey: string;
|
|
2618
|
+
scope: {
|
|
2619
|
+
runId: string;
|
|
2620
|
+
};
|
|
2621
|
+
data: {
|
|
2622
|
+
shas: string[];
|
|
2623
|
+
prUrl?: string | undefined;
|
|
2624
|
+
};
|
|
2625
|
+
timestampMs: number;
|
|
2570
2626
|
}>]>, "many">;
|
|
2571
2627
|
manifest: z.ZodArray<z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
2572
2628
|
v: z.ZodLiteral<1>;
|
|
@@ -5311,6 +5367,21 @@ export declare const SessionContentsV1Schema: z.ZodObject<{
|
|
|
5311
5367
|
durationMs?: number | undefined;
|
|
5312
5368
|
};
|
|
5313
5369
|
timestampMs: number;
|
|
5370
|
+
} | {
|
|
5371
|
+
kind: "delivery_recorded";
|
|
5372
|
+
v: 1;
|
|
5373
|
+
sessionId: string;
|
|
5374
|
+
eventIndex: number;
|
|
5375
|
+
eventId: string;
|
|
5376
|
+
dedupeKey: string;
|
|
5377
|
+
scope: {
|
|
5378
|
+
runId: string;
|
|
5379
|
+
};
|
|
5380
|
+
data: {
|
|
5381
|
+
shas: string[];
|
|
5382
|
+
prUrl?: string | undefined;
|
|
5383
|
+
};
|
|
5384
|
+
timestampMs: number;
|
|
5314
5385
|
})[];
|
|
5315
5386
|
manifest: ({
|
|
5316
5387
|
kind: "segment_closed";
|
|
@@ -5925,6 +5996,21 @@ export declare const SessionContentsV1Schema: z.ZodObject<{
|
|
|
5925
5996
|
durationMs?: number | undefined;
|
|
5926
5997
|
};
|
|
5927
5998
|
timestampMs: number;
|
|
5999
|
+
} | {
|
|
6000
|
+
kind: "delivery_recorded";
|
|
6001
|
+
v: 1;
|
|
6002
|
+
sessionId: string;
|
|
6003
|
+
eventIndex: number;
|
|
6004
|
+
eventId: string;
|
|
6005
|
+
dedupeKey: string;
|
|
6006
|
+
scope: {
|
|
6007
|
+
runId: string;
|
|
6008
|
+
};
|
|
6009
|
+
data: {
|
|
6010
|
+
shas: string[];
|
|
6011
|
+
prUrl?: string | undefined;
|
|
6012
|
+
};
|
|
6013
|
+
timestampMs: number;
|
|
5928
6014
|
})[];
|
|
5929
6015
|
manifest: ({
|
|
5930
6016
|
kind: "segment_closed";
|
|
@@ -8504,6 +8590,62 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
8504
8590
|
durationMs?: number | undefined;
|
|
8505
8591
|
};
|
|
8506
8592
|
timestampMs: number;
|
|
8593
|
+
}>, z.ZodObject<{
|
|
8594
|
+
v: z.ZodLiteral<1>;
|
|
8595
|
+
eventId: z.ZodString;
|
|
8596
|
+
eventIndex: z.ZodNumber;
|
|
8597
|
+
sessionId: z.ZodString;
|
|
8598
|
+
dedupeKey: z.ZodString;
|
|
8599
|
+
timestampMs: z.ZodNumber;
|
|
8600
|
+
} & {
|
|
8601
|
+
kind: z.ZodLiteral<"delivery_recorded">;
|
|
8602
|
+
scope: z.ZodObject<{
|
|
8603
|
+
runId: z.ZodString;
|
|
8604
|
+
}, "strip", z.ZodTypeAny, {
|
|
8605
|
+
runId: string;
|
|
8606
|
+
}, {
|
|
8607
|
+
runId: string;
|
|
8608
|
+
}>;
|
|
8609
|
+
data: z.ZodObject<{
|
|
8610
|
+
shas: z.ZodArray<z.ZodString, "many">;
|
|
8611
|
+
prUrl: z.ZodOptional<z.ZodString>;
|
|
8612
|
+
}, "strip", z.ZodTypeAny, {
|
|
8613
|
+
shas: string[];
|
|
8614
|
+
prUrl?: string | undefined;
|
|
8615
|
+
}, {
|
|
8616
|
+
shas: string[];
|
|
8617
|
+
prUrl?: string | undefined;
|
|
8618
|
+
}>;
|
|
8619
|
+
}, "strip", z.ZodTypeAny, {
|
|
8620
|
+
kind: "delivery_recorded";
|
|
8621
|
+
v: 1;
|
|
8622
|
+
sessionId: string;
|
|
8623
|
+
eventIndex: number;
|
|
8624
|
+
eventId: string;
|
|
8625
|
+
dedupeKey: string;
|
|
8626
|
+
scope: {
|
|
8627
|
+
runId: string;
|
|
8628
|
+
};
|
|
8629
|
+
data: {
|
|
8630
|
+
shas: string[];
|
|
8631
|
+
prUrl?: string | undefined;
|
|
8632
|
+
};
|
|
8633
|
+
timestampMs: number;
|
|
8634
|
+
}, {
|
|
8635
|
+
kind: "delivery_recorded";
|
|
8636
|
+
v: 1;
|
|
8637
|
+
sessionId: string;
|
|
8638
|
+
eventIndex: number;
|
|
8639
|
+
eventId: string;
|
|
8640
|
+
dedupeKey: string;
|
|
8641
|
+
scope: {
|
|
8642
|
+
runId: string;
|
|
8643
|
+
};
|
|
8644
|
+
data: {
|
|
8645
|
+
shas: string[];
|
|
8646
|
+
prUrl?: string | undefined;
|
|
8647
|
+
};
|
|
8648
|
+
timestampMs: number;
|
|
8507
8649
|
}>]>, "many">;
|
|
8508
8650
|
manifest: z.ZodArray<z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
8509
8651
|
v: z.ZodLiteral<1>;
|
|
@@ -11248,6 +11390,21 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
11248
11390
|
durationMs?: number | undefined;
|
|
11249
11391
|
};
|
|
11250
11392
|
timestampMs: number;
|
|
11393
|
+
} | {
|
|
11394
|
+
kind: "delivery_recorded";
|
|
11395
|
+
v: 1;
|
|
11396
|
+
sessionId: string;
|
|
11397
|
+
eventIndex: number;
|
|
11398
|
+
eventId: string;
|
|
11399
|
+
dedupeKey: string;
|
|
11400
|
+
scope: {
|
|
11401
|
+
runId: string;
|
|
11402
|
+
};
|
|
11403
|
+
data: {
|
|
11404
|
+
shas: string[];
|
|
11405
|
+
prUrl?: string | undefined;
|
|
11406
|
+
};
|
|
11407
|
+
timestampMs: number;
|
|
11251
11408
|
})[];
|
|
11252
11409
|
manifest: ({
|
|
11253
11410
|
kind: "segment_closed";
|
|
@@ -11862,6 +12019,21 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
11862
12019
|
durationMs?: number | undefined;
|
|
11863
12020
|
};
|
|
11864
12021
|
timestampMs: number;
|
|
12022
|
+
} | {
|
|
12023
|
+
kind: "delivery_recorded";
|
|
12024
|
+
v: 1;
|
|
12025
|
+
sessionId: string;
|
|
12026
|
+
eventIndex: number;
|
|
12027
|
+
eventId: string;
|
|
12028
|
+
dedupeKey: string;
|
|
12029
|
+
scope: {
|
|
12030
|
+
runId: string;
|
|
12031
|
+
};
|
|
12032
|
+
data: {
|
|
12033
|
+
shas: string[];
|
|
12034
|
+
prUrl?: string | undefined;
|
|
12035
|
+
};
|
|
12036
|
+
timestampMs: number;
|
|
11865
12037
|
})[];
|
|
11866
12038
|
manifest: ({
|
|
11867
12039
|
kind: "segment_closed";
|
|
@@ -12490,6 +12662,21 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
12490
12662
|
durationMs?: number | undefined;
|
|
12491
12663
|
};
|
|
12492
12664
|
timestampMs: number;
|
|
12665
|
+
} | {
|
|
12666
|
+
kind: "delivery_recorded";
|
|
12667
|
+
v: 1;
|
|
12668
|
+
sessionId: string;
|
|
12669
|
+
eventIndex: number;
|
|
12670
|
+
eventId: string;
|
|
12671
|
+
dedupeKey: string;
|
|
12672
|
+
scope: {
|
|
12673
|
+
runId: string;
|
|
12674
|
+
};
|
|
12675
|
+
data: {
|
|
12676
|
+
shas: string[];
|
|
12677
|
+
prUrl?: string | undefined;
|
|
12678
|
+
};
|
|
12679
|
+
timestampMs: number;
|
|
12493
12680
|
})[];
|
|
12494
12681
|
manifest: ({
|
|
12495
12682
|
kind: "segment_closed";
|
|
@@ -13121,6 +13308,21 @@ export declare const ExportBundleV1Schema: z.ZodObject<{
|
|
|
13121
13308
|
durationMs?: number | undefined;
|
|
13122
13309
|
};
|
|
13123
13310
|
timestampMs: number;
|
|
13311
|
+
} | {
|
|
13312
|
+
kind: "delivery_recorded";
|
|
13313
|
+
v: 1;
|
|
13314
|
+
sessionId: string;
|
|
13315
|
+
eventIndex: number;
|
|
13316
|
+
eventId: string;
|
|
13317
|
+
dedupeKey: string;
|
|
13318
|
+
scope: {
|
|
13319
|
+
runId: string;
|
|
13320
|
+
};
|
|
13321
|
+
data: {
|
|
13322
|
+
shas: string[];
|
|
13323
|
+
prUrl?: string | undefined;
|
|
13324
|
+
};
|
|
13325
|
+
timestampMs: number;
|
|
13124
13326
|
})[];
|
|
13125
13327
|
manifest: ({
|
|
13126
13328
|
kind: "segment_closed";
|
|
@@ -2555,5 +2555,61 @@ export declare const DomainEventV1Schema: z.ZodDiscriminatedUnion<"kind", [z.Zod
|
|
|
2555
2555
|
durationMs?: number | undefined;
|
|
2556
2556
|
};
|
|
2557
2557
|
timestampMs: number;
|
|
2558
|
+
}>, z.ZodObject<{
|
|
2559
|
+
v: z.ZodLiteral<1>;
|
|
2560
|
+
eventId: z.ZodString;
|
|
2561
|
+
eventIndex: z.ZodNumber;
|
|
2562
|
+
sessionId: z.ZodString;
|
|
2563
|
+
dedupeKey: z.ZodString;
|
|
2564
|
+
timestampMs: z.ZodNumber;
|
|
2565
|
+
} & {
|
|
2566
|
+
kind: z.ZodLiteral<"delivery_recorded">;
|
|
2567
|
+
scope: z.ZodObject<{
|
|
2568
|
+
runId: z.ZodString;
|
|
2569
|
+
}, "strip", z.ZodTypeAny, {
|
|
2570
|
+
runId: string;
|
|
2571
|
+
}, {
|
|
2572
|
+
runId: string;
|
|
2573
|
+
}>;
|
|
2574
|
+
data: z.ZodObject<{
|
|
2575
|
+
shas: z.ZodArray<z.ZodString, "many">;
|
|
2576
|
+
prUrl: z.ZodOptional<z.ZodString>;
|
|
2577
|
+
}, "strip", z.ZodTypeAny, {
|
|
2578
|
+
shas: string[];
|
|
2579
|
+
prUrl?: string | undefined;
|
|
2580
|
+
}, {
|
|
2581
|
+
shas: string[];
|
|
2582
|
+
prUrl?: string | undefined;
|
|
2583
|
+
}>;
|
|
2584
|
+
}, "strip", z.ZodTypeAny, {
|
|
2585
|
+
kind: "delivery_recorded";
|
|
2586
|
+
v: 1;
|
|
2587
|
+
sessionId: string;
|
|
2588
|
+
eventIndex: number;
|
|
2589
|
+
eventId: string;
|
|
2590
|
+
dedupeKey: string;
|
|
2591
|
+
scope: {
|
|
2592
|
+
runId: string;
|
|
2593
|
+
};
|
|
2594
|
+
data: {
|
|
2595
|
+
shas: string[];
|
|
2596
|
+
prUrl?: string | undefined;
|
|
2597
|
+
};
|
|
2598
|
+
timestampMs: number;
|
|
2599
|
+
}, {
|
|
2600
|
+
kind: "delivery_recorded";
|
|
2601
|
+
v: 1;
|
|
2602
|
+
sessionId: string;
|
|
2603
|
+
eventIndex: number;
|
|
2604
|
+
eventId: string;
|
|
2605
|
+
dedupeKey: string;
|
|
2606
|
+
scope: {
|
|
2607
|
+
runId: string;
|
|
2608
|
+
};
|
|
2609
|
+
data: {
|
|
2610
|
+
shas: string[];
|
|
2611
|
+
prUrl?: string | undefined;
|
|
2612
|
+
};
|
|
2613
|
+
timestampMs: number;
|
|
2558
2614
|
}>]>;
|
|
2559
2615
|
export type DomainEventV1 = z.infer<typeof DomainEventV1Schema>;
|
|
@@ -274,4 +274,12 @@ exports.DomainEventV1Schema = zod_1.z.discriminatedUnion('kind', [
|
|
|
274
274
|
}
|
|
275
275
|
}),
|
|
276
276
|
}),
|
|
277
|
+
exports.DomainEventEnvelopeV1Schema.extend({
|
|
278
|
+
kind: zod_1.z.literal('delivery_recorded'),
|
|
279
|
+
scope: zod_1.z.object({ runId: zod_1.z.string().min(1) }),
|
|
280
|
+
data: zod_1.z.object({
|
|
281
|
+
shas: zod_1.z.array(zod_1.z.string()),
|
|
282
|
+
prUrl: zod_1.z.string().optional(),
|
|
283
|
+
}),
|
|
284
|
+
}),
|
|
277
285
|
]);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { GitEndSnapshot, GitSnapshotPortV2 } from '../../../ports/git-snapshot.port.js';
|
|
2
|
+
export declare class LocalGitSnapshotV2 implements GitSnapshotPortV2 {
|
|
3
|
+
resolveEndSnapshot(repoRoot: string | null, startSha: string | null): Promise<GitEndSnapshot>;
|
|
4
|
+
private resolveEndSha;
|
|
5
|
+
private resolveCommitRange;
|
|
6
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LocalGitSnapshotV2 = void 0;
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const node_util_1 = require("node:util");
|
|
6
|
+
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
7
|
+
const GIT_TIMEOUT_MS = 2000;
|
|
8
|
+
class LocalGitSnapshotV2 {
|
|
9
|
+
async resolveEndSnapshot(repoRoot, startSha) {
|
|
10
|
+
if (!repoRoot)
|
|
11
|
+
return { endSha: null, commitShas: [] };
|
|
12
|
+
const [endSha, commitShas] = await Promise.all([
|
|
13
|
+
this.resolveEndSha(repoRoot),
|
|
14
|
+
this.resolveCommitRange(repoRoot, startSha),
|
|
15
|
+
]);
|
|
16
|
+
return { endSha, commitShas };
|
|
17
|
+
}
|
|
18
|
+
async resolveEndSha(repoRoot) {
|
|
19
|
+
try {
|
|
20
|
+
const { stdout } = await execFileAsync('git', ['rev-parse', 'HEAD'], { cwd: repoRoot, timeout: GIT_TIMEOUT_MS });
|
|
21
|
+
return stdout.trim() || null;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async resolveCommitRange(repoRoot, startSha) {
|
|
28
|
+
if (!startSha)
|
|
29
|
+
return [];
|
|
30
|
+
try {
|
|
31
|
+
const { stdout } = await execFileAsync('git', ['log', '--no-merges', '--first-parent', `${startSha}..HEAD`, '--format=%H'], { cwd: repoRoot, timeout: GIT_TIMEOUT_MS });
|
|
32
|
+
return stdout.trim().split('\n').filter(s => s.length > 0);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.LocalGitSnapshotV2 = LocalGitSnapshotV2;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface GitEndSnapshot {
|
|
2
|
+
readonly endSha: string | null;
|
|
3
|
+
readonly commitShas: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
export interface GitSnapshotPortV2 {
|
|
6
|
+
resolveEndSnapshot(repoRoot: string | null, startSha: string | null): Promise<GitEndSnapshot>;
|
|
7
|
+
}
|
|
8
|
+
export declare class NullGitSnapshotV2 implements GitSnapshotPortV2 {
|
|
9
|
+
resolveEndSnapshot(): Promise<GitEndSnapshot>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NullGitSnapshotV2 = void 0;
|
|
4
|
+
class NullGitSnapshotV2 {
|
|
5
|
+
async resolveEndSnapshot() {
|
|
6
|
+
return { endSha: null, commitShas: [] };
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
exports.NullGitSnapshotV2 = NullGitSnapshotV2;
|
|
@@ -52,6 +52,18 @@ function projectSessionMetricsV2(events) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
+
let deliveryShas = [];
|
|
56
|
+
for (const e of events) {
|
|
57
|
+
if (e.kind !== constants_js_1.EVENT_KIND.DELIVERY_RECORDED)
|
|
58
|
+
continue;
|
|
59
|
+
if (e.scope?.runId !== runCompletedRunId)
|
|
60
|
+
continue;
|
|
61
|
+
const shasRaw = e.data.shas;
|
|
62
|
+
if (Array.isArray(shasRaw)) {
|
|
63
|
+
deliveryShas = shasRaw.filter((s) => typeof s === 'string');
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
55
67
|
const commitShasRaw = metricsContext['metrics_commit_shas'];
|
|
56
68
|
const metricCommitShas = [];
|
|
57
69
|
if (Array.isArray(commitShasRaw)) {
|
|
@@ -60,19 +72,22 @@ function projectSessionMetricsV2(events) {
|
|
|
60
72
|
metricCommitShas.push(sha);
|
|
61
73
|
}
|
|
62
74
|
}
|
|
63
|
-
const finalAgentCommitShas =
|
|
75
|
+
const finalAgentCommitShas = deliveryShas.length > 0 ? deliveryShas :
|
|
76
|
+
metricCommitShas.length > 0 ? metricCommitShas :
|
|
77
|
+
agentCommitShas;
|
|
64
78
|
const filesChangedRaw = metricsContext['metrics_files_changed'];
|
|
65
79
|
const filesChanged = typeof filesChangedRaw === 'number' && Number.isFinite(filesChangedRaw) ? filesChangedRaw : null;
|
|
66
80
|
const linesAddedRaw = metricsContext['metrics_lines_added'];
|
|
67
81
|
const linesAdded = typeof linesAddedRaw === 'number' && Number.isFinite(linesAddedRaw) ? linesAddedRaw : null;
|
|
68
82
|
const linesRemovedRaw = metricsContext['metrics_lines_removed'];
|
|
69
83
|
const linesRemoved = typeof linesRemovedRaw === 'number' && Number.isFinite(linesRemovedRaw) ? linesRemovedRaw : null;
|
|
84
|
+
const finalCaptureConfidence = deliveryShas.length > 0 ? 'high' : captureConfidence;
|
|
70
85
|
return {
|
|
71
86
|
startGitSha,
|
|
72
87
|
endGitSha,
|
|
73
88
|
gitBranch,
|
|
74
89
|
agentCommitShas: finalAgentCommitShas,
|
|
75
|
-
captureConfidence,
|
|
90
|
+
captureConfidence: finalCaptureConfidence,
|
|
76
91
|
durationMs,
|
|
77
92
|
outcome,
|
|
78
93
|
prNumbers,
|