@kitman-sh/cli 0.9.0 → 0.10.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/chunk-11p4wf6n.js +3551 -0
  2. package/dist/chunk-1mc9vgcr.js +39 -0
  3. package/dist/chunk-30397r95.js +30 -0
  4. package/dist/chunk-3bj7sc3v.js +389 -0
  5. package/dist/chunk-6vns3ej0.js +23 -0
  6. package/dist/chunk-7thnf14y.js +936 -0
  7. package/dist/chunk-arvwar2c.js +141 -0
  8. package/dist/chunk-b6thzgc9.js +32 -0
  9. package/dist/{chunk-8bvf4fh4.js → chunk-ctasxxz5.js} +26 -11
  10. package/dist/{chunk-5gjpv3ax.js → chunk-dzh9e6n2.js} +824 -651
  11. package/dist/{chunk-snn0e1qb.js → chunk-eg8f5ncv.js} +7 -3
  12. package/dist/chunk-g5bs3f6z.js +173 -0
  13. package/dist/chunk-jafetf7z.js +109 -0
  14. package/dist/chunk-jagzz148.js +527 -0
  15. package/dist/{chunk-1d4316hp.js → chunk-jfvq7s24.js} +38 -25
  16. package/dist/chunk-mbctzx7e.js +11436 -0
  17. package/dist/chunk-mej2bx5n.js +100 -0
  18. package/dist/chunk-p6spvbwq.js +6305 -0
  19. package/dist/chunk-pp1p3g6e.js +133 -0
  20. package/dist/chunk-r8p3nxcp.js +231 -0
  21. package/dist/chunk-txwt6r25.js +1731 -0
  22. package/dist/chunk-v290mf51.js +5242 -0
  23. package/dist/chunk-vjmz23rs.js +13 -0
  24. package/dist/chunk-vyv0p5eq.js +3183 -0
  25. package/dist/chunk-wh1pa2aa.js +15322 -0
  26. package/dist/chunk-x0b92bjb.js +222 -0
  27. package/dist/{chunk-8z5b6fpd.js → chunk-x9dhxfts.js} +216 -152
  28. package/dist/chunk-z821b2gp.js +164 -0
  29. package/dist/index.js +13 -5738
  30. package/dist/opencode-reader.main.ts +4 -0
  31. package/package.json +6 -5
  32. package/dist/chunk-3gxahgnq.js +0 -28495
  33. package/dist/chunk-ehzbtavj.js +0 -247
  34. package/dist/chunk-f5z8tgss.js +0 -1214
  35. package/dist/chunk-kdb1cbnx.js +0 -1273
  36. package/dist/chunk-ke1w0hx7.js +0 -5771
  37. package/dist/chunk-z6hc4ew9.js +0 -13
