@vercel/factory 0.0.11 → 0.0.13
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/approval-CwhTP1XB.mjs +269 -0
- package/dist/approval-CwhTP1XB.mjs.map +1 -0
- package/dist/blob/index.d.mts +1 -1
- package/dist/build-factory.d.mts +1 -1
- package/dist/build-factory.mjs +1 -1
- package/dist/change-CzEAoFVE.mjs +620 -0
- package/dist/change-CzEAoFVE.mjs.map +1 -0
- package/dist/connectors/slack.d.mts +4 -4
- package/dist/connectors/slack.mjs +81 -30
- package/dist/connectors/slack.mjs.map +1 -1
- package/dist/{approval-CDiBco2V.d.mts → dispatch-B77cuPxh.d.mts} +293 -99
- package/dist/{driver-CrZsy7sm.d.mts → driver-BJutB0PE.d.mts} +2 -2
- package/dist/driver-Bbd25rNM.mjs.map +1 -1
- package/dist/eve/index.d.mts +546 -120
- package/dist/eve/index.mjs +358 -82
- package/dist/eve/index.mjs.map +1 -1
- package/dist/{factory-config-ifd3JxiU.mjs → factory-config-BJcjsPKl.mjs} +42 -5
- package/dist/factory-config-BJcjsPKl.mjs.map +1 -0
- package/dist/{factory-config-Bu4mklm9.d.mts → factory-config-D2yU3G0c.d.mts} +21 -2
- package/dist/{github-wThBfbm-.d.mts → github-DXsxboUL.d.mts} +25 -2
- package/dist/github.d.mts +2 -2
- package/dist/github.mjs +47 -1
- package/dist/github.mjs.map +1 -1
- package/dist/index.d.mts +129 -59
- package/dist/index.mjs +336 -333
- package/dist/index.mjs.map +1 -1
- package/dist/postgres/index.d.mts +1 -1
- package/package.json +1 -1
- package/dist/approval-DdvEKLiE.mjs +0 -132
- package/dist/approval-DdvEKLiE.mjs.map +0 -1
- package/dist/change-BPYhWKuL.mjs +0 -230
- package/dist/change-BPYhWKuL.mjs.map +0 -1
- package/dist/factory-config-ifd3JxiU.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,44 @@
|
|
|
1
1
|
import { a as repositoryIdsSchema, c as SCHEMA_VERSION, d as schemaVersionSchema, f as usdSchema, i as repositoryIdSchema, l as isoDateTimeSchema, n as factoryIdSchema, o as signalIdSchema, p as vocabularySchema, r as receiptIdSchema, s as taskIdSchema, t as changeIdSchema, u as replyToSchema } from "./id-DwCihQr4.mjs";
|
|
2
|
-
import { a as findingCategorySchema, c as findingSchema, d as findingVerificationSchema, i as requiresApproval, l as findingVerificationLevelSchema, n as approvalRuleSchema, o as findingFingerprint, r as defaultApprovalPolicy, s as findingPrioritySchema, t as approvalPolicySchema, u as findingVerificationMethodSchema } from "./approval-
|
|
2
|
+
import { C as taskUsageSchema, S as taskStateSchema, _ as taskExecutionRepositoryIdsSchema, a as findingCategorySchema, b as taskQuestionSchema, c as findingSchema, d as findingVerificationSchema, f as coordinationRepositoryIdsSchema, g as taskApprovalSchema, h as standardTaskKinds, i as requiresApproval, l as findingVerificationLevelSchema, m as harnessSchema, n as approvalRuleSchema, o as findingFingerprint, p as executionReferenceSchema, r as defaultApprovalPolicy, s as findingPrioritySchema, t as approvalPolicySchema, u as findingVerificationMethodSchema, v as taskKindSchema, x as taskSchema, y as taskOriginSchema } from "./approval-CwhTP1XB.mjs";
|
|
3
|
+
import { C as budgetStatus, D as sweepBudget, E as deriveFactoryId, O as sweepSettlements, S as budgetMonthOf, T as computeMonthSpendUsd, _ as taskInitialState, a as BudgetExhaustedError, b as createCoordination, c as dispatchTask, d as changeInitialState, f as changeTransitions, g as signalOutcomeTransitions, h as signalInitialOutcome, i as levelSchema, l as InvalidTransitionError, m as legalNextStates, n as changeSchema, o as DEFAULT_MAX_LAUNCH_ATTEMPTS, p as isTransitionAllowed, r as changeStateSchema, s as DispatchRefusedError, t as changeEvidenceSchema, u as assertTransition, v as taskTransitions, w as canReserve, x as reconcileCoordination, y as terminalStates } from "./change-CzEAoFVE.mjs";
|
|
3
4
|
import { n as RecordNotFoundError, r as VersionConflictError, t as RecordExistsError } from "./driver-Bbd25rNM.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { a as repositorySlugSchema, i as repositorySchema, n as factoryConfigRepositorySchema, r as factoryConfigSchema, t as defineFactory } from "./factory-config-ifd3JxiU.mjs";
|
|
5
|
+
import { a as factoryConfigSchema, c as budgetSchema, i as factoryConfigRepositorySchema, l as repositorySchema, n as defineFactory, o as budgetLimitsSchema, r as executionPolicySchema, s as budgetMonthSchema, t as defaultExecutionPolicy, u as repositorySlugSchema } from "./factory-config-BJcjsPKl.mjs";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
8
|
+
//#region src/agent-routes.ts
|
|
9
|
+
const agentRouteSchema = z.strictObject({
|
|
10
|
+
id: z.string().regex(/^[a-z][a-z0-9-]{0,63}$/u).describe("Stable route selected by a conversational agent or workflow."),
|
|
11
|
+
agent: z.string().regex(/^[a-z][a-z0-9-]{0,31}$/u).describe("Internally addressable Eve agent that executes this route."),
|
|
12
|
+
taskKind: taskKindSchema.describe("Factory task kind created for this route."),
|
|
13
|
+
description: z.string().min(1).max(500).describe("Model-facing guidance for when this route is appropriate."),
|
|
14
|
+
permissions: z.array(z.string().min(1)).default([]).describe("Inspectable capabilities granted to the target agent.")
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Define the application-owned routes an agent or workflow may select. Route
|
|
18
|
+
* descriptions inform judgment; this validated registry remains the authority.
|
|
19
|
+
*/
|
|
20
|
+
function defineAgentRoutes(inputs) {
|
|
21
|
+
const routes = inputs.map((input) => agentRouteSchema.parse(input));
|
|
22
|
+
const byId = /* @__PURE__ */ new Map();
|
|
23
|
+
const byTaskKind = /* @__PURE__ */ new Map();
|
|
24
|
+
for (const route of routes) {
|
|
25
|
+
if (byId.has(route.id)) throw new Error(`Agent route ${route.id} is registered more than once.`);
|
|
26
|
+
if (byTaskKind.has(route.taskKind)) throw new Error(`Task kind ${route.taskKind} is handled by more than one agent route.`);
|
|
27
|
+
byId.set(route.id, route);
|
|
28
|
+
byTaskKind.set(route.taskKind, route);
|
|
29
|
+
}
|
|
30
|
+
const frozen = Object.freeze(routes.map((route) => Object.freeze(route)));
|
|
31
|
+
return Object.freeze({
|
|
32
|
+
routes: frozen,
|
|
33
|
+
get(id) {
|
|
34
|
+
return byId.get(id);
|
|
35
|
+
},
|
|
36
|
+
forTaskKind(kind) {
|
|
37
|
+
return byTaskKind.get(kind);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
8
42
|
//#region src/briefs.ts
|
|
9
43
|
/** The finding behind a task, when its signal carries one. */
|
|
10
44
|
async function findingForTask(stores, task) {
|
|
@@ -37,6 +71,14 @@ function scanBrief(task, repository) {
|
|
|
37
71
|
"You never fix anything. When you are done, summarize what deepsec found and what you added, by priority, and what you could not scan."
|
|
38
72
|
].join("\n");
|
|
39
73
|
}
|
|
74
|
+
/** The verifier's starting message for a recorded pull request. */
|
|
75
|
+
function verificationBrief(task, repository, change) {
|
|
76
|
+
return [
|
|
77
|
+
`You are assigned factory verification task ${task.id} in repository ${repository.slug}.`,
|
|
78
|
+
`Change under review: ${change.id} (${change.prUrl}).`,
|
|
79
|
+
"Read the task with get_task, independently inspect and test the change, then call record_verification with every evidence field."
|
|
80
|
+
].join("\n");
|
|
81
|
+
}
|
|
40
82
|
//#endregion
|
|
41
83
|
//#region src/changes.ts
|
|
42
84
|
async function adoptPullRequest(stores, input) {
|
|
@@ -56,76 +98,6 @@ async function adoptPullRequest(stores, input) {
|
|
|
56
98
|
});
|
|
57
99
|
}
|
|
58
100
|
//#endregion
|
|
59
|
-
//#region src/coordination.ts
|
|
60
|
-
/** Create one non-executable parent and one independently executable child per repository. */
|
|
61
|
-
async function createCoordination(stores, input) {
|
|
62
|
-
const repositoryIds = [...new Set(input.repositoryIds)];
|
|
63
|
-
if (repositoryIds.length < 2) throw new Error("coordination requires at least two distinct repositories");
|
|
64
|
-
const parent = await stores.tasks.create({
|
|
65
|
-
repositoryIds,
|
|
66
|
-
kind: "coordination",
|
|
67
|
-
origin: { signalId: input.signalId },
|
|
68
|
-
replyTo: input.replyTo
|
|
69
|
-
});
|
|
70
|
-
return {
|
|
71
|
-
parent: await stores.tasks.transition(parent.id, "running", { reason: "repository-scoped child tasks created" }),
|
|
72
|
-
children: await Promise.all(repositoryIds.map((repositoryId) => stores.tasks.create({
|
|
73
|
-
repositoryIds: [repositoryId],
|
|
74
|
-
kind: "code_change",
|
|
75
|
-
origin: { parentTaskId: parent.id },
|
|
76
|
-
replyTo: input.replyTo
|
|
77
|
-
})))
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
/** Reconcile a coordination parent from its direct children without ever dispatching the parent. */
|
|
81
|
-
async function reconcileCoordination(stores, parentTaskId, options) {
|
|
82
|
-
const parent = await stores.tasks.get(parentTaskId);
|
|
83
|
-
if (parent === null) throw new RecordNotFoundError("tasks", parentTaskId);
|
|
84
|
-
if (parent.kind !== "coordination") throw new Error(`task ${parentTaskId} is ${parent.kind}, not coordination`);
|
|
85
|
-
const children = (await stores.tasks.list()).filter((task) => task.origin.parentTaskId === parentTaskId);
|
|
86
|
-
if (children.length !== parent.repositoryIds.length) return {
|
|
87
|
-
status: "pending",
|
|
88
|
-
parent,
|
|
89
|
-
children
|
|
90
|
-
};
|
|
91
|
-
if (parent.state === "succeeded" || parent.state === "failed") return {
|
|
92
|
-
status: parent.state,
|
|
93
|
-
transitioned: false,
|
|
94
|
-
parent,
|
|
95
|
-
children
|
|
96
|
-
};
|
|
97
|
-
if (children.some((child) => child.state === "failed" || child.state === "cancelled")) {
|
|
98
|
-
await options.present({
|
|
99
|
-
status: "failed",
|
|
100
|
-
parent,
|
|
101
|
-
children
|
|
102
|
-
});
|
|
103
|
-
return {
|
|
104
|
-
status: "failed",
|
|
105
|
-
transitioned: true,
|
|
106
|
-
parent: await stores.tasks.transition(parent.id, "failed", { reason: "one or more repository tasks failed" }),
|
|
107
|
-
children
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
if (!children.every((child) => child.state === "succeeded")) return {
|
|
111
|
-
status: "pending",
|
|
112
|
-
parent,
|
|
113
|
-
children
|
|
114
|
-
};
|
|
115
|
-
await options.present({
|
|
116
|
-
status: "succeeded",
|
|
117
|
-
parent,
|
|
118
|
-
children
|
|
119
|
-
});
|
|
120
|
-
await stores.tasks.transition(parent.id, "verifying", { reason: "all repository tasks succeeded" });
|
|
121
|
-
return {
|
|
122
|
-
status: "succeeded",
|
|
123
|
-
transitioned: true,
|
|
124
|
-
parent: await stores.tasks.transition(parent.id, "succeeded", { reason: "aggregate multi-repository handoff is ready" }),
|
|
125
|
-
children
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
//#endregion
|
|
129
101
|
//#region src/metrics.ts
|
|
130
102
|
const bucketTable = {
|
|
131
103
|
low: {
|
|
@@ -250,9 +222,10 @@ function computeLedgerMetrics(rows, options = {}) {
|
|
|
250
222
|
}
|
|
251
223
|
const openChangeStates = /* @__PURE__ */ new Set(["verifying", "ready"]);
|
|
252
224
|
/**
|
|
253
|
-
* Green, yellow, or red from rows, never from a model. Budget and
|
|
254
|
-
*
|
|
255
|
-
*
|
|
225
|
+
* Green, yellow, or red from rows, never from a model. Budget threshold and
|
|
226
|
+
* onboarding rules are not evaluated here yet: budget notices live on the
|
|
227
|
+
* budgets collection (not in these rows), and onboarding investigations are
|
|
228
|
+
* not recorded.
|
|
256
229
|
*/
|
|
257
230
|
function computeRepositoryHealth(rows, options = {}) {
|
|
258
231
|
const now = (options.now ?? /* @__PURE__ */ new Date()).getTime();
|
|
@@ -288,31 +261,13 @@ function computeRepositoryHealth(rows, options = {}) {
|
|
|
288
261
|
};
|
|
289
262
|
}
|
|
290
263
|
//#endregion
|
|
291
|
-
//#region src/schema/budget.ts
|
|
292
|
-
const budgetMonthSchema = z.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/);
|
|
293
|
-
const budgetSchema = z.strictObject({
|
|
294
|
-
schemaVersion: schemaVersionSchema,
|
|
295
|
-
factoryId: factoryIdSchema,
|
|
296
|
-
month: budgetMonthSchema,
|
|
297
|
-
limits: z.strictObject({
|
|
298
|
-
totalUsd: usdSchema,
|
|
299
|
-
investigationUsd: usdSchema,
|
|
300
|
-
perTaskReservationUsd: usdSchema,
|
|
301
|
-
warningPercent: z.number().int().min(1).max(100),
|
|
302
|
-
perRepositoryUsd: z.record(repositorySlugSchema, usdSchema).optional()
|
|
303
|
-
}),
|
|
304
|
-
notices: z.strictObject({
|
|
305
|
-
warningAt: isoDateTimeSchema.optional(),
|
|
306
|
-
exhaustedAt: isoDateTimeSchema.optional()
|
|
307
|
-
})
|
|
308
|
-
});
|
|
309
|
-
//#endregion
|
|
310
264
|
//#region src/schema/receipt.ts
|
|
311
265
|
/** States the engine writes on transitions. Any vocabulary value is valid. */
|
|
312
266
|
const standardReceiptStates = [
|
|
313
267
|
"approved",
|
|
314
268
|
"rejected",
|
|
315
269
|
"dispatched",
|
|
270
|
+
"stalled",
|
|
316
271
|
"succeeded",
|
|
317
272
|
"failed",
|
|
318
273
|
"needs_human",
|
|
@@ -421,232 +376,6 @@ const signalSchema = z.strictObject({
|
|
|
421
376
|
});
|
|
422
377
|
});
|
|
423
378
|
//#endregion
|
|
424
|
-
//#region src/schema/transitions.ts
|
|
425
|
-
const taskInitialState = "queued";
|
|
426
|
-
const taskTransitions = [
|
|
427
|
-
{
|
|
428
|
-
from: "queued",
|
|
429
|
-
to: "running",
|
|
430
|
-
trigger: "dependencies have a change, reservation succeeded, devbox created",
|
|
431
|
-
actor: "reconciler"
|
|
432
|
-
},
|
|
433
|
-
{
|
|
434
|
-
from: "queued",
|
|
435
|
-
to: "failed",
|
|
436
|
-
trigger: "reservation refused",
|
|
437
|
-
actor: "reconciler"
|
|
438
|
-
},
|
|
439
|
-
{
|
|
440
|
-
from: "queued",
|
|
441
|
-
to: "needs_human",
|
|
442
|
-
trigger: "kind is question",
|
|
443
|
-
actor: "system"
|
|
444
|
-
},
|
|
445
|
-
{
|
|
446
|
-
from: "queued",
|
|
447
|
-
to: "cancelled",
|
|
448
|
-
trigger: "cancel or kill",
|
|
449
|
-
actor: "operator"
|
|
450
|
-
},
|
|
451
|
-
{
|
|
452
|
-
from: "running",
|
|
453
|
-
to: "verifying",
|
|
454
|
-
trigger: "devbox task reported complete",
|
|
455
|
-
actor: "reconciler"
|
|
456
|
-
},
|
|
457
|
-
{
|
|
458
|
-
from: "running",
|
|
459
|
-
to: "queued",
|
|
460
|
-
trigger: "launch failed below attempt limit",
|
|
461
|
-
actor: "reconciler"
|
|
462
|
-
},
|
|
463
|
-
{
|
|
464
|
-
from: "running",
|
|
465
|
-
to: "failed",
|
|
466
|
-
trigger: "devbox task errored, deadline exceeded, or launch failed at attempt limit",
|
|
467
|
-
actor: "reconciler"
|
|
468
|
-
},
|
|
469
|
-
{
|
|
470
|
-
from: "running",
|
|
471
|
-
to: "needs_human",
|
|
472
|
-
trigger: "devbox task requires attention",
|
|
473
|
-
actor: "reconciler"
|
|
474
|
-
},
|
|
475
|
-
{
|
|
476
|
-
from: "running",
|
|
477
|
-
to: "cancelled",
|
|
478
|
-
trigger: "cancel or kill",
|
|
479
|
-
actor: "operator"
|
|
480
|
-
},
|
|
481
|
-
{
|
|
482
|
-
from: "verifying",
|
|
483
|
-
to: "succeeded",
|
|
484
|
-
trigger: "kind criterion true",
|
|
485
|
-
actor: "reconciler"
|
|
486
|
-
},
|
|
487
|
-
{
|
|
488
|
-
from: "verifying",
|
|
489
|
-
to: "running",
|
|
490
|
-
trigger: "verification failed below attempt limit",
|
|
491
|
-
actor: "reconciler"
|
|
492
|
-
},
|
|
493
|
-
{
|
|
494
|
-
from: "verifying",
|
|
495
|
-
to: "failed",
|
|
496
|
-
trigger: "verification failed at attempt limit",
|
|
497
|
-
actor: "reconciler"
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
from: "verifying",
|
|
501
|
-
to: "cancelled",
|
|
502
|
-
trigger: "cancel or kill",
|
|
503
|
-
actor: "operator"
|
|
504
|
-
},
|
|
505
|
-
{
|
|
506
|
-
from: "needs_human",
|
|
507
|
-
to: "succeeded",
|
|
508
|
-
trigger: "question answered",
|
|
509
|
-
actor: "operator"
|
|
510
|
-
},
|
|
511
|
-
{
|
|
512
|
-
from: "needs_human",
|
|
513
|
-
to: "queued",
|
|
514
|
-
trigger: "operator retry",
|
|
515
|
-
actor: "operator"
|
|
516
|
-
},
|
|
517
|
-
{
|
|
518
|
-
from: "needs_human",
|
|
519
|
-
to: "cancelled",
|
|
520
|
-
trigger: "cancel or kill",
|
|
521
|
-
actor: "operator"
|
|
522
|
-
},
|
|
523
|
-
{
|
|
524
|
-
from: "failed",
|
|
525
|
-
to: "queued",
|
|
526
|
-
trigger: "operator retry",
|
|
527
|
-
actor: "operator"
|
|
528
|
-
}
|
|
529
|
-
];
|
|
530
|
-
const changeInitialState = "verifying";
|
|
531
|
-
const changeTransitions = [
|
|
532
|
-
{
|
|
533
|
-
from: "verifying",
|
|
534
|
-
to: "ready",
|
|
535
|
-
trigger: "verification task succeeded, risk and confidence written",
|
|
536
|
-
actor: "reconciler"
|
|
537
|
-
},
|
|
538
|
-
{
|
|
539
|
-
from: "verifying",
|
|
540
|
-
to: "closed",
|
|
541
|
-
trigger: "verification failed at attempt limit or pr closed upstream",
|
|
542
|
-
actor: "reconciler"
|
|
543
|
-
},
|
|
544
|
-
{
|
|
545
|
-
from: "ready",
|
|
546
|
-
to: "merged",
|
|
547
|
-
trigger: "pr merged on github",
|
|
548
|
-
actor: "webhook"
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
from: "ready",
|
|
552
|
-
to: "closed",
|
|
553
|
-
trigger: "pr closed without merge",
|
|
554
|
-
actor: "webhook"
|
|
555
|
-
},
|
|
556
|
-
{
|
|
557
|
-
from: "merged",
|
|
558
|
-
to: "deployed",
|
|
559
|
-
trigger: "production deployment ready containing the merge sha",
|
|
560
|
-
actor: "webhook"
|
|
561
|
-
},
|
|
562
|
-
{
|
|
563
|
-
from: "deployed",
|
|
564
|
-
to: "rolled_out",
|
|
565
|
-
trigger: "no flag, or flag ramped to full and held",
|
|
566
|
-
actor: "foreman"
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
from: "deployed",
|
|
570
|
-
to: "rolled_back",
|
|
571
|
-
trigger: "rollback rule crossed",
|
|
572
|
-
actor: "foreman"
|
|
573
|
-
},
|
|
574
|
-
{
|
|
575
|
-
from: "rolled_out",
|
|
576
|
-
to: "rolled_back",
|
|
577
|
-
trigger: "rollback rule crossed or flag flipped off",
|
|
578
|
-
actor: "foreman"
|
|
579
|
-
},
|
|
580
|
-
{
|
|
581
|
-
from: "rolled_back",
|
|
582
|
-
to: "deployed",
|
|
583
|
-
trigger: "human retried the ramp",
|
|
584
|
-
actor: "human"
|
|
585
|
-
}
|
|
586
|
-
];
|
|
587
|
-
const signalInitialOutcome = "pending";
|
|
588
|
-
const signalOutcomeTransitions = [
|
|
589
|
-
{
|
|
590
|
-
from: "pending",
|
|
591
|
-
to: "accepted",
|
|
592
|
-
trigger: "classified as actionable",
|
|
593
|
-
actor: "reconciler"
|
|
594
|
-
},
|
|
595
|
-
{
|
|
596
|
-
from: "pending",
|
|
597
|
-
to: "duplicate",
|
|
598
|
-
trigger: "classified as duplicate",
|
|
599
|
-
actor: "reconciler"
|
|
600
|
-
},
|
|
601
|
-
{
|
|
602
|
-
from: "pending",
|
|
603
|
-
to: "unactionable",
|
|
604
|
-
trigger: "classified as unactionable",
|
|
605
|
-
actor: "reconciler"
|
|
606
|
-
},
|
|
607
|
-
{
|
|
608
|
-
from: "pending",
|
|
609
|
-
to: "low_confidence",
|
|
610
|
-
trigger: "classified below confidence threshold",
|
|
611
|
-
actor: "reconciler"
|
|
612
|
-
},
|
|
613
|
-
{
|
|
614
|
-
from: "pending",
|
|
615
|
-
to: "ignored",
|
|
616
|
-
trigger: "classified as ignorable",
|
|
617
|
-
actor: "reconciler"
|
|
618
|
-
}
|
|
619
|
-
];
|
|
620
|
-
function isTransitionAllowed(transitions, from, to) {
|
|
621
|
-
return transitions.some((transition) => transition.from === from && transition.to === to);
|
|
622
|
-
}
|
|
623
|
-
function legalNextStates(transitions, from) {
|
|
624
|
-
return [...new Set(transitions.filter((transition) => transition.from === from).map((t) => t.to))];
|
|
625
|
-
}
|
|
626
|
-
var InvalidTransitionError = class extends Error {
|
|
627
|
-
from;
|
|
628
|
-
to;
|
|
629
|
-
legalNextStates;
|
|
630
|
-
constructor(from, to, legal) {
|
|
631
|
-
super(legal.length > 0 ? `invalid transition from "${from}" to "${to}"; legal next states: ${legal.map((state) => `"${state}"`).join(", ")}` : `invalid transition from "${from}" to "${to}"; "${from}" is terminal`);
|
|
632
|
-
this.name = "InvalidTransitionError";
|
|
633
|
-
this.from = from;
|
|
634
|
-
this.to = to;
|
|
635
|
-
this.legalNextStates = legal;
|
|
636
|
-
}
|
|
637
|
-
};
|
|
638
|
-
function assertTransition(transitions, from, to) {
|
|
639
|
-
if (!isTransitionAllowed(transitions, from, to)) throw new InvalidTransitionError(from, to, legalNextStates(transitions, from));
|
|
640
|
-
}
|
|
641
|
-
function terminalStates(transitions) {
|
|
642
|
-
const states = /* @__PURE__ */ new Set();
|
|
643
|
-
for (const transition of transitions) {
|
|
644
|
-
states.add(transition.from);
|
|
645
|
-
states.add(transition.to);
|
|
646
|
-
}
|
|
647
|
-
return [...states].filter((state) => !transitions.some((transition) => transition.from === state));
|
|
648
|
-
}
|
|
649
|
-
//#endregion
|
|
650
379
|
//#region src/signals.ts
|
|
651
380
|
/**
|
|
652
381
|
* Bind normalized intake to signal creation alone. Connectors and API routes
|
|
@@ -659,6 +388,64 @@ function createSignalCreator(stores) {
|
|
|
659
388
|
} };
|
|
660
389
|
}
|
|
661
390
|
//#endregion
|
|
391
|
+
//#region src/stall.ts
|
|
392
|
+
function stallWindowMinutes(policy, kind) {
|
|
393
|
+
return policy.stallMinutesByKind[kind] ?? policy.stallMinutes;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* The reconciler's stall pass. A running task whose execution has not
|
|
397
|
+
* progressed within its stall window is marked stalled; a stalled task is
|
|
398
|
+
* re-queued for a replacement attempt while attempts remain, and failed once
|
|
399
|
+
* they are exhausted. Only `running` tasks can stall: a task whose result has
|
|
400
|
+
* already been recorded (verifying, or terminal) is never retried by this
|
|
401
|
+
* pass. Coordination parents run only through their children and are skipped.
|
|
402
|
+
*/
|
|
403
|
+
async function sweepStalled(stores, options) {
|
|
404
|
+
const nowMs = (options.now ?? (() => /* @__PURE__ */ new Date()))().getTime();
|
|
405
|
+
const result = {
|
|
406
|
+
stalled: [],
|
|
407
|
+
requeued: [],
|
|
408
|
+
failed: []
|
|
409
|
+
};
|
|
410
|
+
const tasks = await stores.tasks.list();
|
|
411
|
+
for (const task of tasks) {
|
|
412
|
+
if (task.state !== "running" || task.kind === "coordination") continue;
|
|
413
|
+
const minutes = stallWindowMinutes(options.policy, task.kind);
|
|
414
|
+
const sinceProgress = nowMs - Date.parse(task.lastProgressAt ?? task.updatedAt);
|
|
415
|
+
if (sinceProgress < minutes * 6e4) continue;
|
|
416
|
+
try {
|
|
417
|
+
await stores.tasks.transition(task.id, "stalled", {
|
|
418
|
+
reason: `no progress for ${Math.floor(sinceProgress / 6e4)} minutes (window ${minutes})`,
|
|
419
|
+
expectFrom: "running"
|
|
420
|
+
});
|
|
421
|
+
result.stalled.push(task.id);
|
|
422
|
+
} catch {
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
for (const task of await stores.tasks.list()) {
|
|
427
|
+
if (task.state !== "stalled") continue;
|
|
428
|
+
try {
|
|
429
|
+
if (task.attempt < options.policy.maxAttempts) {
|
|
430
|
+
await stores.tasks.transition(task.id, "queued", {
|
|
431
|
+
reason: `stalled on attempt ${task.attempt} of ${options.policy.maxAttempts}; replacing`,
|
|
432
|
+
expectFrom: "stalled"
|
|
433
|
+
});
|
|
434
|
+
result.requeued.push(task.id);
|
|
435
|
+
} else {
|
|
436
|
+
await stores.tasks.transition(task.id, "failed", {
|
|
437
|
+
reason: `stalled on attempt ${task.attempt} of ${options.policy.maxAttempts}; attempts exhausted`,
|
|
438
|
+
expectFrom: "stalled"
|
|
439
|
+
});
|
|
440
|
+
result.failed.push(task.id);
|
|
441
|
+
}
|
|
442
|
+
} catch {
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return result;
|
|
447
|
+
}
|
|
448
|
+
//#endregion
|
|
662
449
|
//#region src/store/engine.ts
|
|
663
450
|
/** An approval decision that does not apply to the task's current approval or state. */
|
|
664
451
|
var ApprovalError = class extends Error {
|
|
@@ -671,6 +458,17 @@ var ApprovalError = class extends Error {
|
|
|
671
458
|
this.reason = reason;
|
|
672
459
|
}
|
|
673
460
|
};
|
|
461
|
+
/** A settlement that does not apply to the task's current state. */
|
|
462
|
+
var SettlementError = class extends Error {
|
|
463
|
+
taskId;
|
|
464
|
+
reason;
|
|
465
|
+
constructor(taskId, reason) {
|
|
466
|
+
super(`settlement on "${taskId}" refused: ${reason}`);
|
|
467
|
+
this.name = "SettlementError";
|
|
468
|
+
this.taskId = taskId;
|
|
469
|
+
this.reason = reason;
|
|
470
|
+
}
|
|
471
|
+
};
|
|
674
472
|
var ChangeAssociationError = class extends Error {
|
|
675
473
|
taskId;
|
|
676
474
|
repositoryId;
|
|
@@ -685,6 +483,7 @@ var ChangeAssociationError = class extends Error {
|
|
|
685
483
|
};
|
|
686
484
|
const taskReceiptStates = {
|
|
687
485
|
running: "dispatched",
|
|
486
|
+
stalled: "stalled",
|
|
688
487
|
succeeded: "succeeded",
|
|
689
488
|
failed: "failed",
|
|
690
489
|
needs_human: "needs_human",
|
|
@@ -706,6 +505,17 @@ function derivedId(prefix, key) {
|
|
|
706
505
|
function bumpsAttempt(from, to) {
|
|
707
506
|
return to === "queued" || from === "verifying" && to === "running";
|
|
708
507
|
}
|
|
508
|
+
const emptyUsage = {
|
|
509
|
+
costUsd: 0,
|
|
510
|
+
inputTokens: 0,
|
|
511
|
+
outputTokens: 0,
|
|
512
|
+
cacheReadTokens: 0,
|
|
513
|
+
cacheWriteTokens: 0,
|
|
514
|
+
steps: {}
|
|
515
|
+
};
|
|
516
|
+
function addUsd(a, b) {
|
|
517
|
+
return (Math.round(a * 1e6) + Math.round(b * 1e6)) / 1e6;
|
|
518
|
+
}
|
|
709
519
|
function createStores(options) {
|
|
710
520
|
const { driver } = options;
|
|
711
521
|
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -741,7 +551,7 @@ function createStores(options) {
|
|
|
741
551
|
}
|
|
742
552
|
}
|
|
743
553
|
async function appendReceipt(key, receipt) {
|
|
744
|
-
|
|
554
|
+
return insertReceipt(derivedId("rcpt", key), receipt);
|
|
745
555
|
}
|
|
746
556
|
return {
|
|
747
557
|
driverName: driver.name,
|
|
@@ -807,9 +617,10 @@ function createStores(options) {
|
|
|
807
617
|
tasks: {
|
|
808
618
|
async create(input) {
|
|
809
619
|
const timestamp = now();
|
|
620
|
+
const id = input.dedupeKey === void 0 ? randomId("task") : derivedId("task", input.dedupeKey);
|
|
810
621
|
const task = taskSchema.parse({
|
|
811
622
|
schemaVersion: 1,
|
|
812
|
-
id
|
|
623
|
+
id,
|
|
813
624
|
repositoryIds: input.repositoryIds,
|
|
814
625
|
kind: input.kind,
|
|
815
626
|
area: input.area,
|
|
@@ -820,11 +631,17 @@ function createStores(options) {
|
|
|
820
631
|
replyTo: input.replyTo,
|
|
821
632
|
attempt: 1,
|
|
822
633
|
question: input.question,
|
|
634
|
+
changeId: input.changeId,
|
|
823
635
|
createdAt: timestamp,
|
|
824
636
|
updatedAt: timestamp
|
|
825
637
|
});
|
|
826
|
-
|
|
827
|
-
|
|
638
|
+
try {
|
|
639
|
+
await driver.insert("tasks", task.id, task);
|
|
640
|
+
return task;
|
|
641
|
+
} catch (error) {
|
|
642
|
+
if (input.dedupeKey !== void 0 && error instanceof RecordExistsError) return (await mustRead("tasks", task.id, taskSchema)).value;
|
|
643
|
+
throw error;
|
|
644
|
+
}
|
|
828
645
|
},
|
|
829
646
|
async approve(id, decision) {
|
|
830
647
|
const existing = await mustRead("tasks", id, taskSchema);
|
|
@@ -883,30 +700,124 @@ function createStores(options) {
|
|
|
883
700
|
await driver.update("tasks", id, next, existing.version);
|
|
884
701
|
return next;
|
|
885
702
|
},
|
|
703
|
+
async recordExecution(id, execution) {
|
|
704
|
+
const existing = await mustRead("tasks", id, taskSchema);
|
|
705
|
+
const task = existing.value;
|
|
706
|
+
if (task.state !== "running") throw new InvalidTransitionError(task.state, "running", legalNextStates(taskTransitions, task.state));
|
|
707
|
+
const timestamp = now();
|
|
708
|
+
const next = taskSchema.parse({
|
|
709
|
+
...task,
|
|
710
|
+
execution,
|
|
711
|
+
lastProgressAt: timestamp,
|
|
712
|
+
updatedAt: timestamp
|
|
713
|
+
});
|
|
714
|
+
await driver.update("tasks", id, next, existing.version);
|
|
715
|
+
return next;
|
|
716
|
+
},
|
|
717
|
+
async recordUsage(id, step) {
|
|
718
|
+
for (;;) {
|
|
719
|
+
const existing = await mustRead("tasks", id, taskSchema);
|
|
720
|
+
const task = existing.value;
|
|
721
|
+
const usage = task.usage ?? emptyUsage;
|
|
722
|
+
const recordedIndex = usage.steps[step.turnId];
|
|
723
|
+
if (recordedIndex !== void 0 && step.stepIndex <= recordedIndex) return task;
|
|
724
|
+
const timestamp = now();
|
|
725
|
+
const next = taskSchema.parse({
|
|
726
|
+
...task,
|
|
727
|
+
lastProgressAt: timestamp,
|
|
728
|
+
usage: {
|
|
729
|
+
costUsd: addUsd(usage.costUsd, step.costUsd ?? 0),
|
|
730
|
+
inputTokens: usage.inputTokens + (step.inputTokens ?? 0),
|
|
731
|
+
outputTokens: usage.outputTokens + (step.outputTokens ?? 0),
|
|
732
|
+
cacheReadTokens: usage.cacheReadTokens + (step.cacheReadTokens ?? 0),
|
|
733
|
+
cacheWriteTokens: usage.cacheWriteTokens + (step.cacheWriteTokens ?? 0),
|
|
734
|
+
steps: {
|
|
735
|
+
...usage.steps,
|
|
736
|
+
[step.turnId]: step.stepIndex
|
|
737
|
+
}
|
|
738
|
+
},
|
|
739
|
+
updatedAt: timestamp
|
|
740
|
+
});
|
|
741
|
+
try {
|
|
742
|
+
await driver.update("tasks", id, next, existing.version);
|
|
743
|
+
return next;
|
|
744
|
+
} catch (error) {
|
|
745
|
+
if (!(error instanceof VersionConflictError)) throw error;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
},
|
|
749
|
+
async settle(id, cost, settleOptions = {}) {
|
|
750
|
+
const existing = await mustRead("tasks", id, taskSchema);
|
|
751
|
+
const task = existing.value;
|
|
752
|
+
if (task.settledUsd !== void 0) return task;
|
|
753
|
+
if (task.state !== "succeeded" && task.state !== "failed" && task.state !== "cancelled") throw new SettlementError(id, `task is ${task.state}, not terminal`);
|
|
754
|
+
const validated = costSchema.parse(cost);
|
|
755
|
+
const normalized = { totalUsd: Math.round(validated.totalUsd * 1e6) / 1e6 };
|
|
756
|
+
let recorded = normalized;
|
|
757
|
+
if (task.repositoryIds !== void 0) recorded = (await appendReceipt(`task:${id}:settled:${task.attempt}`, {
|
|
758
|
+
repositoryIds: task.repositoryIds,
|
|
759
|
+
taskId: id,
|
|
760
|
+
changeId: task.changeId,
|
|
761
|
+
kind: task.kind,
|
|
762
|
+
state: "settled",
|
|
763
|
+
phase: "budget",
|
|
764
|
+
reason: settleOptions.reason,
|
|
765
|
+
attempt: task.attempt,
|
|
766
|
+
cost: normalized
|
|
767
|
+
})).cost ?? normalized;
|
|
768
|
+
const next = taskSchema.parse({
|
|
769
|
+
...task,
|
|
770
|
+
settledUsd: recorded.totalUsd,
|
|
771
|
+
updatedAt: now()
|
|
772
|
+
});
|
|
773
|
+
await driver.update("tasks", id, next, existing.version);
|
|
774
|
+
return next;
|
|
775
|
+
},
|
|
886
776
|
async get(id) {
|
|
887
777
|
const record = await read("tasks", id, taskSchema);
|
|
888
778
|
return record === null ? null : record.value;
|
|
889
779
|
},
|
|
890
780
|
async transition(id, to, transitionOptions = {}) {
|
|
781
|
+
if (transitionOptions.patch !== void 0 && "settledUsd" in transitionOptions.patch) throw new SettlementError(id, "settledUsd is set only by settle, not a transition");
|
|
782
|
+
if (transitionOptions.patch !== void 0 && "usage" in transitionOptions.patch) throw new SettlementError(id, "usage is set only by recordUsage, not a transition");
|
|
891
783
|
const existing = await mustRead("tasks", id, taskSchema);
|
|
784
|
+
if (transitionOptions.expectFrom !== void 0 && existing.value.state !== transitionOptions.expectFrom) throw new InvalidTransitionError(existing.value.state, to, legalNextStates(taskTransitions, existing.value.state));
|
|
892
785
|
assertTransition(taskTransitions, existing.value.state, to);
|
|
893
|
-
|
|
786
|
+
if (to === "needs_human" && existing.value.kind !== "question") {
|
|
787
|
+
if (!(await listAll("tasks", taskSchema)).some((task) => task.kind === "question" && task.state === "needs_human" && task.origin.parentTaskId === id)) throw new Error(`task ${id} cannot enter needs_human without an open QuestionTask`);
|
|
788
|
+
}
|
|
789
|
+
const bumps = bumpsAttempt(existing.value.state, to);
|
|
790
|
+
const timestamp = now();
|
|
791
|
+
const { stalledAt: _stalledAt, stalledReason: _stalledReason, ...cleared } = existing.value;
|
|
894
792
|
const next = taskSchema.parse({
|
|
895
|
-
...
|
|
793
|
+
...cleared,
|
|
794
|
+
...bumps ? { execution: void 0 } : {},
|
|
896
795
|
...transitionOptions.patch,
|
|
796
|
+
...to === "stalled" ? {
|
|
797
|
+
stalledAt: timestamp,
|
|
798
|
+
stalledReason: transitionOptions.reason
|
|
799
|
+
} : {},
|
|
800
|
+
...to === "running" ? { lastProgressAt: timestamp } : {},
|
|
897
801
|
state: to,
|
|
898
|
-
attempt,
|
|
899
|
-
updatedAt:
|
|
802
|
+
attempt: bumps ? existing.value.attempt + 1 : existing.value.attempt,
|
|
803
|
+
updatedAt: timestamp
|
|
900
804
|
});
|
|
901
805
|
const receiptState = taskReceiptStates[to];
|
|
902
|
-
if (receiptState !== void 0 && next.repositoryIds !== void 0) await appendReceipt(
|
|
806
|
+
if (receiptState !== void 0 && next.repositoryIds !== void 0) await appendReceipt(JSON.stringify([
|
|
807
|
+
"task",
|
|
808
|
+
id,
|
|
809
|
+
receiptState,
|
|
810
|
+
next.attempt,
|
|
811
|
+
next.changeId ?? null,
|
|
812
|
+
transitionOptions.reason ?? null
|
|
813
|
+
]), {
|
|
903
814
|
repositoryIds: next.repositoryIds,
|
|
904
815
|
taskId: id,
|
|
905
816
|
changeId: next.changeId,
|
|
906
817
|
kind: next.kind,
|
|
907
818
|
state: receiptState,
|
|
908
819
|
reason: transitionOptions.reason,
|
|
909
|
-
attempt
|
|
820
|
+
attempt: next.attempt
|
|
910
821
|
});
|
|
911
822
|
await driver.update("tasks", id, next, existing.version);
|
|
912
823
|
return next;
|
|
@@ -990,6 +901,66 @@ function createStores(options) {
|
|
|
990
901
|
list() {
|
|
991
902
|
return listAll("receipts", receiptSchema);
|
|
992
903
|
}
|
|
904
|
+
},
|
|
905
|
+
budgets: {
|
|
906
|
+
async ensure(input) {
|
|
907
|
+
const budget = budgetSchema.parse({
|
|
908
|
+
schemaVersion: 1,
|
|
909
|
+
factoryId: input.factoryId,
|
|
910
|
+
month: input.month,
|
|
911
|
+
limits: input.limits,
|
|
912
|
+
notices: {}
|
|
913
|
+
});
|
|
914
|
+
try {
|
|
915
|
+
await driver.insert("budgets", input.month, budget);
|
|
916
|
+
return budget;
|
|
917
|
+
} catch (error) {
|
|
918
|
+
if (!(error instanceof RecordExistsError)) throw error;
|
|
919
|
+
}
|
|
920
|
+
const existing = await mustRead("budgets", input.month, budgetSchema);
|
|
921
|
+
const refreshed = budgetSchema.parse({
|
|
922
|
+
...existing.value,
|
|
923
|
+
limits: input.limits
|
|
924
|
+
});
|
|
925
|
+
if (JSON.stringify(refreshed) === JSON.stringify(existing.value)) return existing.value;
|
|
926
|
+
try {
|
|
927
|
+
await driver.update("budgets", input.month, refreshed, existing.version);
|
|
928
|
+
return refreshed;
|
|
929
|
+
} catch (error) {
|
|
930
|
+
if (error instanceof VersionConflictError) return (await mustRead("budgets", input.month, budgetSchema)).value;
|
|
931
|
+
throw error;
|
|
932
|
+
}
|
|
933
|
+
},
|
|
934
|
+
async get(month) {
|
|
935
|
+
const record = await read("budgets", month, budgetSchema);
|
|
936
|
+
return record === null ? null : record.value;
|
|
937
|
+
},
|
|
938
|
+
async stampNotice(month, notice) {
|
|
939
|
+
const field = notice === "warning" ? "warningAt" : "exhaustedAt";
|
|
940
|
+
for (;;) {
|
|
941
|
+
const existing = await mustRead("budgets", month, budgetSchema);
|
|
942
|
+
if (existing.value.notices[field] !== void 0) return {
|
|
943
|
+
budget: existing.value,
|
|
944
|
+
stamped: false
|
|
945
|
+
};
|
|
946
|
+
const next = budgetSchema.parse({
|
|
947
|
+
...existing.value,
|
|
948
|
+
notices: {
|
|
949
|
+
...existing.value.notices,
|
|
950
|
+
[field]: now()
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
try {
|
|
954
|
+
await driver.update("budgets", month, next, existing.version);
|
|
955
|
+
return {
|
|
956
|
+
budget: next,
|
|
957
|
+
stamped: true
|
|
958
|
+
};
|
|
959
|
+
} catch (error) {
|
|
960
|
+
if (!(error instanceof VersionConflictError)) throw error;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
993
964
|
}
|
|
994
965
|
};
|
|
995
966
|
}
|
|
@@ -1097,7 +1068,10 @@ async function sweepQueued(stores, options) {
|
|
|
1097
1068
|
continue;
|
|
1098
1069
|
}
|
|
1099
1070
|
try {
|
|
1100
|
-
await dispatchTask(stores, task.id, {
|
|
1071
|
+
await dispatchTask(stores, task.id, {
|
|
1072
|
+
launch: (dispatched) => launcher(dispatched, repository),
|
|
1073
|
+
budget: options.budget
|
|
1074
|
+
});
|
|
1101
1075
|
result.dispatched.push(task.id);
|
|
1102
1076
|
} catch (error) {
|
|
1103
1077
|
if (error instanceof DispatchRefusedError) {
|
|
@@ -1116,6 +1090,35 @@ async function sweepQueued(stores, options) {
|
|
|
1116
1090
|
return result;
|
|
1117
1091
|
}
|
|
1118
1092
|
//#endregion
|
|
1119
|
-
|
|
1093
|
+
//#region src/verification-dispatch.ts
|
|
1094
|
+
/** Ensure every recorded code change has exactly one durable verification task. */
|
|
1095
|
+
async function ensureVerificationTasks(stores) {
|
|
1096
|
+
const tasks = await stores.tasks.list();
|
|
1097
|
+
const existingIds = new Set(tasks.map((task) => task.id));
|
|
1098
|
+
const result = {
|
|
1099
|
+
created: [],
|
|
1100
|
+
existing: []
|
|
1101
|
+
};
|
|
1102
|
+
const sources = tasks.filter((task) => task.kind === "code_change" && task.state === "verifying" && task.changeId !== void 0);
|
|
1103
|
+
for (const source of sources) {
|
|
1104
|
+
const existing = tasks.find((task) => task.kind === "verification" && task.origin.parentTaskId === source.id);
|
|
1105
|
+
if (existing !== void 0) {
|
|
1106
|
+
result.existing.push(existing.id);
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
const verification = await stores.tasks.create({
|
|
1110
|
+
repositoryIds: source.repositoryIds,
|
|
1111
|
+
kind: "verification",
|
|
1112
|
+
origin: { parentTaskId: source.id },
|
|
1113
|
+
replyTo: source.replyTo,
|
|
1114
|
+
changeId: source.changeId,
|
|
1115
|
+
dedupeKey: `verification:${source.id}:${source.changeId}`
|
|
1116
|
+
});
|
|
1117
|
+
(existingIds.has(verification.id) ? result.existing : result.created).push(verification.id);
|
|
1118
|
+
}
|
|
1119
|
+
return result;
|
|
1120
|
+
}
|
|
1121
|
+
//#endregion
|
|
1122
|
+
export { ApprovalError, BudgetExhaustedError, ChangeAssociationError, DEFAULT_MAX_LAUNCH_ATTEMPTS, DispatchRefusedError, InvalidTransitionError, RecordExistsError, RecordNotFoundError, SCHEMA_VERSION, SettlementError, VersionConflictError, adoptPullRequest, agentRouteSchema, approvalPolicySchema, approvalRuleSchema, assertTransition, budgetLimitsSchema, budgetMonthOf, budgetMonthSchema, budgetSchema, budgetStatus, canReserve, changeEvidenceSchema, changeIdSchema, changeInitialState, changeSchema, changeStateSchema, changeTransitions, computeLedgerMetrics, computeMonthSpendUsd, computeRepositoryHealth, coordinationRepositoryIdsSchema, costSchema, createCoordination, createInMemoryDriver, createSignalCreator, createStores, defaultApprovalPolicy, defaultExecutionPolicy, defineAgentRoutes, defineFactory, deriveFactoryId, dispatchTask, ensureVerificationTasks, executionPolicySchema, executionReferenceSchema, factoryConfigRepositorySchema, factoryConfigSchema, factoryIdSchema, findingCategorySchema, findingFingerprint, findingForTask, findingPrioritySchema, findingSchema, findingVerificationLevelSchema, findingVerificationMethodSchema, findingVerificationSchema, fixBrief, harnessSchema, isTransitionAllowed, isoDateTimeSchema, legalNextStates, levelSchema, receiptIdSchema, receiptKindSchema, receiptPhaseSchema, receiptSchema, receiptStateSchema, reconcileCoordination, replyToSchema, repositoryIdSchema, repositoryIdsSchema, repositorySchema, repositorySlugSchema, requiresApproval, reviewBucket, scanBrief, schemaVersionSchema, signalIdSchema, signalInitialOutcome, signalOutcomeSchema, signalOutcomeTransitions, signalSchema, signalSourceSchema, stallWindowMinutes, standardReceiptKinds, standardReceiptPhases, standardReceiptStates, standardSignalSources, standardTaskKinds, sweepBudget, sweepQueued, sweepSettlements, sweepStalled, taskApprovalSchema, taskExecutionRepositoryIdsSchema, taskIdSchema, taskInitialState, taskKindSchema, taskOriginSchema, taskQuestionSchema, taskSchema, taskStateSchema, taskTransitions, taskUsageSchema, terminalStates, usdSchema, verificationBrief, vocabularySchema };
|
|
1120
1123
|
|
|
1121
1124
|
//# sourceMappingURL=index.mjs.map
|