@@ -0,0 +1,1731 @@
1
+ // @bun
2
+ import {
3
+ dual,
4
+ hasProperty,
5
+ Prototype,
6
+ isNone,
7
+ Service2,
8
+ empty3,
9
+ add,
10
+ getOrUndefined2,
11
+ get4,
12
+ merge3,
13
+ Reference,
14
+ fromInputUnsafe,
15
+ toMillis,
16
+ TaggedClass,
17
+ encode,
18
+ isSuccess2,
19
+ addFinalizerExit,
20
+ effectDiscard,
21
+ hasInterruptsOnly,
22
+ combine2,
23
+ squash,
24
+ hasInterrupts2,
25
+ min2,
26
+ exponential,
27
+ spaced,
28
+ while_,
29
+ setInputType,
30
+ promise,
31
+ succeed6,
32
+ suspend3,
33
+ sync2,
34
+ void_3,
35
+ callback3,
36
+ gen,
37
+ fail7,
38
+ failCause3,
39
+ die3,
40
+ try_2,
41
+ yieldNow,
42
+ flatMap3,
43
+ andThen2,
44
+ tap2,
45
+ map8,
46
+ catch_,
47
+ catchTag,
48
+ mapError2,
49
+ orDie,
50
+ retry,
51
+ sandbox,
52
+ matchEffect2,
53
+ context,
54
+ contextWith,
55
+ provideContext2,
56
+ provideService,
57
+ acquireUseRelease,
58
+ onExit,
59
+ interruptible,
60
+ uninterruptibleMask2,
61
+ annotateCurrentSpan,
62
+ withSpan,
63
+ fnUntraced,
64
+ encode3,
65
+ transform,
66
+ encodeBase64Url,
67
+ decodeBase64UrlString,
68
+ transform2,
69
+ declare,
70
+ decodeUnknownEffect2,
71
+ decodeEffect,
72
+ decodeSync,
73
+ encodeUnknownEffect,
74
+ encodeEffect,
75
+ encodeSync,
76
+ isSchema,
77
+ optionalKey,
78
+ optional,
79
+ Literal,
80
+ Never,
81
+ Unknown,
82
+ Null,
83
+ String4,
84
+ Boolean2,
85
+ Void,
86
+ Struct,
87
+ Record,
88
+ Tuple2,
89
+ ArraySchema,
90
+ NonEmptyArray,
91
+ Union,
92
+ Literals,
93
+ decodeTo2,
94
+ tag,
95
+ makeFilter,
96
+ isPattern,
97
+ Finite,
98
+ isGreaterThanOrEqualTo,
99
+ isLessThanOrEqualTo,
100
+ Int,
101
+ isMinLength,
102
+ isMaxLength,
103
+ Defect,
104
+ fromJsonString,
105
+ Cause,
106
+ Exit,
107
+ Class2,
108
+ TaggedError2,
109
+ toEquivalence,
110
+ toJsonSchemaDocument,
111
+ toCodecJson,
112
+ Json
113
+ } from "./chunk-mbctzx7e.js";
114
+ import {
115
+ WebCrypto,
116
+ SafeJson,
117
+ AgentSandboxNetwork,
118
+ AgentEfforts,
119
+ AgentCapabilities,
120
+ recommendedDefault,
121
+ LoopDataSchemaRef,
122
+ LoopVersion,
123
+ ProgramLoop,
124
+ AgentFallback,
125
+ MeasureEvidence,
126
+ CatchUp,
127
+ ClaimResult
128
+ } from "./chunk-wh1pa2aa.js";
129
+ import {
130
+ getCurrent
131
+ } from "./chunk-11p4wf6n.js";
132
+ import {
133
+ guard
134
+ } from "./chunk-pp1p3g6e.js";
135
+ import {
136
+ splitQuestionOptions,
137
+ recommendationProblem,
138
+ questionAdvice
139
+ } from "./chunk-1mc9vgcr.js";
140
+ import {
141
+ KitName,
142
+ KitDigest
143
+ } from "./chunk-z821b2gp.js";
144
+
145
+ // node_modules/.bun/effect@4.1.2/node_modules/effect/dist/crypto/internal/webCrypto.js
146
+ var subtleUnavailable = () => new Error("crypto.subtle is unavailable; browsers expose it only in secure contexts");
147
+
148
+ // node_modules/.bun/effect@4.1.2/node_modules/effect/dist/crypto/internal/digest.js
149
+ var webCryptoDigest = (crypto, algorithm, data) => {
150
+ const implementation = algorithm.implementation;
151
+ if (implementation !== undefined) {
152
+ return sync2(() => implementation(data));
153
+ }
154
+ return suspend3(() => {
155
+ const subtle = crypto?.subtle;
156
+ if (subtle === undefined)
157
+ return die3(subtleUnavailable());
158
+ return promise(async () => new Uint8Array(await subtle.digest(algorithm.name, data)));
159
+ });
160
+ };
161
+
162
+ // node_modules/.bun/effect@4.1.2/node_modules/effect/dist/crypto/Digest.js
163
+ var sha256 = {
164
+ name: "SHA-256",
165
+ outputLength: 32,
166
+ implementation: undefined
167
+ };
168
+
169
+ // packages/core/src/schedule.ts
170
+ var ScheduleFrequency = ["daily", "weekly"];
171
+ var ScheduleMisfirePolicies = ["skip", "fire_once", "catch_up"];
172
+ var ScheduleOverlapPolicies = ["allow", "skip", "coalesce"];
173
+ var ScheduleVersionStatuses = ["draft", "published", "disabled", "archived"];
174
+ var ScheduleCalendarRule = Struct({
175
+ frequency: Literals(ScheduleFrequency),
176
+ hour: Int.check(isGreaterThanOrEqualTo(0), isLessThanOrEqualTo(23)),
177
+ minute: Int.check(isGreaterThanOrEqualTo(0), isLessThanOrEqualTo(59)),
178
+ second: optionalKey(Int.check(isGreaterThanOrEqualTo(0), isLessThanOrEqualTo(59))),
179
+ daysOfWeek: optionalKey(ArraySchema(Int.check(isGreaterThanOrEqualTo(0), isLessThanOrEqualTo(6))).check(isMinLength(1), isMaxLength(7)))
180
+ });
181
+ var ScheduleCronRule = Struct({
182
+ cron: String4.check(isMinLength(9), isMaxLength(200), isPattern(new RegExp("^[0-9*,/-]+( [0-9*,/-]+){4}$", "u")))
183
+ });
184
+ var ScheduleRule = Union([ScheduleCalendarRule, ScheduleCronRule]);
185
+ var cronBounds = [
186
+ [0, 59],
187
+ [0, 23],
188
+ [1, 31],
189
+ [1, 12],
190
+ [0, 7]
191
+ ];
192
+ function cronField(field, [min, max]) {
193
+ const values = new Set;
194
+ for (const part of field.split(",")) {
195
+ const match = /^(\*|(\d+)(?:-(\d+))?)(?:\/(\d+))?$/.exec(part);
196
+ if (match === null)
197
+ return;
198
+ const from = match[1] === "*" ? min : Number(match[2]);
199
+ const to = match[1] === "*" ? max : match[3] === undefined ? match[4] === undefined ? from : max : Number(match[3]);
200
+ const step = match[4] === undefined ? 1 : Number(match[4]);
201
+ if (from < min || to > max || from > to || step < 1)
202
+ return;
203
+ for (let value = from;value <= to; value += step)
204
+ values.add(value);
205
+ }
206
+ return values;
207
+ }
208
+ function parseCron(cron) {
209
+ const fields = cron.split(" ");
210
+ const [minutes, hours, days, months, weekdays] = fields.map((field, index) => cronField(field, cronBounds[index] ?? [0, 0]));
211
+ if (fields.length !== 5 || !minutes || !hours || !days || !months || !weekdays)
212
+ return;
213
+ return {
214
+ minutes,
215
+ hours,
216
+ days,
217
+ months,
218
+ weekdays: new Set([...weekdays].map((value) => value % 7)),
219
+ dayRestricted: !(fields[2] ?? "").startsWith("*"),
220
+ weekdayRestricted: !(fields[4] ?? "").startsWith("*")
221
+ };
222
+ }
223
+ function isScheduleRule(value) {
224
+ return guard(ScheduleRule)(value) && (!("cron" in value) || parseCron(value.cron) !== undefined);
225
+ }
226
+ var ScheduleVersion = Struct({
227
+ contractVersion: Literal("schedule.v1"),
228
+ id: String4.check(isMinLength(1)),
229
+ scheduleId: String4.check(isMinLength(1)),
230
+ workspaceId: String4.check(isMinLength(1)),
231
+ teamId: optionalKey(String4.check(isMinLength(1))),
232
+ loopId: optionalKey(String4.check(isMinLength(1))),
233
+ name: optionalKey(String4.check(isMinLength(1), isMaxLength(200))),
234
+ version: Int.check(isGreaterThanOrEqualTo(1)),
235
+ status: Literals(ScheduleVersionStatuses),
236
+ timezone: String4.check(isMinLength(1), isMaxLength(80)),
237
+ rule: ScheduleRule,
238
+ misfirePolicy: Literals(ScheduleMisfirePolicies),
239
+ overlapPolicy: Literals(ScheduleOverlapPolicies),
240
+ maxCatchUp: Int.check(isGreaterThanOrEqualTo(0), isLessThanOrEqualTo(200)),
241
+ misfireGraceSeconds: optionalKey(Int.check(isGreaterThanOrEqualTo(0), isLessThanOrEqualTo(604800))),
242
+ inputSchemaRef: optionalKey(LoopDataSchemaRef),
243
+ input: optionalKey(SafeJson),
244
+ createdAt: String4.check(isMinLength(1))
245
+ });
246
+ var zones = new Map;
247
+ var resolvedLocalDateTimes = new Map;
248
+
249
+ // packages/core/src/kit-declarations.ts
250
+ var LoopCapabilities = [
251
+ "agent_work",
252
+ "ask",
253
+ "call",
254
+ "verify",
255
+ "change_request",
256
+ "write_back",
257
+ "post_comment",
258
+ "create_tasks",
259
+ "merge_change_request",
260
+ "approve_change_request",
261
+ "publish_release",
262
+ "read_transcripts",
263
+ "read_change_request",
264
+ "measure",
265
+ "claim",
266
+ "propose",
267
+ "read_project",
268
+ "draft_update"
269
+ ];
270
+ var JsonObject = Record(String4, Json);
271
+ var SecretName = String4.check(isPattern(/^[A-Za-z_][A-Za-z0-9_]{0,127}$/));
272
+ var EventFilterValue = Union([String4, Finite, Boolean2, Null]);
273
+ var LoopManifest = Struct({
274
+ id: String4,
275
+ title: String4,
276
+ version: optionalKey(LoopVersion),
277
+ input: JsonObject,
278
+ output: JsonObject,
279
+ outcome: optionalKey(Literals(["feature", "bug", "refactor", "investigation", "docs", "migration", "performance"])),
280
+ agents: Record(String4, String4),
281
+ checkout: Literals(["none", "read", "write"]),
282
+ when: ArraySchema(Struct({
283
+ event: String4,
284
+ filter: optionalKey(Record(String4, Union([EventFilterValue, ArraySchema(EventFilterValue)]))),
285
+ input: Record(String4, String4),
286
+ values: optionalKey(JsonObject)
287
+ })),
288
+ offers: ArraySchema(Struct({
289
+ id: String4,
290
+ title: String4,
291
+ loop: String4,
292
+ from: optionalKey(String4)
293
+ })),
294
+ capabilities: ArraySchema(Literals(LoopCapabilities)),
295
+ secrets: optionalKey(ArraySchema(SecretName)),
296
+ network: optionalKey(AgentSandboxNetwork),
297
+ schedule: optionalKey(Struct({ rule: ScheduleRule, timezone: String4 }))
298
+ });
299
+ var LoopDetail = Struct({
300
+ id: String4,
301
+ resolved: optionalKey(Struct({
302
+ ...ProgramLoop.fields,
303
+ agents: LoopManifest.fields.agents,
304
+ when: LoopManifest.fields.when,
305
+ schedule: optionalKey(Struct({
306
+ rule: ScheduleRule,
307
+ timezone: String4,
308
+ on: Boolean2,
309
+ nextRunAt: optionalKey(String4)
310
+ }))
311
+ }))
312
+ });
313
+ var AgentDeclaration = Struct({
314
+ extends: optionalKey(String4),
315
+ instructions: optionalKey(String4),
316
+ harness: optionalKey(String4),
317
+ model: optionalKey(String4),
318
+ effort: optionalKey(Literals(AgentEfforts)),
319
+ fallbacks: optionalKey(ArraySchema(AgentFallback)),
320
+ tools: optionalKey(ArraySchema(Literals(AgentCapabilities))),
321
+ skills: optionalKey(ArraySchema(String4.check(isMinLength(1)))),
322
+ network: optionalKey(Union([Struct({ hosts: ArraySchema(String4) }), Literal("open")])),
323
+ sandbox: optionalKey(Literal("docker"))
324
+ });
325
+ var scheduleFields = {
326
+ name: String4.check(isMinLength(1)),
327
+ loop: String4,
328
+ team: optionalKey(String4),
329
+ input: optionalKey(JsonObject),
330
+ timezone: String4,
331
+ misfire: optionalKey(Literals(ScheduleMisfirePolicies)),
332
+ overlap: optionalKey(Literals(ScheduleOverlapPolicies))
333
+ };
334
+ var ScheduleDeclaration = Union([
335
+ Struct({
336
+ ...scheduleFields,
337
+ cron: String4.check(makeFilter((cron) => isScheduleRule({ cron }) || "five cron fields, each within its range"))
338
+ }),
339
+ Struct({
340
+ ...scheduleFields,
341
+ rule: declare((value) => isScheduleRule(value), {
342
+ expected: "a Schedule rule: frequency daily or weekly, hour, minute, and optionally second and daysOfWeek"
343
+ })
344
+ })
345
+ ]);
346
+ var CarriedKit = Struct({
347
+ name: KitName,
348
+ version: String4.check(isMinLength(1)),
349
+ setup: KitDigest,
350
+ loops: ArraySchema(String4),
351
+ agents: ArraySchema(String4)
352
+ });
353
+ var KitDeclarations = Struct({
354
+ loops: ArraySchema(LoopManifest),
355
+ agents: Record(String4, AgentDeclaration),
356
+ schedules: optionalKey(Record(String4, ScheduleDeclaration)),
357
+ carried: optionalKey(ArraySchema(CarriedKit))
358
+ });
359
+ var sameLoop = toEquivalence(LoopManifest);
360
+ var sameAgent = toEquivalence(AgentDeclaration);
361
+
362
+ // packages/sdk/src/loop/define.ts
363
+ var LoopOutcome = Literals([
364
+ "feature",
365
+ "bug",
366
+ "refactor",
367
+ "investigation",
368
+ "docs",
369
+ "migration",
370
+ "performance"
371
+ ]);
372
+ var defineLoop = (definition) => definition;
373
+
374
+ class ManifestInvalid extends TaggedError2()("ManifestInvalid", {
375
+ loop: String4,
376
+ message: String4
377
+ }) {
378
+ }
379
+ var jsonSchemaOf = (loop, schema) => try_2({
380
+ try: () => toJsonSchemaDocument(schema),
381
+ catch: (error) => new ManifestInvalid({ loop, message: `Schema has no JSON Schema: ${String(error)}` })
382
+ }).pipe(flatMap3((document) => decodeUnknownEffect2(JsonObjectSchema)({ ...document.schema, $defs: document.definitions }).pipe(mapError2((error) => new ManifestInvalid({ loop, message: error.message })))));
383
+ var JsonObjectSchema = Record(String4, Json);
384
+ // node_modules/.bun/effect@4.1.2/node_modules/effect/dist/workflow/internal/crypto.js
385
+ var encoder = /* @__PURE__ */ new TextEncoder;
386
+ var makeHashDigest = (original) => WebCrypto.use((crypto) => map8(webCryptoDigest(crypto, sha256, encoder.encode(original)), (bytes) => encode(bytes).slice(0, 32)));
387
+
388
+ // node_modules/.bun/effect@4.1.2/node_modules/effect/dist/workflow/Workflow.js
389
+ var TypeId = "~effect/workflow/Workflow";
390
+ var EngineTag = /* @__PURE__ */ Service2("effect/workflow/WorkflowEngine");
391
+ var InstanceTag = /* @__PURE__ */ Service2("effect/workflow/WorkflowEngine/WorkflowInstance");
392
+ var makeExecutionIdFromPayload = (self, payload) => makeHashDigest(`${self._tag.length}:${self._tag}:${self.idempotencyKey(payload)}`);
393
+ var Proto = {
394
+ [TypeId]: TypeId,
395
+ annotate(tag, value) {
396
+ return makeProto({
397
+ _tag: this._tag,
398
+ payloadSchema: this.payloadSchema,
399
+ successSchema: this.successSchema,
400
+ errorSchema: this.errorSchema,
401
+ annotations: add(this.annotations, tag, value),
402
+ idempotencyKey: this.idempotencyKey,
403
+ suspendedRetrySchedule: this.suspendedRetrySchedule
404
+ });
405
+ },
406
+ annotateMerge(context) {
407
+ return makeProto({
408
+ _tag: this._tag,
409
+ payloadSchema: this.payloadSchema,
410
+ successSchema: this.successSchema,
411
+ errorSchema: this.errorSchema,
412
+ annotations: merge3(this.annotations, context),
413
+ idempotencyKey: this.idempotencyKey,
414
+ suspendedRetrySchedule: this.suspendedRetrySchedule
415
+ });
416
+ },
417
+ execute(fields, opts) {
418
+ return suspend3(() => {
419
+ const payload = this.payloadSchema.make(fields);
420
+ const run = flatMap3(EngineTag, (engine) => flatMap3(makeExecutionIdFromPayload(this, payload), (executionId) => andThen2(annotateCurrentSpan({
421
+ executionId
422
+ }), engine.execute(this, {
423
+ executionId,
424
+ payload,
425
+ discard: opts?.discard,
426
+ detached: opts?.detached,
427
+ suspendedRetrySchedule: this.suspendedRetrySchedule
428
+ }))));
429
+ return opts?.discard ? run : withPendingActivity(run);
430
+ }).pipe(withSpan(`${this._tag}.execute`, {}, {
431
+ captureStackTrace: false
432
+ }));
433
+ },
434
+ poll(executionId) {
435
+ return flatMap3(EngineTag, (engine) => engine.poll(this, executionId)).pipe(withSpan(`${this._tag}.poll`, {
436
+ attributes: {
437
+ executionId
438
+ }
439
+ }, {
440
+ captureStackTrace: false
441
+ }));
442
+ },
443
+ interrupt(executionId) {
444
+ return flatMap3(EngineTag, (engine) => engine.interrupt(this, executionId)).pipe(withSpan(`${this._tag}.interrupt`, {
445
+ attributes: {
446
+ executionId
447
+ }
448
+ }, {
449
+ captureStackTrace: false
450
+ }));
451
+ },
452
+ resume(executionId) {
453
+ return flatMap3(EngineTag, (engine) => engine.resume(this, executionId)).pipe(withSpan(`${this._tag}.resume`, {
454
+ attributes: {
455
+ executionId
456
+ }
457
+ }, {
458
+ captureStackTrace: false
459
+ }));
460
+ },
461
+ toLayer(execute) {
462
+ return effectDiscard(flatMap3(EngineTag, (engine) => engine.register(this, execute)));
463
+ },
464
+ executionId(payload) {
465
+ return flatMap3(orDie(this.payloadSchema.makeEffect(payload)), (payload) => makeExecutionIdFromPayload(this, payload));
466
+ },
467
+ withCompensation: (...args) => withCompensation(...args)
468
+ };
469
+ var makeProto = (options) => {
470
+ function Workflow() {}
471
+ Object.setPrototypeOf(Workflow, Proto);
472
+ Object.assign(Workflow, options);
473
+ return Workflow;
474
+ };
475
+ var make14 = (tag, options) => makeProto({
476
+ _tag: tag,
477
+ payloadSchema: isSchema(options.payload) ? options.payload : Struct(options.payload),
478
+ successSchema: options.success ?? Void,
479
+ errorSchema: options.error ?? Never,
480
+ annotations: options.annotations ?? empty3(),
481
+ idempotencyKey: options.idempotencyKey,
482
+ suspendedRetrySchedule: options.suspendedRetrySchedule
483
+ });
484
+ var ResultTypeId = "~effect/workflow/Workflow/Result";
485
+ var isResult = (u) => hasProperty(u, ResultTypeId);
486
+ class Suspended extends (/* @__PURE__ */ Class2("effect/workflow/Workflow/Suspended")({
487
+ _tag: /* @__PURE__ */ tag("Suspended"),
488
+ cause: /* @__PURE__ */ optional(/* @__PURE__ */ Cause(Never, /* @__PURE__ */ Defect())),
489
+ failed: /* @__PURE__ */ optional(Boolean2)
490
+ })) {
491
+ [ResultTypeId] = ResultTypeId;
492
+ }
493
+ var wrapActivityResult = (effect, isSuspend) => contextWith((context) => {
494
+ const instance = get4(context, InstanceTag);
495
+ return acquireUseRelease(sync2(() => adoptActivityUnsafe(context, instance) ?? registerActivityUnsafe(instance)), () => effect, (registration, exit) => {
496
+ releaseActivityUnsafe(registration);
497
+ const isSuspended = isSuccess2(exit) && isSuspend(exit.value);
498
+ if (isSuccess2(exit) && isResult(exit.value) && exit.value._tag === "Suspended" && exit.value.cause) {
499
+ instance.cause = instance.cause ? combine2(instance.cause, exit.value.cause) : exit.value.cause;
500
+ }
501
+ return isSuspended && instance.activityState.count > 0 ? waitForZero(instance) : void_3;
502
+ });
503
+ });
504
+ var PendingActivityRegistration = /* @__PURE__ */ Service2("effect/workflow/Workflow/PendingActivityRegistration");
505
+ var registerActivityUnsafe = (instance) => {
506
+ const state = instance.activityState;
507
+ if (state.count === 0)
508
+ state.latch.closeUnsafe();
509
+ state.count++;
510
+ return {
511
+ instance,
512
+ state: "pending"
513
+ };
514
+ };
515
+ var adoptActivityUnsafe = (context, instance) => {
516
+ const pending = getOrUndefined2(context, PendingActivityRegistration);
517
+ if (!pending || pending.instance !== instance) {
518
+ return;
519
+ }
520
+ if (pending.state !== "pending") {
521
+ throw new Error("Workflow.wrapActivityResult: pending child registration has already been consumed");
522
+ }
523
+ pending.state = "adopted";
524
+ return pending;
525
+ };
526
+ var releaseActivityUnsafe = (registration) => {
527
+ if (registration.state === "released")
528
+ return;
529
+ registration.state = "released";
530
+ const state = registration.instance.activityState;
531
+ state.count--;
532
+ if (state.count === 0)
533
+ state.latch.openUnsafe();
534
+ };
535
+ var withPendingActivity = (effect) => contextWith((context) => {
536
+ const instance = getOrUndefined2(context, InstanceTag);
537
+ if (!instance)
538
+ return effect;
539
+ return acquireUseRelease(sync2(() => registerActivityUnsafe(instance)), (registration) => provideService(effect, PendingActivityRegistration, registration), (registration) => sync2(() => releaseActivityUnsafe(registration)));
540
+ });
541
+ var waitForZero = /* @__PURE__ */ fnUntraced(function* (instance) {
542
+ const state = instance.activityState;
543
+ while (true) {
544
+ if (state.count > 0) {
545
+ yield* state.latch.await;
546
+ yield* yieldNow;
547
+ continue;
548
+ }
549
+ yield* yieldNow;
550
+ if (state.count === 0)
551
+ return;
552
+ }
553
+ });
554
+ var addFinalizer = /* @__PURE__ */ fnUntraced(function* (f) {
555
+ const instance = yield* InstanceTag;
556
+ const services = yield* context();
557
+ yield* addFinalizerExit(instance.scope, (exit) => instance.abandoned ? void_3 : provideContext2(f(exit), services));
558
+ });
559
+ var withCompensation = /* @__PURE__ */ dual(2, (effect, compensation) => uninterruptibleMask2((restore) => tap2(restore(effect), (value) => addFinalizer((exit) => isSuccess2(exit) ? void_3 : compensation(value, exit.cause)))));
560
+ var suspend = (instance) => interruptible(callback3(() => {
561
+ instance.suspended = true;
562
+ const fiber = getCurrent();
563
+ fiber.interruptUnsafe(fiber.id);
564
+ }));
565
+
566
+ // node_modules/.bun/effect@4.1.2/node_modules/effect/dist/workflow/DurableDeferred.js
567
+ var TypeId2 = "~effect/workflow/DurableDeferred";
568
+ var make = (name, options) => {
569
+ const successSchema = options?.success ?? Void;
570
+ const errorSchema = options?.error ?? Never;
571
+ return {
572
+ [TypeId2]: TypeId2,
573
+ name,
574
+ successSchema,
575
+ errorSchema,
576
+ exitSchema: Exit(toCodecJson(successSchema), toCodecJson(errorSchema), toCodecJson(Defect())),
577
+ withActivityAttempt: gen(function* () {
578
+ const attempt = yield* CurrentAttempt;
579
+ return make(`${name}/${attempt}`, {
580
+ success: successSchema,
581
+ error: errorSchema
582
+ });
583
+ })
584
+ };
585
+ };
586
+ var EngineTag2 = /* @__PURE__ */ Service2("effect/workflow/WorkflowEngine");
587
+ var InstanceTag2 = /* @__PURE__ */ Service2("effect/workflow/WorkflowEngine/WorkflowInstance");
588
+ var CurrentAttempt = /* @__PURE__ */ Reference("effect/workflow/Activity/CurrentAttempt", {
589
+ defaultValue: () => 1
590
+ });
591
+ var awaitOwners = /* @__PURE__ */ new WeakMap;
592
+ var registerAwait = (instance, name) => {
593
+ instance.awaitedDeferreds.set(name, (instance.awaitedDeferreds.get(name) ?? 0) + 1);
594
+ awaitOwners.get(instance)?.push(name);
595
+ };
596
+ var await_ = /* @__PURE__ */ fnUntraced(function* (self) {
597
+ const engine = yield* EngineTag2;
598
+ const instance = yield* InstanceTag2;
599
+ registerAwait(instance, self.name);
600
+ const exit = yield* wrapActivityResult(engine.deferredResult(self), isNone);
601
+ if (isNone(exit)) {
602
+ return yield* suspend(instance);
603
+ }
604
+ return yield* exit.value;
605
+ });
606
+ class TokenParsed extends (/* @__PURE__ */ Class2("effect/workflow/DurableDeferred/TokenParsed")({
607
+ workflowName: String4,
608
+ executionId: String4,
609
+ deferredName: String4
610
+ })) {
611
+ get asToken() {
612
+ return encode3(JSON.stringify([this.workflowName, this.executionId, this.deferredName]));
613
+ }
614
+ static FromString = /* @__PURE__ */ String4.pipe(/* @__PURE__ */ decodeTo2(/* @__PURE__ */ fromJsonString(/* @__PURE__ */ Tuple2([String4, String4, String4])), {
615
+ decode: /* @__PURE__ */ decodeBase64UrlString(),
616
+ encode: /* @__PURE__ */ encodeBase64Url()
617
+ }), /* @__PURE__ */ decodeTo2(TokenParsed, {
618
+ decode: /* @__PURE__ */ transform(([workflowName, executionId, deferredName]) => new TokenParsed({
619
+ workflowName,
620
+ executionId,
621
+ deferredName
622
+ })),
623
+ encode: /* @__PURE__ */ transform((parsed) => [parsed.workflowName, parsed.executionId, parsed.deferredName])
624
+ }));
625
+ static fromString = /* @__PURE__ */ decodeSync(TokenParsed.FromString);
626
+ static encode = /* @__PURE__ */ encodeSync(TokenParsed.FromString);
627
+ }
628
+ var token = /* @__PURE__ */ fnUntraced(function* (self) {
629
+ const instance = yield* InstanceTag2;
630
+ return tokenFromExecutionId(self, instance);
631
+ });
632
+ var tokenFromExecutionId = /* @__PURE__ */ dual(2, (self, options) => new TokenParsed({
633
+ workflowName: options.workflow._tag,
634
+ executionId: options.executionId,
635
+ deferredName: self.name
636
+ }).asToken);
637
+
638
+ // node_modules/.bun/effect@4.1.2/node_modules/effect/dist/workflow/Activity.js
639
+ var TypeId3 = "~effect/workflow/Activity";
640
+ var make2 = (options) => {
641
+ const successSchema = options.success ?? Void;
642
+ const errorSchema = options.error ?? Never;
643
+ const successSchemaJson = toCodecJson(successSchema);
644
+ const errorSchemaJson = toCodecJson(errorSchema);
645
+ let execute;
646
+ const executeWithoutInterrupt = retryOnInterrupt(options.name, options.interruptRetryPolicy)(options.execute);
647
+ const self = {
648
+ ...Prototype({
649
+ label: "Activity",
650
+ evaluate(_) {
651
+ return execute;
652
+ }
653
+ }),
654
+ [TypeId3]: TypeId3,
655
+ name: options.name,
656
+ successSchema,
657
+ errorSchema,
658
+ exitSchema: Exit(successSchemaJson, errorSchemaJson, Defect()),
659
+ exitSchemaPartial: Exit(successSchemaJson, errorSchemaJson, Unknown),
660
+ annotations: options.annotations ?? empty3(),
661
+ annotate(tag, value) {
662
+ return make2({
663
+ ...options,
664
+ annotations: add(self.annotations, tag, value)
665
+ });
666
+ },
667
+ annotateMerge(context) {
668
+ return make2({
669
+ ...options,
670
+ annotations: merge3(self.annotations, context)
671
+ });
672
+ },
673
+ execute: executeWithoutInterrupt,
674
+ executeEncoded: matchEffect2(executeWithoutInterrupt, {
675
+ onFailure: (error) => flatMap3(orDie(encodeEffect(errorSchemaJson)(error)), fail7),
676
+ onSuccess: (value) => orDie(encodeEffect(successSchemaJson)(value))
677
+ })
678
+ };
679
+ execute = makeExecute(self);
680
+ return self;
681
+ };
682
+ var interruptRetryPolicy = /* @__PURE__ */ min2([exponential(400, 1.5), spaced("10 seconds")]).pipe(/* @__PURE__ */ setInputType(), /* @__PURE__ */ while_((meta) => meta.attempt <= 10 && hasInterrupts2(meta.input)));
683
+ var retryOnInterrupt = (name, policy = interruptRetryPolicy) => (effect) => flatMap3(InstanceTag3, (instance) => effect.pipe(sandbox, retry({
684
+ schedule: policy,
685
+ while: () => !instance.suspended
686
+ }), catch_((cause) => hasInterrupts2(cause) && !instance.suspended ? die3(`Activity "${name}" interrupted and retry attempts exhausted`) : failCause3(cause))));
687
+ var CurrentAttempt2 = /* @__PURE__ */ Reference("effect/workflow/Activity/CurrentAttempt", {
688
+ defaultValue: () => 1
689
+ });
690
+ var EngineTag3 = /* @__PURE__ */ Service2("effect/workflow/WorkflowEngine");
691
+ var InstanceTag3 = /* @__PURE__ */ Service2("effect/workflow/WorkflowEngine/WorkflowInstance");
692
+ var makeExecute = /* @__PURE__ */ fnUntraced(function* (activity) {
693
+ const engine = yield* EngineTag3;
694
+ const instance = yield* InstanceTag3;
695
+ const attempt = yield* CurrentAttempt2;
696
+ yield* annotateCurrentSpan({
697
+ executionId: instance.executionId
698
+ });
699
+ const result = yield* wrapActivityResult(engine.activityExecute(activity, attempt), (_) => _._tag === "Suspended");
700
+ if (result._tag === "Suspended") {
701
+ if (result.failed)
702
+ instance.failed = true;
703
+ return yield* suspend(instance);
704
+ }
705
+ return yield* result.exit;
706
+ }, (effect, activity) => withSpan(effect, activity.name, {
707
+ captureStackTrace: false
708
+ }));
709
+ // packages/sdk/src/loop/evidence.ts
710
+ var EvidenceCheck = Struct({
711
+ name: String4,
712
+ command: String4,
713
+ status: Literals(["passed", "failed"]),
714
+ preExisting: Boolean2,
715
+ durationMs: Finite,
716
+ evidenceId: String4,
717
+ outputTail: optionalKey(String4),
718
+ suggested: optionalKey(Boolean2)
719
+ });
720
+ var VerifyResult = Struct({
721
+ revision: String4,
722
+ tree: String4,
723
+ passed: Boolean2,
724
+ unchanged: optionalKey(Boolean2),
725
+ checks: ArraySchema(EvidenceCheck)
726
+ });
727
+ var verdict = (reasons) => reasons.length === 0 ? { settled: true } : { settled: false, reasons };
728
+ var missing = (side) => `No verification evidence for the ${side}`;
729
+ var failsOn = (side, name, tree) => `${name} fails on the ${side} tree ${tree}`;
730
+ var allPass = (side, result) => {
731
+ if (result === undefined)
732
+ return [missing(side)];
733
+ if (result.checks.length === 0)
734
+ return [`No approved verification ran on the ${side} tree ${result.tree}`];
735
+ return result.checks.filter((check) => check.status === "failed" && !check.preExisting).map((check) => failsOn(side, check.name, result.tree));
736
+ };
737
+ var checkOn = (side, result, name) => {
738
+ if (result === undefined)
739
+ return { reason: missing(side) };
740
+ if (name === undefined)
741
+ return { reason: `No check was named for the ${side}` };
742
+ const found = result.checks.find((check) => check.name === name);
743
+ return found === undefined ? { reason: `No evidence for ${name} on the ${side} tree ${result.tree}` } : { found };
744
+ };
745
+ var passesOnHead = (head, name) => {
746
+ const { found, reason } = checkOn("head", head, name);
747
+ if (found === undefined)
748
+ return [reason];
749
+ return found.status === "passed" ? [] : [failsOn("head", found.name, head?.tree)];
750
+ };
751
+ var bugReasons = (input) => {
752
+ const base = checkOn("base", input.base, input.reproducing);
753
+ const head = checkOn("head", input.head, input.reproducing);
754
+ return [
755
+ ...base.found === undefined ? [base.reason] : base.found.status === "failed" ? [] : [`${base.found.name} does not fail on the base tree ${input.base?.tree}, so the bug is not reproduced`],
756
+ ...head.found === undefined ? [head.reason] : head.found.status === "passed" ? [] : [failsOn("head", head.found.name, input.head?.tree)]
757
+ ];
758
+ };
759
+ var conclusionReasons = (conclusion) => {
760
+ if (conclusion === undefined || conclusion.text.trim() === "")
761
+ return ["No conclusion was given"];
762
+ return conclusion.sources.length === 0 ? ["The conclusion names no sources"] : [];
763
+ };
764
+ var scopeReasons = (scope) => {
765
+ if (scope === undefined)
766
+ return ["Review has not judged the scope"];
767
+ if (scope.met)
768
+ return [];
769
+ return scope.unmet.length === 0 ? ["Review found the scope unmet"] : scope.unmet.map((item) => `Review found the scope unmet: ${item}`);
770
+ };
771
+ var evidenceGate = (input) => {
772
+ switch (input.outcome) {
773
+ case "feature":
774
+ return verdict([...allPass("head", input.head), ...scopeReasons(input.review)]);
775
+ case "bug":
776
+ return verdict(bugReasons(input));
777
+ case "refactor":
778
+ return verdict([...allPass("base", input.base), ...allPass("head", input.head)]);
779
+ case "investigation":
780
+ return verdict(conclusionReasons(input.conclusion));
781
+ case "docs":
782
+ return verdict((input.documented ?? []).length === 0 ? ["No documented command was named"] : (input.documented ?? []).flatMap((name) => passesOnHead(input.head, name)));
783
+ case "migration":
784
+ return verdict(passesOnHead(input.head, input.rollback));
785
+ case "performance":
786
+ return verdict([
787
+ ...input.measurement === undefined ? ["No final measurement against the merge base was kept"] : input.measurement.verdict === "gain" ? [] : [`The final measurement is ${input.measurement.verdict}: ${input.measurement.reason}`],
788
+ ...allPass("head", input.head)
789
+ ]);
790
+ default:
791
+ return verdict(allPass("head", input.head));
792
+ }
793
+ };
794
+
795
+ // packages/sdk/src/loop/steps.ts
796
+ class StepFailed extends TaggedError2()("StepFailed", {
797
+ step: String4,
798
+ reason: String4
799
+ }) {
800
+ get message() {
801
+ return `Step "${this.step}" failed: ${this.reason}`;
802
+ }
803
+ }
804
+
805
+ class OutputInvalid extends TaggedError2()("OutputInvalid", {
806
+ step: String4,
807
+ message: String4
808
+ }) {
809
+ }
810
+
811
+ class QuestionRefused extends TaggedError2()("QuestionRefused", {
812
+ step: String4,
813
+ answer: String4,
814
+ options: ArraySchema(String4)
815
+ }) {
816
+ }
817
+
818
+ class WaitTimedOut extends TaggedError2()("WaitTimedOut", {
819
+ step: String4,
820
+ event: String4
821
+ }) {
822
+ }
823
+
824
+ class ChangeRequestClosed extends TaggedError2()("ChangeRequestClosed", {
825
+ step: String4,
826
+ merged: Boolean2
827
+ }) {
828
+ }
829
+
830
+ class ChildFailed extends TaggedError2()("ChildFailed", {
831
+ step: String4,
832
+ loop: String4,
833
+ reason: String4
834
+ }) {
835
+ get message() {
836
+ return `Child Run of "${this.loop}" for Step "${this.step}" failed: ${this.reason}`;
837
+ }
838
+ }
839
+
840
+ class CapabilityDenied extends TaggedError2()("CapabilityDenied", {
841
+ step: String4,
842
+ capability: Literals(LoopCapabilities),
843
+ secret: optionalKey(String4)
844
+ }) {
845
+ get message() {
846
+ return this.secret === undefined ? `Step "${this.step}" needs the "${this.capability}" capability, which this Run was not granted` : `Step "${this.step}" names the Secret "${this.secret}", which its Loop does not declare`;
847
+ }
848
+ }
849
+
850
+ class DuplicateStep extends TaggedError2()("DuplicateStep", {
851
+ step: String4
852
+ }) {
853
+ }
854
+
855
+ class InputInvalid extends TaggedError2()("InputInvalid", {
856
+ loop: String4,
857
+ message: String4
858
+ }) {
859
+ }
860
+ var LoopEvent = Struct({ type: String4, payload: Record(String4, Json) });
861
+
862
+ class LoopRun extends Service2()("@kitman-sh/sdk/loop/LoopRun") {
863
+ }
864
+
865
+ class LoopHost extends Service2()("@kitman-sh/sdk/loop/LoopHost") {
866
+ }
867
+ var agentDeferredNamed = (deferredName) => make(deferredName, { success: Json, error: StepFailed });
868
+ var agentWorkDeferred = (step) => agentDeferredNamed(`agent_work/${step}`);
869
+ var syncDeferred = (step) => agentDeferredNamed(`sync/${step}`);
870
+ var answerDeferred = (step) => make(`ask/${step}`, { success: String4, error: StepFailed });
871
+ var childDeferred = (step) => make(`call/${step}`, { success: Json, error: ChildFailed });
872
+ var eventDeferred = (step) => make(`wait_for/${step}`, { success: LoopEvent, error: WaitTimedOut });
873
+ var verifyDeferred = (step) => make(`verify/${step}`, { success: VerifyResult, error: StepFailed });
874
+ var recordStep = (name, kind, exit) => {
875
+ if (isSuccess2(exit))
876
+ return { name, kind, status: "succeeded", result: exit.value };
877
+ if (hasInterruptsOnly(exit.cause))
878
+ return;
879
+ return { name, kind, status: "failed", error: squash(exit.cause) };
880
+ };
881
+ var takeStep = (name, kind, capability, body) => gen(function* () {
882
+ const run = yield* LoopRun;
883
+ if (run.names.has(name))
884
+ return yield* new DuplicateStep({ step: name });
885
+ if (capability !== undefined && !run.granted.has(capability))
886
+ return yield* new CapabilityDenied({ step: name, capability });
887
+ run.names.add(name);
888
+ return yield* body.pipe(onExit((exit) => sync2(() => {
889
+ const record = recordStep(name, kind, exit);
890
+ if (record !== undefined)
891
+ run.steps.push(record);
892
+ })));
893
+ });
894
+ var launch = (deferred, start) => make2({
895
+ name: deferred.name,
896
+ error: StepFailed,
897
+ execute: gen(function* () {
898
+ return yield* start(yield* LoopHost, yield* token(deferred));
899
+ })
900
+ });
901
+ var toJson = (step, schema, value) => encodeUnknownEffect(toCodecJson(schema))(value).pipe(flatMap3(decodeUnknownEffect2(Json)), mapError2((error) => new StepFailed({ step, reason: error.message })));
902
+ var agentWork = (name, options) => agentWorkAs(agentWorkDeferred, name, options);
903
+ var agentWorkAs = (deferredOf, name, options) => takeStep(name, "agent_work", "agent_work", gen(function* () {
904
+ const run = yield* LoopRun;
905
+ const agent = run.agents[options.agent];
906
+ const undeclared = options.secrets?.find((secret) => !run.secrets.has(secret));
907
+ if (undeclared !== undefined)
908
+ return yield* new CapabilityDenied({ step: name, capability: "agent_work", secret: undeclared });
909
+ if (agent === undefined)
910
+ return yield* new StepFailed({ step: name, reason: `Agent role "${options.agent}" is not declared` });
911
+ const deferred = deferredOf(name);
912
+ const output = yield* jsonSchemaOf(run.loop, options.answer ?? options.output).pipe(mapError2((error) => new StepFailed({ step: name, reason: error.message })));
913
+ yield* launch(deferred, (host, token2) => host.startAgentWork({
914
+ step: name,
915
+ deferredName: deferred.name,
916
+ role: options.agent,
917
+ agent,
918
+ prompt: options.prompt,
919
+ ...options.skill === undefined ? undefined : { skill: options.skill },
920
+ output,
921
+ ...options.secrets === undefined ? undefined : { secrets: options.secrets },
922
+ ...options.timeout === undefined ? undefined : { timeoutMillis: toMillis(fromInputUnsafe(options.timeout)) },
923
+ ...options.mergeTarget === undefined ? undefined : { mergeTarget: options.mergeTarget },
924
+ token: token2
925
+ }));
926
+ const submitted = yield* await_(deferred);
927
+ return yield* decodeEffect(toCodecJson(options.output))(submitted).pipe(mapError2((error) => new OutputInvalid({ step: name, message: error.message })));
928
+ }));
929
+ var agentWorkOnce = (name, options) => agentWork(name, options).pipe(catchTag("OutputInvalid", (invalid) => agentWork(`${name}:again`, {
930
+ ...options,
931
+ prompt: `${options.prompt}
932
+
933
+ Your last Output was refused: ${invalid.message}. Give it again in the right shape.`
934
+ })));
935
+ var ask = (name, question) => takeStep(name, "ask", "ask", gen(function* () {
936
+ const deferred = answerDeferred(name);
937
+ const offered = "options" in question ? splitQuestionOptions(question.options) : undefined;
938
+ const options = offered?.options;
939
+ const recommended = "recommended" in question ? question.recommended : undefined;
940
+ const informationOnly = "informationOnly" in question ? question.informationOnly : undefined;
941
+ const advice = questionAdvice({
942
+ ...offered,
943
+ ...recommended === undefined ? undefined : { recommended },
944
+ recommendationReason: question.recommendationReason,
945
+ ...informationOnly === undefined ? undefined : { informationOnly }
946
+ });
947
+ const refused = recommendationProblem({ ...advice, ...options === undefined ? undefined : { options } });
948
+ if (refused !== undefined)
949
+ return yield* new StepFailed({ step: name, reason: refused });
950
+ const fallback = question.default === undefined ? recommendedDefault(recommended) : question.default ?? undefined;
951
+ if (fallback !== undefined && options !== undefined && !options.includes(fallback))
952
+ return yield* new QuestionRefused({ step: name, answer: fallback, options });
953
+ yield* launch(deferred, (host, token2) => host.putQuestion({
954
+ step: name,
955
+ prompt: question.prompt,
956
+ ...options === undefined ? undefined : { options },
957
+ ...advice,
958
+ ...fallback === undefined ? undefined : { default: fallback },
959
+ ...question.timeout === undefined ? undefined : { timeoutMillis: toMillis(fromInputUnsafe(question.timeout)) },
960
+ token: token2
961
+ }));
962
+ const answer = yield* await_(deferred);
963
+ if (options === undefined) {
964
+ return answer;
965
+ }
966
+ const offeredAnswer = options.find((option) => option === answer);
967
+ if (offeredAnswer === undefined)
968
+ return yield* new QuestionRefused({ step: name, answer, options });
969
+ return offeredAnswer;
970
+ }));
971
+ var call = (name, loop, input) => takeStep(name, "call", "call", gen(function* () {
972
+ const deferred = childDeferred(name);
973
+ const encoded = yield* toJson(name, loop.input, input);
974
+ yield* launch(deferred, (host, token2) => host.admitChild({ step: name, loop: loop.id, input: encoded, token: token2 }));
975
+ const result = yield* await_(deferred);
976
+ return yield* decodeEffect(toCodecJson(loop.output))(result).pipe(mapError2((error) => new ChildFailed({ step: name, loop: loop.id, reason: error.message })));
977
+ }));
978
+ var waitFor = (name, wait) => takeStep(name, "wait_for", undefined, gen(function* () {
979
+ const deferred = eventDeferred(name);
980
+ const timeoutMillis = toMillis(fromInputUnsafe(wait.timeout));
981
+ yield* launch(deferred, (host, token2) => host.awaitEvent({
982
+ step: name,
983
+ event: wait.event,
984
+ ...wait.filter === undefined ? undefined : { filter: wait.filter },
985
+ ...wait.since === undefined ? undefined : { since: wait.since },
986
+ ...wait.or === undefined ? undefined : { or: wait.or },
987
+ timeoutMillis,
988
+ token: token2
989
+ }));
990
+ const event = yield* await_(deferred);
991
+ if (event.type === "change_request.closed" && wait.event !== event.type && wait.or?.some((other) => other.event === event.type) !== true)
992
+ return yield* new ChangeRequestClosed({
993
+ step: name,
994
+ merged: event.payload.merged === true
995
+ });
996
+ return event;
997
+ }));
998
+ var verify = (name, request) => takeStep(name, "verify", "verify", gen(function* () {
999
+ const deferred = verifyDeferred(name);
1000
+ yield* launch(deferred, (host, token2) => host.startVerification({
1001
+ step: name,
1002
+ ...request.revision === undefined ? undefined : { revision: request.revision },
1003
+ ...request.checks === undefined ? undefined : { checks: request.checks },
1004
+ ...request.suggested === undefined || request.suggested.length === 0 ? undefined : { suggested: request.suggested },
1005
+ token: token2
1006
+ }));
1007
+ return yield* await_(deferred);
1008
+ }));
1009
+ // packages/sdk/src/loop/plan.ts
1010
+ var PlanTicket = Struct({
1011
+ key: String4,
1012
+ title: String4,
1013
+ body: String4,
1014
+ acceptanceCriteria: ArraySchema(String4),
1015
+ repoBindingId: optional(String4),
1016
+ blockedBy: ArraySchema(String4),
1017
+ outcome: optional(LoopOutcome)
1018
+ });
1019
+ var cycleMessage = (keys) => `These tickets block each other in a cycle, so none can start: ${keys.join(", ")}`;
1020
+ var ticketsProblem = (tickets) => {
1021
+ const keys = new Set;
1022
+ for (const ticket of tickets) {
1023
+ if (keys.has(ticket.key))
1024
+ return `Two tickets have the key "${ticket.key}"`;
1025
+ keys.add(ticket.key);
1026
+ }
1027
+ for (const ticket of tickets)
1028
+ for (const blocker of ticket.blockedBy)
1029
+ if (!keys.has(blocker))
1030
+ return `Ticket "${ticket.key}" is blocked by "${blocker}", which is not a ticket`;
1031
+ const { blocked } = wavesOf(tickets);
1032
+ return blocked.length === 0 ? undefined : cycleMessage(blocked);
1033
+ };
1034
+ var PlanTickets = ArraySchema(PlanTicket).check(makeFilter((tickets) => ticketsProblem(tickets) ?? true));
1035
+
1036
+ class BlockingCycle extends TaggedError2()("BlockingCycle", {
1037
+ tickets: ArraySchema(String4)
1038
+ }) {
1039
+ get message() {
1040
+ return cycleMessage(this.tickets);
1041
+ }
1042
+ }
1043
+ var byRepoBinding = (left, right) => (left.repoBindingId ?? "").localeCompare(right.repoBindingId ?? "");
1044
+ function wavesOf(tickets) {
1045
+ const placed = new Set;
1046
+ const waves = [];
1047
+ let left = tickets;
1048
+ while (left.length > 0) {
1049
+ const ready = left.filter((ticket) => ticket.blockedBy.every((blocker) => placed.has(blocker)));
1050
+ if (ready.length === 0)
1051
+ break;
1052
+ for (const ticket of ready)
1053
+ placed.add(ticket.key);
1054
+ waves.push(ready.toSorted(byRepoBinding));
1055
+ left = left.filter((ticket) => !placed.has(ticket.key));
1056
+ }
1057
+ return { waves, blocked: left.map((ticket) => ticket.key) };
1058
+ }
1059
+ var planWaves = (tickets) => suspend3(() => {
1060
+ const { waves, blocked } = wavesOf(tickets);
1061
+ return blocked.length === 0 ? succeed6(waves) : fail7(new BlockingCycle({ tickets: blocked }));
1062
+ });
1063
+
1064
+ // packages/sdk/src/loop/activities.ts
1065
+ var ChangeRequestRequest = Struct({
1066
+ title: String4,
1067
+ body: String4,
1068
+ integration: optional(String4)
1069
+ });
1070
+ var ChangeRequestResult = Struct({ id: String4, number: String4, url: String4 });
1071
+ var WriteBackMilestones = ["started", "change_request_opened", "merged", "failed"];
1072
+ var WriteBackRequest = Struct({
1073
+ milestone: optional(Literals(WriteBackMilestones)),
1074
+ changeRequestUrl: optional(String4)
1075
+ });
1076
+ var RunFile = Struct({ runFile: String4 }).pipe(decodeTo2(Struct({ id: String4 }), transform2({
1077
+ decode: ({ runFile }) => ({ id: runFile }),
1078
+ encode: ({ id }) => ({ runFile: id })
1079
+ })));
1080
+ var FileRequest = Struct({ path: String4, caption: optional(String4) });
1081
+ var ArtifactRequest = Struct({
1082
+ kind: String4,
1083
+ title: String4,
1084
+ text: String4,
1085
+ data: optional(Json),
1086
+ files: optional(ArraySchema(RunFile))
1087
+ });
1088
+ var ArtifactResult = Struct({ artifactId: String4 });
1089
+ var NoteRequest = Struct({ text: String4, artifactId: optional(String4) });
1090
+ var CreateTasksRequest = Struct({
1091
+ tickets: ArraySchema(PlanTicket),
1092
+ projectId: optionalKey(String4)
1093
+ });
1094
+ var CreateTasksResult = Struct({
1095
+ tasks: ArraySchema(Struct({ key: String4, taskId: String4 }))
1096
+ });
1097
+ var AlertTaskRequest = Struct({
1098
+ fingerprint: String4.check(isMinLength(1), isMaxLength(400)),
1099
+ title: String4,
1100
+ windowHours: Int.check(isGreaterThanOrEqualTo(0), isLessThanOrEqualTo(720)),
1101
+ resolved: optionalKey(Boolean2),
1102
+ priority: optionalKey(Literals(["urgent", "high", "medium", "low"]))
1103
+ });
1104
+ var AlertTaskResult = Struct({
1105
+ taskId: optionalKey(String4),
1106
+ created: Boolean2,
1107
+ resolved: optionalKey(Boolean2),
1108
+ joined: optionalKey(Struct({ kind: Literals(["run", "recent"]), runId: String4 }))
1109
+ });
1110
+ var IntegrationBranchRequest = Struct({ repoBindingId: optional(String4) });
1111
+ var IntegrationBranch = Struct({
1112
+ repoBindingId: String4,
1113
+ branch: String4,
1114
+ revision: String4
1115
+ });
1116
+ var MergeChangeRequestRequest = Struct({
1117
+ changeRequestId: String4,
1118
+ head: optionalKey(String4)
1119
+ });
1120
+ var MergeResult = Union([
1121
+ Struct({ status: Literal("merged"), revision: String4 }),
1122
+ Struct({ status: Literal("conflict") }),
1123
+ Struct({ status: Literal("moved"), head: String4 })
1124
+ ]);
1125
+ var ApproveChangeRequestRequest = Struct({
1126
+ changeRequestId: String4,
1127
+ head: String4,
1128
+ summary: String4,
1129
+ review: optionalKey(String4),
1130
+ carries: optionalKey(String4)
1131
+ });
1132
+ var ApproveChangeRequestResult = Union([
1133
+ Struct({ approved: Literal(true), reviewId: String4 }),
1134
+ Struct({ approved: Literal(false), reason: String4 })
1135
+ ]);
1136
+ var CloseChangeRequestRequest = Struct({
1137
+ number: String4,
1138
+ head: String4,
1139
+ note: String4
1140
+ });
1141
+ var CloseChangeRequestResult = Struct({
1142
+ closed: Boolean2,
1143
+ head: optionalKey(String4)
1144
+ });
1145
+ var RerunPipelineRequest = Union([
1146
+ Struct({ changeRequestId: String4 }),
1147
+ Struct({ ref: String4, all: optionalKey(Boolean2) })
1148
+ ]);
1149
+ var RerunPipelineResult = Struct({ head: String4, pipelines: Int });
1150
+ var ReportPipelineRequest = Struct({ changeRequestId: String4, verification: String4 });
1151
+ var ReportPipelineResult = Struct({
1152
+ head: String4,
1153
+ status: Literals(["success", "failed"])
1154
+ });
1155
+ var CommentRequest = Struct({
1156
+ changeRequestId: String4,
1157
+ body: String4,
1158
+ threadId: optionalKey(String4),
1159
+ summary: optionalKey(String4),
1160
+ anchors: optionalKey(ArraySchema(Struct({
1161
+ file: String4,
1162
+ line: Int.check(isGreaterThanOrEqualTo(1)),
1163
+ body: String4.check(isMinLength(1))
1164
+ })))
1165
+ });
1166
+ var ReleaseRequest = Struct({
1167
+ tag: String4,
1168
+ revision: optional(String4),
1169
+ title: String4,
1170
+ notes: String4
1171
+ });
1172
+ var ReleaseResult = Struct({ tag: String4, revision: String4, url: String4 });
1173
+ var ChangeRequestReadRequest = Struct({ changeRequestId: String4 });
1174
+ var PipelineJob = Struct({
1175
+ name: String4,
1176
+ status: Literals(["running", "success", "failed", "skipped"]),
1177
+ url: optional(String4),
1178
+ logTail: optional(String4)
1179
+ });
1180
+ var PipelineStatus = Struct({
1181
+ head: String4,
1182
+ status: Literals(["none", "running", "success", "failed", "canceled"]),
1183
+ source: Literals(["forge", "reported"]),
1184
+ jobs: ArraySchema(PipelineJob),
1185
+ readAt: optionalKey(String4),
1186
+ runnerChecks: optionalKey(ArraySchema(String4))
1187
+ });
1188
+ var ReviewThread = Struct({
1189
+ id: String4,
1190
+ path: optional(String4),
1191
+ line: optional(Int),
1192
+ outdated: optional(Boolean2),
1193
+ comments: ArraySchema(Struct({ author: optional(String4), body: String4 }))
1194
+ });
1195
+ var ReviewThreads = Struct({ threads: ArraySchema(ReviewThread) });
1196
+ var OpenChangeRequestsRequest = Struct({ authors: NonEmptyArray(String4) });
1197
+ var OpenChangeRequest = Struct({
1198
+ number: String4,
1199
+ title: String4,
1200
+ body: String4,
1201
+ url: String4,
1202
+ author: String4,
1203
+ sourceBranch: String4,
1204
+ head: String4
1205
+ });
1206
+ var OpenChangeRequests = Struct({ changeRequests: ArraySchema(OpenChangeRequest) });
1207
+ var OwnChangeRequest = Struct({
1208
+ id: String4,
1209
+ number: String4,
1210
+ url: String4,
1211
+ title: String4,
1212
+ sourceBranch: String4,
1213
+ body: String4
1214
+ });
1215
+ var OwnChangeRequests = Struct({ changeRequests: ArraySchema(OwnChangeRequest) });
1216
+ var TranscriptPoint = Struct({
1217
+ runId: String4,
1218
+ stepAttemptId: String4,
1219
+ sequence: Int
1220
+ });
1221
+ var TranscriptsRequest = Struct({
1222
+ days: Int.check(isGreaterThanOrEqualTo(1), isLessThanOrEqualTo(31))
1223
+ });
1224
+ var TranscriptsResult = Struct({
1225
+ runs: ArraySchema(Struct({
1226
+ runId: String4,
1227
+ loopId: String4,
1228
+ status: optional(Literals(["completed", "failed", "canceled", "expired"])),
1229
+ teamId: optional(String4),
1230
+ failure: optional(String4),
1231
+ retried: optional(Boolean2),
1232
+ entries: ArraySchema(Struct({ stepAttemptId: String4, sequence: Int, kind: String4, text: String4 }))
1233
+ }))
1234
+ });
1235
+ var Citations = NonEmptyArray(TranscriptPoint);
1236
+ var ProposeRequest = Union([
1237
+ Struct({
1238
+ kind: Literal("memory"),
1239
+ teamId: String4,
1240
+ content: String4,
1241
+ citations: Citations
1242
+ }),
1243
+ Struct({
1244
+ kind: Literal("task"),
1245
+ title: String4,
1246
+ description: String4,
1247
+ teamId: optional(String4),
1248
+ key: optionalKey(String4.check(isPattern(/^[a-z0-9]+(?:-[a-z0-9]+)*$/), isMaxLength(80))),
1249
+ citations: Citations
1250
+ })
1251
+ ]);
1252
+ var ProposeResult = Struct({
1253
+ kind: Literals(["memory", "task"]),
1254
+ id: String4,
1255
+ matched: optionalKey(Boolean2)
1256
+ });
1257
+ var Health = Literals(["on_track", "at_risk", "off_track"]);
1258
+ var ProjectActivityRequest = Struct({ projectId: String4 });
1259
+ var ProjectActivityResult = Struct({
1260
+ project: Struct({ id: String4, name: String4 }),
1261
+ health: optional(Health),
1262
+ since: optional(String4),
1263
+ runs: ArraySchema(Struct({
1264
+ runId: String4,
1265
+ loopId: String4,
1266
+ status: String4,
1267
+ taskKey: optional(String4),
1268
+ taskTitle: optional(String4),
1269
+ summary: optional(String4),
1270
+ entries: ArraySchema(Struct({ stepAttemptId: String4, sequence: Int, kind: String4, text: String4 }))
1271
+ })),
1272
+ taskChanges: ArraySchema(Struct({ taskKey: String4, title: String4, change: String4, at: String4 }))
1273
+ });
1274
+ var DraftUpdateRequest = Struct({
1275
+ projectId: String4,
1276
+ health: Health,
1277
+ note: String4,
1278
+ writtenFrom: Struct({
1279
+ runs: Int,
1280
+ taskChanges: Int,
1281
+ since: optional(String4)
1282
+ })
1283
+ });
1284
+ var DraftUpdateResult = Struct({ id: String4 });
1285
+
1286
+ class ChangeRequestActivity extends Service2()("@kitman-sh/sdk/loop/ChangeRequestActivity") {
1287
+ }
1288
+
1289
+ class WriteBackActivity extends Service2()("@kitman-sh/sdk/loop/WriteBackActivity") {
1290
+ }
1291
+
1292
+ class ArtifactActivity extends Service2()("@kitman-sh/sdk/loop/ArtifactActivity") {
1293
+ }
1294
+
1295
+ class FileActivity extends Service2()("@kitman-sh/sdk/loop/FileActivity") {
1296
+ }
1297
+
1298
+ class NoteActivity extends Service2()("@kitman-sh/sdk/loop/NoteActivity") {
1299
+ }
1300
+
1301
+ class CommentActivity extends Service2()("@kitman-sh/sdk/loop/CommentActivity") {
1302
+ }
1303
+
1304
+ class CreateTasksActivity extends Service2()("@kitman-sh/sdk/loop/CreateTasksActivity") {
1305
+ }
1306
+
1307
+ class AlertTaskActivity extends Service2()("@kitman-sh/sdk/loop/AlertTaskActivity") {
1308
+ }
1309
+
1310
+ class IntegrationBranchActivity extends Service2()("@kitman-sh/sdk/loop/IntegrationBranchActivity") {
1311
+ }
1312
+
1313
+ class MergeChangeRequestActivity extends Service2()("@kitman-sh/sdk/loop/MergeChangeRequestActivity") {
1314
+ }
1315
+
1316
+ class ReleaseActivity extends Service2()("@kitman-sh/sdk/loop/ReleaseActivity") {
1317
+ }
1318
+
1319
+ class TranscriptsActivity extends Service2()("@kitman-sh/sdk/loop/TranscriptsActivity") {
1320
+ }
1321
+
1322
+ class ProposeActivity extends Service2()("@kitman-sh/sdk/loop/ProposeActivity") {
1323
+ }
1324
+
1325
+ class ProjectActivityActivity extends Service2()("@kitman-sh/sdk/loop/ProjectActivityActivity") {
1326
+ }
1327
+
1328
+ class DraftUpdateActivity extends Service2()("@kitman-sh/sdk/loop/DraftUpdateActivity") {
1329
+ }
1330
+
1331
+ class ChangeRequestReadActivity extends Service2()("@kitman-sh/sdk/loop/ChangeRequestReadActivity") {
1332
+ }
1333
+ var hostActivity = (name, kind, capability, success, execute) => takeStep(name, kind, capability, make2({ name: `${kind}/${name}`, success, error: StepFailed, execute }));
1334
+ var changeRequest = (name, request) => hostActivity(name, "change_request", "change_request", ChangeRequestResult, gen(function* () {
1335
+ return yield* (yield* ChangeRequestActivity).run(request, name);
1336
+ }));
1337
+ var writeBack = (name, request) => hostActivity(name, "write_back", "write_back", Void, gen(function* () {
1338
+ return yield* (yield* WriteBackActivity).run(request, name);
1339
+ }));
1340
+ var artifact = (name, request) => hostActivity(name, "artifact", undefined, ArtifactResult, gen(function* () {
1341
+ return yield* (yield* ArtifactActivity).run(request, name);
1342
+ }));
1343
+ var note = (name, request) => hostActivity(name, "note", undefined, Void, gen(function* () {
1344
+ return yield* (yield* NoteActivity).run(request, name);
1345
+ }));
1346
+ var comment = (name, request) => hostActivity(name, "comment", "post_comment", Void, gen(function* () {
1347
+ return yield* (yield* CommentActivity).run(request, name);
1348
+ }));
1349
+ var createTasks = (name, request) => hostActivity(name, "create_tasks", "create_tasks", CreateTasksResult, gen(function* () {
1350
+ return yield* (yield* CreateTasksActivity).run(request, name);
1351
+ }));
1352
+ var alertTask = (name, request) => hostActivity(name, "create_tasks", "create_tasks", AlertTaskResult, gen(function* () {
1353
+ return yield* (yield* AlertTaskActivity).run(request, name);
1354
+ }));
1355
+ var integrationBranch = (name, request) => hostActivity(name, "integration_branch", "merge_change_request", IntegrationBranch, gen(function* () {
1356
+ return yield* (yield* IntegrationBranchActivity).run(request, name);
1357
+ }));
1358
+ var mergeChangeRequest = (name, request) => hostActivity(name, "merge_change_request", "merge_change_request", MergeResult, gen(function* () {
1359
+ return yield* (yield* MergeChangeRequestActivity).run(request, name);
1360
+ }));
1361
+ var approveChangeRequest = (name, request) => hostActivity(name, "approve_change_request", "approve_change_request", ApproveChangeRequestResult, gen(function* () {
1362
+ return yield* (yield* MergeChangeRequestActivity).approve(request, name);
1363
+ }));
1364
+ var closeChangeRequest = (name, request) => hostActivity(name, "close_change_request", "merge_change_request", CloseChangeRequestResult, gen(function* () {
1365
+ return yield* (yield* MergeChangeRequestActivity).close(request, name);
1366
+ }));
1367
+ var pipelineMoved = (name, changeRequestId, read, timeout = "6 hours") => waitFor(name, {
1368
+ event: "change_request.pipeline",
1369
+ filter: read.readAt === undefined ? { changeRequestId, head: read.head } : { changeRequestId },
1370
+ timeout,
1371
+ ...read.readAt === undefined ? undefined : { since: read.readAt }
1372
+ });
1373
+ var rerunPipeline = (name, request) => hostActivity(name, "rerun_pipeline", "merge_change_request", RerunPipelineResult, gen(function* () {
1374
+ return yield* (yield* MergeChangeRequestActivity).rerun(request, name);
1375
+ }));
1376
+ var reportPipeline = (name, request) => hostActivity(name, "report_pipeline", "verify", ReportPipelineResult, gen(function* () {
1377
+ return yield* (yield* MergeChangeRequestActivity).report(request, name);
1378
+ }));
1379
+ var release2 = (name, request) => hostActivity(name, "release", "publish_release", ReleaseResult, gen(function* () {
1380
+ return yield* (yield* ReleaseActivity).run(request, name);
1381
+ }));
1382
+ var transcripts = (name, request) => hostActivity(name, "transcripts", "read_transcripts", TranscriptsResult, gen(function* () {
1383
+ return yield* (yield* TranscriptsActivity).run(request, name);
1384
+ }));
1385
+ var propose = (name, request) => hostActivity(name, "propose", "propose", ProposeResult, gen(function* () {
1386
+ return yield* (yield* ProposeActivity).run(request, name);
1387
+ }));
1388
+ var projectActivity = (name, request) => hostActivity(name, "project_activity", "read_project", ProjectActivityResult, gen(function* () {
1389
+ return yield* (yield* ProjectActivityActivity).run(request, name);
1390
+ }));
1391
+ var pipelineStatus = (name, request) => hostActivity(name, "pipeline_status", "read_change_request", PipelineStatus, gen(function* () {
1392
+ return yield* (yield* ChangeRequestReadActivity).pipeline(request, name);
1393
+ }));
1394
+ var reviewThreads = (name, request) => hostActivity(name, "review_threads", "read_change_request", ReviewThreads, gen(function* () {
1395
+ return yield* (yield* ChangeRequestReadActivity).reviewThreads(request, name);
1396
+ }));
1397
+ var openChangeRequests = (name, request) => hostActivity(name, "open_change_requests", "read_change_request", OpenChangeRequests, gen(function* () {
1398
+ return yield* (yield* ChangeRequestReadActivity).opened(request, name);
1399
+ }));
1400
+ var ownChangeRequests = (name) => hostActivity(name, "own_change_requests", "read_change_request", OwnChangeRequests, gen(function* () {
1401
+ return yield* (yield* ChangeRequestReadActivity).own(name);
1402
+ }));
1403
+ var draftUpdate = (name, request) => hostActivity(name, "draft_update", "draft_update", DraftUpdateResult, gen(function* () {
1404
+ return yield* (yield* DraftUpdateActivity).run(request, name);
1405
+ }));
1406
+ // packages/sdk/src/loop/claims.ts
1407
+ var claimDeferred = (step) => make(`claim/${step}`, { success: ClaimResult, error: StepFailed });
1408
+ var claimOnce = (name, resource, action) => takeStep(name, "claim", "claim", gen(function* () {
1409
+ const deferred = claimDeferred(name);
1410
+ yield* launch(deferred, (host, token) => host.claimResource({ step: name, resource, action, token }));
1411
+ return yield* await_(deferred);
1412
+ }));
1413
+ var takeOver = "Take it over";
1414
+ var holderName = (holder) => holder.private === true ? "a Run of a private Team you are not in" : `Run ${holder.runId} of ${holder.loopId}`;
1415
+ var claim = (name, request) => gen(function* () {
1416
+ const first = yield* claimOnce(name, request.resource, "claim");
1417
+ if (first.status === "granted")
1418
+ return first;
1419
+ const { holder } = first;
1420
+ const fallback = holder.sameLoop ? takeOver : "Leave it";
1421
+ const answer = (yield* LoopRun).granted.has("ask") ? yield* ask(`${name}-offer`, {
1422
+ prompt: `${request.resource} is still held by ${holderName(holder)}${holder.status === undefined ? "" : `, which ${holder.status}`}${holder.reason === undefined ? "" : `: ${holder.reason}`}. Take it over?`,
1423
+ options: [takeOver, "Leave it"],
1424
+ recommended: fallback,
1425
+ recommendationReason: holder.sameLoop ? "The holder is this Loop on the same repository and settled without completing, so nothing else is using it." : "Another Loop holds it and may still need it; waiting is safer than taking it from under that Run.",
1426
+ timeout: request.timeout ?? "10 minutes"
1427
+ }) : fallback;
1428
+ if (answer !== takeOver)
1429
+ return yield* new StepFailed({ step: name, reason: `${request.resource} was left to ${holderName(holder)}` });
1430
+ const taken = yield* claimOnce(`${name}-take-over`, request.resource, "take_over");
1431
+ if (taken.status === "granted")
1432
+ return taken;
1433
+ return yield* new StepFailed({ step: name, reason: `${request.resource} is kept by ${holderName(taken.holder)}` });
1434
+ });
1435
+
1436
+ // packages/sdk/src/loop/measure.ts
1437
+ var MetricStats = Struct({
1438
+ samples: Finite,
1439
+ median: Finite,
1440
+ mean: Finite,
1441
+ min: Finite,
1442
+ max: Finite,
1443
+ stdev: Finite
1444
+ });
1445
+ var MeasureVerdict = Literals(["gain", "no_gain", "guardrail_regressed", "too_noisy"]);
1446
+ var Measurement = Struct({
1447
+ verdict: MeasureVerdict,
1448
+ reason: String4,
1449
+ metrics: ArraySchema(Struct({
1450
+ name: String4,
1451
+ role: Literals(["primary", "guardrail"]),
1452
+ direction: Literals(["lower", "higher"]),
1453
+ base: MetricStats,
1454
+ head: MetricStats,
1455
+ change: Finite,
1456
+ noise: Finite
1457
+ })),
1458
+ suggestion: optional(String4),
1459
+ evidence: MeasureEvidence
1460
+ });
1461
+ var measureDeferred = (step) => make(`measure/${step}`, { success: MeasureEvidence, error: StepFailed });
1462
+ var stats = (values) => {
1463
+ if (values.length === 0)
1464
+ return { samples: 0, median: 0, mean: 0, min: 0, max: 0, stdev: 0 };
1465
+ const sorted = [...values].sort((left, right) => left - right);
1466
+ const middle = Math.floor(sorted.length / 2);
1467
+ const mean = values.reduce((sum, value) => sum + value, 0) / values.length;
1468
+ return {
1469
+ samples: values.length,
1470
+ median: sorted.length % 2 === 0 ? ((sorted[middle - 1] ?? 0) + (sorted[middle] ?? 0)) / 2 : sorted[middle] ?? 0,
1471
+ mean,
1472
+ min: sorted[0] ?? 0,
1473
+ max: sorted.at(-1) ?? 0,
1474
+ stdev: Math.sqrt(values.reduce((sum, value) => sum + (value - mean) ** 2, 0) / values.length)
1475
+ };
1476
+ };
1477
+ var valuesOf = (samples, metric) => samples.flatMap((sample) => sample[metric] === undefined ? [] : [sample[metric]]);
1478
+ var incomplete = (plan, evidence) => plan.metrics.map((metric) => metric.name).filter((metric) => evidence.base.length === 0 || evidence.head.length === 0 || [...evidence.base, ...evidence.head, ...evidence.baseAgain ?? []].some((sample) => sample[metric] === undefined));
1479
+ var relative = (delta, of) => of === 0 ? Math.sign(delta) : delta / Math.abs(of);
1480
+ var noiseFloor = (plan, evidence) => Object.fromEntries(plan.metrics.map((metric) => {
1481
+ const base = stats(valuesOf(evidence.base, metric.name));
1482
+ const again = stats(valuesOf(evidence.baseAgain ?? [], metric.name));
1483
+ const spread = relative(base.stdev, base.median);
1484
+ const gap = again.samples === 0 ? 0 : relative(Math.abs(again.median - base.median), base.median);
1485
+ return [metric.name, Math.max(spread, gap)];
1486
+ }));
1487
+ var judgeMeasurement = (plan, evidence, noise, limits) => {
1488
+ const metrics = plan.metrics.map((metric) => {
1489
+ const base = stats(valuesOf(evidence.base, metric.name));
1490
+ const head = stats(valuesOf(evidence.head, metric.name));
1491
+ const delta = metric.direction === "lower" ? base.median - head.median : head.median - base.median;
1492
+ const change = base.samples === 0 || head.samples === 0 ? 0 : relative(delta, base.median);
1493
+ return { ...metric, base, head, change, noise: noise[metric.name] ?? 0 };
1494
+ });
1495
+ const percent = (fraction) => `${(fraction * 100).toFixed(1)}%`;
1496
+ const primary = metrics.find((metric) => metric.role === "primary");
1497
+ const judged = { metrics, evidence };
1498
+ if (primary === undefined)
1499
+ return { ...judged, verdict: "too_noisy", reason: "The plan names no primary metric" };
1500
+ const missing = incomplete(plan, evidence);
1501
+ if (missing.length > 0)
1502
+ return { ...judged, verdict: "too_noisy", reason: `${missing.join(", ")} is missing from some samples` };
1503
+ if (!Number.isFinite(primary.noise) || primary.noise > limits.threshold) {
1504
+ const steadier = plan.metrics.find((metric) => metric.lowVariance === true && metric.name !== primary.name);
1505
+ return {
1506
+ ...judged,
1507
+ verdict: "too_noisy",
1508
+ reason: `${primary.name} strays ${percent(primary.noise)} from itself, more than the ${percent(limits.threshold)} threshold`,
1509
+ suggestion: steadier === undefined ? "Measure a low-variance counter (instructions, allocations, queries) and make it the primary metric" : `Make ${steadier.name}, which varies less, the primary metric`
1510
+ };
1511
+ }
1512
+ const regressed = metrics.filter((metric) => metric.role === "guardrail" && metric.change < -(limits.tolerance + metric.noise));
1513
+ if (regressed.length > 0)
1514
+ return {
1515
+ ...judged,
1516
+ verdict: "guardrail_regressed",
1517
+ reason: regressed.map((metric) => `${metric.name} got ${percent(-metric.change)} worse, beyond the ${percent(limits.tolerance)} tolerance`).join("; ")
1518
+ };
1519
+ return primary.change > limits.threshold + primary.noise ? {
1520
+ ...judged,
1521
+ verdict: "gain",
1522
+ reason: `${primary.name} improved ${percent(primary.change)}, past the ${percent(limits.threshold)} threshold and ${percent(primary.noise)} of noise`
1523
+ } : {
1524
+ ...judged,
1525
+ verdict: "no_gain",
1526
+ reason: `${primary.name} changed ${percent(primary.change)}, within the ${percent(limits.threshold)} threshold and ${percent(primary.noise)} of noise`
1527
+ };
1528
+ };
1529
+ var floors = new WeakMap;
1530
+ var measure = (name, request) => takeStep(name, "measure", "measure", gen(function* () {
1531
+ const run = yield* LoopRun;
1532
+ const known = floors.get(run);
1533
+ const deferred = measureDeferred(name);
1534
+ yield* launch(deferred, (host, token) => host.startVerification({
1535
+ step: name,
1536
+ ...request.head === undefined ? undefined : { revision: request.head },
1537
+ measure: {
1538
+ ...request.base === undefined ? undefined : { base: request.base },
1539
+ plan: request.plan,
1540
+ samples: request.samples ?? 5,
1541
+ calibrate: known === undefined
1542
+ },
1543
+ token
1544
+ }));
1545
+ const evidence = yield* await_(deferred);
1546
+ const noise = known ?? noiseFloor(request.plan, evidence);
1547
+ if (known === undefined && incomplete(request.plan, evidence).length === 0)
1548
+ floors.set(run, noise);
1549
+ return judgeMeasurement(request.plan, evidence, noise, {
1550
+ threshold: request.threshold ?? 0.05,
1551
+ tolerance: request.tolerance ?? 0.02
1552
+ });
1553
+ }));
1554
+
1555
+ // packages/sdk/src/loop/test-loop.ts
1556
+ var LoopJournal = Struct({
1557
+ activities: Record(String4, Json),
1558
+ deferreds: Record(String4, Json)
1559
+ });
1560
+
1561
+ class ScriptedFailure extends TaggedClass("ScriptedFailure") {
1562
+ }
1563
+ // packages/sdk/src/loop/review.ts
1564
+ var Severity = Literals(["blocker", "major", "minor"]);
1565
+ var Finding = Struct({
1566
+ severity: Severity,
1567
+ file: String4,
1568
+ line: Int,
1569
+ detail: String4
1570
+ });
1571
+ var MergedFinding = Struct({
1572
+ id: String4,
1573
+ ...Finding.fields,
1574
+ seats: ArraySchema(String4)
1575
+ });
1576
+ var Rebuttal = Struct({ findingId: String4, reason: String4 });
1577
+ var RebuttalVerdict = Struct({ findingId: String4, accepted: Boolean2 });
1578
+ var ScopeJudgement = Struct({ met: Boolean2, unmet: ArraySchema(String4) });
1579
+ var rank = { blocker: 0, major: 1, minor: 2 };
1580
+ var isBlocking = (finding) => finding.severity !== "minor";
1581
+ var mergeFindings = (bySeat) => {
1582
+ const merged = new Map;
1583
+ for (const [seat, findings] of Object.entries(bySeat))
1584
+ for (const finding of findings) {
1585
+ const id = `${finding.file}:${finding.line}`;
1586
+ const known = merged.get(id);
1587
+ const seats = [...new Set([...known?.seats ?? [], seat])];
1588
+ const worst = known === undefined || rank[finding.severity] < rank[known.severity] ? finding : known;
1589
+ merged.set(id, { id, severity: worst.severity, file: worst.file, line: worst.line, detail: worst.detail, seats });
1590
+ }
1591
+ return [...merged.values()].toSorted((left, right) => rank[left.severity] - rank[right.severity]);
1592
+ };
1593
+ var splitDisputed = (findings, rebuttals) => {
1594
+ const disputed = [];
1595
+ const undisputed = [];
1596
+ for (const finding of findings) {
1597
+ const rebuttal = rebuttals.find((entry) => entry.findingId === finding.id);
1598
+ if (rebuttal === undefined)
1599
+ undisputed.push(finding);
1600
+ else
1601
+ disputed.push({ finding, rebuttal });
1602
+ }
1603
+ return { disputed, undisputed };
1604
+ };
1605
+ var settleRound = (round) => {
1606
+ const { disputed, undisputed } = splitDisputed(round.findings, round.rebuttals);
1607
+ const accepted = (entry) => {
1608
+ const verdicts = round.verdicts.filter((verdict) => verdict.findingId === entry.finding.id);
1609
+ return verdicts.length > 0 && verdicts.every((verdict) => verdict.accepted);
1610
+ };
1611
+ return {
1612
+ open: undisputed,
1613
+ withdrawn: disputed.filter(accepted),
1614
+ standing: disputed.filter((entry) => !accepted(entry))
1615
+ };
1616
+ };
1617
+ var rallyStop = (input) => {
1618
+ const open = input.settled.open.filter(isBlocking).map((finding) => finding.id);
1619
+ const standing = input.settled.standing.flatMap((entry) => isBlocking(entry.finding) ? [entry.finding.id] : []);
1620
+ const unsettled = [...open, ...standing];
1621
+ const stop = (reason) => ({ stop: true, reason, unsettled });
1622
+ if (unsettled.length === 0)
1623
+ return stop("settled");
1624
+ if (standing.length > 0)
1625
+ return stop("dispute_stands");
1626
+ if (input.previous !== undefined && sameIds(input.previous, unsettled))
1627
+ return stop("findings_returned");
1628
+ return input.round >= input.maxRounds ? stop("round_cap") : { stop: false };
1629
+ };
1630
+ var sameIds = (left, right) => left.length === right.length && left.every((id) => right.includes(id));
1631
+ // packages/sdk/src/loop/check.ts
1632
+ class CheckFailed extends TaggedError2()("CheckFailed", {
1633
+ loop: String4,
1634
+ check: String4,
1635
+ reason: String4
1636
+ }) {
1637
+ get detail() {
1638
+ return `Check "${this.check}": ${this.reason}`;
1639
+ }
1640
+ get message() {
1641
+ return `Loop "${this.loop}": ${this.detail}`;
1642
+ }
1643
+ }
1644
+
1645
+ class StepNamedTwice extends TaggedError2()("StepNamedTwice", {
1646
+ loop: String4,
1647
+ check: String4,
1648
+ step: String4
1649
+ }) {
1650
+ get detail() {
1651
+ return `Check "${this.check}": Step "${this.step}" is named twice`;
1652
+ }
1653
+ get message() {
1654
+ return `Loop "${this.loop}": ${this.detail}`;
1655
+ }
1656
+ }
1657
+
1658
+ class ReplayDiverged extends TaggedError2()("ReplayDiverged", {
1659
+ loop: String4,
1660
+ check: String4,
1661
+ first: ArraySchema(String4),
1662
+ replay: ArraySchema(String4),
1663
+ rerun: ArraySchema(String4)
1664
+ }) {
1665
+ get detail() {
1666
+ const steps = (names) => names.join(", ") || "no Steps";
1667
+ return `Check "${this.check}": its replay from the journal diverged; it took ${steps(this.first)} and then ${steps(this.replay)}${this.rerun.length > 0 ? `, running ${this.rerun.join(", ")} again` : ""}. Keep effects and randomness inside Activities.`;
1668
+ }
1669
+ get message() {
1670
+ return `Loop "${this.loop}": ${this.detail}`;
1671
+ }
1672
+ }
1673
+ var LoopCheckError = Union([CheckFailed, StepNamedTwice, ReplayDiverged]);
1674
+ // packages/sdk/src/loop/sync.ts
1675
+ var UpToDate = Struct({ status: Literal("up_to_date") });
1676
+ var Conflict = Struct({
1677
+ status: Literal("conflict"),
1678
+ files: NonEmptyArray(String4),
1679
+ reason: String4
1680
+ });
1681
+ var merged = {
1682
+ status: Literal("merged"),
1683
+ settled: ArraySchema(String4)
1684
+ };
1685
+ var SyncAnswer = Union([UpToDate, Struct(merged), Conflict]);
1686
+ var BaseSync = Union([
1687
+ UpToDate,
1688
+ Struct({ ...merged, catchUp: optionalKey(CatchUp) }),
1689
+ Conflict
1690
+ ]);
1691
+ var afterMerge = "One thing comes before any answer of merged, a clean merge included, and stopping above means stopping after it: before you answer merged, do what the repository's agent instructions say to do once the target branch is merged in, such as regenerating this branch's database migrations on top of the target's. Leave what that changes in the workspace: Kitman commits it.";
1692
+ var prompt = (target) => [
1693
+ `Kitman merged \`origin/${target}\` into this branch before you started, outside your sandbox, and says what came of it in a note after this brief. Do not fetch, as this workspace has no credential for the forge, and do not run git commands that write, such as \`git add\`, \`git commit\` or \`git merge --abort\`: Kitman finishes the merge itself from your answer.`,
1694
+ "If it was already up to date, change nothing and answer up_to_date. If it merged cleanly, answer merged with no settled files and stop: do not review or test anything else.",
1695
+ "If it conflicts, settle each file the note names so both sides' intent survives: leave no conflict marker, and for a file one side deleted or git could not mark, leave it as the version you want or delete it. Run the tests of the files you touched, and answer merged with those files under settled. Kitman then commits the files as you left them.",
1696
+ "If you cannot settle a file, answer conflict with the files and why: Kitman then aborts the whole merge.",
1697
+ "Never rebase, reset or force-push: this branch's history only grows."
1698
+ ].concat(afterMerge).join(`
1699
+
1700
+ `);
1701
+ var syncBase = (name, options) => agentWorkAs(syncDeferred, name, {
1702
+ agent: options.agent,
1703
+ prompt: prompt(options.target ?? "HEAD"),
1704
+ output: BaseSync,
1705
+ answer: SyncAnswer,
1706
+ mergeTarget: options.target ?? "HEAD"
1707
+ });
1708
+ // packages/sdk/src/loop/continuing.ts
1709
+ var Continuing = Struct({
1710
+ changeRequestId: String4,
1711
+ number: String4,
1712
+ url: String4,
1713
+ branch: String4,
1714
+ targetBranch: String4,
1715
+ revision: optional(String4),
1716
+ lastRunId: optional(String4),
1717
+ lastRunStatus: optional(String4),
1718
+ lastRunSummary: optional(String4)
1719
+ });
1720
+ var continuingBrief = (continuing) => [
1721
+ `This continues the work on ${continuing.branch}, whose ChangeRequest is ${continuing.url}. Build on what is there; do not start over.`,
1722
+ ...continuing.lastRunId === undefined ? [] : [
1723
+ `The last Run on it, ${continuing.lastRunId}, ended ${continuing.lastRunStatus ?? "unfinished"}${continuing.lastRunSummary === undefined ? "" : `: ${continuing.lastRunSummary}`}.`
1724
+ ],
1725
+ ...continuing.revision === undefined ? [] : [
1726
+ `It last pushed ${continuing.revision}. If the branch head is newer, someone pushed since: read \`git log ${continuing.revision}..HEAD\` first and keep their work.`
1727
+ ],
1728
+ "The ChangeRequest's description lists what was left unsettled; settle those first."
1729
+ ].join(`
1730
+ `);
1731
+ export { LoopManifest, AgentDeclaration, KitDeclarations, LoopOutcome, defineLoop, ManifestInvalid, make14, Suspended, failsOn, evidenceGate, ChildFailed, agentWork, agentWorkOnce, ask, call, waitFor, verify, PlanTickets, planWaves, ChangeRequestResult, RunFile, CreateTasksResult, ApproveChangeRequestResult, TranscriptPoint, changeRequest, writeBack, artifact, note, comment, createTasks, alertTask, integrationBranch, mergeChangeRequest, approveChangeRequest, closeChangeRequest, pipelineMoved, rerunPipeline, reportPipeline, release2, transcripts, propose, projectActivity, pipelineStatus, reviewThreads, openChangeRequests, ownChangeRequests, draftUpdate, claim, measure, Finding, MergedFinding, Rebuttal, RebuttalVerdict, ScopeJudgement, isBlocking, mergeFindings, settleRound, rallyStop, LoopCheckError, syncBase, Continuing, continuingBrief };