@mastra/factory 0.15.1-alpha.0 → 0.16.0-alpha.6
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/boards/index.d.ts +1 -1
- package/dist/boards/index.d.ts.map +1 -1
- package/dist/boards/index.js +2 -2
- package/dist/boards/index.js.map +1 -1
- package/dist/boards/review.d.ts.map +1 -1
- package/dist/boards/review.js +4 -1
- package/dist/boards/review.js.map +1 -1
- package/dist/boards/semantics.d.ts +7 -0
- package/dist/boards/semantics.d.ts.map +1 -1
- package/dist/boards/semantics.js +15 -1
- package/dist/boards/semantics.js.map +1 -1
- package/dist/capabilities/intake.d.ts +4 -0
- package/dist/capabilities/intake.d.ts.map +1 -1
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +25 -11
- package/dist/factory.js.map +1 -1
- package/dist/integrations/linear/claim.d.ts +8 -0
- package/dist/integrations/linear/claim.d.ts.map +1 -0
- package/dist/integrations/linear/claim.js +14 -0
- package/dist/integrations/linear/claim.js.map +1 -0
- package/dist/integrations/linear/default-rules.d.ts +1 -0
- package/dist/integrations/linear/default-rules.d.ts.map +1 -1
- package/dist/integrations/linear/default-rules.js +2 -0
- package/dist/integrations/linear/default-rules.js.map +1 -1
- package/dist/integrations/linear/integration.d.ts +24 -6
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/integration.js +257 -37
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/routes.d.ts +10 -0
- package/dist/integrations/linear/routes.d.ts.map +1 -1
- package/dist/integrations/linear/routes.js +74 -10
- package/dist/integrations/linear/routes.js.map +1 -1
- package/dist/integrations/linear/rules.d.ts +1 -1
- package/dist/integrations/linear/rules.d.ts.map +1 -1
- package/dist/integrations/linear/rules.js +27 -2
- package/dist/integrations/linear/rules.js.map +1 -1
- package/dist/integrations/platform/linear/integration.d.ts +34 -1
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +271 -48
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/routes/intake.d.ts.map +1 -1
- package/dist/routes/intake.js +12 -2
- package/dist/routes/intake.js.map +1 -1
- package/dist/rules/dispatch-errors.d.ts.map +1 -1
- package/dist/rules/dispatch-errors.js +8 -0
- package/dist/rules/dispatch-errors.js.map +1 -1
- package/dist/rules/dispatcher.d.ts +1 -0
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +179 -105
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +4 -1
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/rules/terminal-cleanup.d.ts +14 -1
- package/dist/rules/terminal-cleanup.d.ts.map +1 -1
- package/dist/rules/terminal-cleanup.js +20 -0
- package/dist/rules/terminal-cleanup.js.map +1 -1
- package/dist/rules/tools.d.ts +2 -0
- package/dist/rules/tools.d.ts.map +1 -1
- package/dist/rules/tools.js +30 -2
- package/dist/rules/tools.js.map +1 -1
- package/dist/rules/transition-service.d.ts +3 -0
- package/dist/rules/transition-service.d.ts.map +1 -1
- package/dist/rules/transition-service.js +4 -2
- package/dist/rules/transition-service.js.map +1 -1
- package/dist/rules/types.d.ts +15 -0
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.d.ts.map +1 -1
- package/dist/rules/validation.js +11 -2
- package/dist/rules/validation.js.map +1 -1
- package/dist/session/run-audit.d.ts +9 -0
- package/dist/session/run-audit.d.ts.map +1 -1
- package/dist/session/run-audit.js +37 -6
- package/dist/session/run-audit.js.map +1 -1
- package/dist/skills/service.d.ts +12 -0
- package/dist/skills/service.d.ts.map +1 -1
- package/dist/skills/service.js +27 -1
- package/dist/skills/service.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +41 -2
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +159 -12
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/supervisor/session-messaging.d.ts +23 -0
- package/dist/supervisor/session-messaging.d.ts.map +1 -0
- package/dist/supervisor/session-messaging.js +15 -0
- package/dist/supervisor/session-messaging.js.map +1 -0
- package/dist/supervisor/write-tools.d.ts +2 -1
- package/dist/supervisor/write-tools.d.ts.map +1 -1
- package/dist/supervisor/write-tools.js +11 -7
- package/dist/supervisor/write-tools.js.map +1 -1
- package/package.json +10 -10
|
@@ -21,6 +21,26 @@ function createTerminalStageCleanup(options) {
|
|
|
21
21
|
id: args.workItemId
|
|
22
22
|
}).catch(() => null);
|
|
23
23
|
if (args.revision !== void 0 && item?.revision !== args.revision) return;
|
|
24
|
+
if (options.abortSession) try {
|
|
25
|
+
const active = await options.workItems.listRunBindings(args.orgId, args.factoryProjectId, args.workItemId);
|
|
26
|
+
for (const binding of active) {
|
|
27
|
+
if (binding.status !== "active") continue;
|
|
28
|
+
if (binding.id === args.initiatingBindingId) continue;
|
|
29
|
+
let current;
|
|
30
|
+
try {
|
|
31
|
+
current = await options.workItems.findRunBindingBySession({
|
|
32
|
+
factoryProjectId: binding.factoryProjectId,
|
|
33
|
+
threadId: binding.threadId,
|
|
34
|
+
resourceId: binding.resourceId,
|
|
35
|
+
sessionId: binding.sessionId
|
|
36
|
+
});
|
|
37
|
+
} catch {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (current && current.status === "active" && current.workItemId !== args.workItemId) continue;
|
|
41
|
+
await options.abortSession(binding).catch(() => {});
|
|
42
|
+
}
|
|
43
|
+
} catch {}
|
|
24
44
|
try {
|
|
25
45
|
await options.workItems.revokeRunBindingsForWorkItem({
|
|
26
46
|
orgId: args.orgId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-cleanup.js","names":[],"sources":["../../src/rules/terminal-cleanup.ts"],"sourcesContent":["import type { FactoryRunBindingRecord, WorkItemsStorage } from '../storage/domains/work-items/base.js';\n\nexport interface TerminalStageCleanupOptions {\n workItems: Pick<\n WorkItemsStorage,\n 'get'
|
|
1
|
+
{"version":3,"file":"terminal-cleanup.js","names":[],"sources":["../../src/rules/terminal-cleanup.ts"],"sourcesContent":["import type { FactoryRunBindingRecord, WorkItemsStorage } from '../storage/domains/work-items/base.js';\n\nexport interface TerminalStageCleanupOptions {\n workItems: Pick<\n WorkItemsStorage,\n | 'get'\n | 'listRunBindings'\n | 'revokeRunBindingsForWorkItem'\n | 'supersedeTerminalDecisionsForWorkItem'\n | 'findRunBindingBySession'\n >;\n /** Final ingest of trailing tool results before the binding is revoked. */\n reconcileBinding?: (binding: FactoryRunBindingRecord) => Promise<void>;\n /**\n * Abort the live controller run bound to a retired seat. Without this the\n * model keeps executing unbound after its binding is revoked (its transition\n * tool vanishes or throws), and the parked run can later be resumed and\n * rationalize a false blocked state.\n */\n abortSession?: (binding: FactoryRunBindingRecord) => Promise<void>;\n /** Release the item's session sandboxes back to the reuse pool. */\n releaseSandboxes?: (args: TerminalStageCleanupArgs) => Promise<unknown>;\n}\n\nexport interface TerminalStageCleanupArgs {\n orgId: string;\n factoryProjectId: string;\n workItemId: string;\n /** Revision produced by the terminal transition that scheduled this cleanup. */\n revision?: number;\n /**\n * The bound agent seat whose own tool call drove this terminal transition, if\n * any. Its run is already returning from the tool call; aborting it would\n * interrupt its own completion, so it is left alone.\n */\n initiatingBindingId?: string;\n}\n\n/**\n * Terminal-stage cleanup for a work item: ingest any trailing tool results\n * from the item's bound threads, revoke its active run bindings so completed\n * items leave the reconcile walk (the active set otherwise grows forever),\n * dismiss the runs still parked on it, then release its sandboxes. Every step\n * is best-effort — a committed transition never fails on cleanup; leaked\n * bindings are drained by the staleness sweep.\n */\nexport function createTerminalStageCleanup(options: TerminalStageCleanupOptions) {\n return async (args: TerminalStageCleanupArgs): Promise<void> => {\n try {\n const bindings = await options.workItems.listRunBindings(args.orgId, args.factoryProjectId, args.workItemId);\n for (const binding of bindings) {\n if (binding.status !== 'active') continue;\n // The tool result that drove this terminal transition (e.g. PR\n // creation) may not be ingested yet — reconcile before revoking.\n await options.reconcileBinding?.(binding).catch(() => {});\n }\n } catch {\n // Best-effort; revocation below does not depend on the listing.\n }\n // Cleanup can outlive the terminal transition's response window. Do not\n // revoke a new binding or retire its workspace if the card has since been\n // re-entered for another pass.\n const item = await options.workItems.get({ orgId: args.orgId, id: args.workItemId }).catch(() => null);\n if (args.revision !== undefined && item?.revision !== args.revision) return;\n\n // Stop the live runs still executing on this item's seats before the\n // bindings are revoked, so no model keeps running unbound (and no parked\n // run can later be resumed) once its transition tool is gone.\n if (options.abortSession) {\n try {\n const active = await options.workItems.listRunBindings(args.orgId, args.factoryProjectId, args.workItemId);\n for (const binding of active) {\n if (binding.status !== 'active') continue;\n // The seat that drove this transition is already ending gracefully.\n if (binding.id === args.initiatingBindingId) continue;\n // A role handoff or reopen may have rebound this session to a newer\n // active run for another item; aborting would kill that successor.\n // If the lookup fails we cannot rule out a successor, so skip the\n // abort — revocation below still severs this seat's authority, and a\n // false abort would kill a live run for a different work item.\n let current: FactoryRunBindingRecord | null;\n try {\n current = await options.workItems.findRunBindingBySession({\n factoryProjectId: binding.factoryProjectId,\n threadId: binding.threadId,\n resourceId: binding.resourceId,\n sessionId: binding.sessionId,\n });\n } catch {\n continue;\n }\n if (current && current.status === 'active' && current.workItemId !== args.workItemId) continue;\n await options.abortSession(binding).catch(() => {});\n }\n } catch {\n // Best-effort; revocation below still severs the seat's authority.\n }\n }\n\n try {\n await options.workItems.revokeRunBindingsForWorkItem({\n orgId: args.orgId,\n factoryProjectId: args.factoryProjectId,\n workItemId: args.workItemId,\n revokedAt: new Date(),\n });\n } catch {\n // Best-effort; the staleness sweep retries later.\n }\n try {\n await options.workItems.supersedeTerminalDecisionsForWorkItem({\n orgId: args.orgId,\n factoryProjectId: args.factoryProjectId,\n workItemId: args.workItemId,\n supersededAt: new Date(),\n });\n } catch {\n // Best-effort; legacy rows are repaired at the next startup.\n }\n try {\n await options.releaseSandboxes?.(args);\n } catch {\n // Best-effort; a leaked sandbox is retired by the next reconcile walk.\n }\n };\n}\n"],"mappings":";;;;;;;;;AA8CA,SAAgB,2BAA2B,SAAsC;CAC/E,OAAO,OAAO,SAAkD;EAC9D,IAAI;GACF,MAAM,WAAW,MAAM,QAAQ,UAAU,gBAAgB,KAAK,OAAO,KAAK,kBAAkB,KAAK,UAAU;GAC3G,KAAK,MAAM,WAAW,UAAU;IAC9B,IAAI,QAAQ,WAAW,UAAU;IAGjC,MAAM,QAAQ,mBAAmB,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;GAC1D;EACF,QAAQ,CAER;EAIA,MAAM,OAAO,MAAM,QAAQ,UAAU,IAAI;GAAE,OAAO,KAAK;GAAO,IAAI,KAAK;EAAW,CAAC,CAAC,CAAC,YAAY,IAAI;EACrG,IAAI,KAAK,aAAa,KAAA,KAAa,MAAM,aAAa,KAAK,UAAU;EAKrE,IAAI,QAAQ,cACV,IAAI;GACF,MAAM,SAAS,MAAM,QAAQ,UAAU,gBAAgB,KAAK,OAAO,KAAK,kBAAkB,KAAK,UAAU;GACzG,KAAK,MAAM,WAAW,QAAQ;IAC5B,IAAI,QAAQ,WAAW,UAAU;IAEjC,IAAI,QAAQ,OAAO,KAAK,qBAAqB;IAM7C,IAAI;IACJ,IAAI;KACF,UAAU,MAAM,QAAQ,UAAU,wBAAwB;MACxD,kBAAkB,QAAQ;MAC1B,UAAU,QAAQ;MAClB,YAAY,QAAQ;MACpB,WAAW,QAAQ;KACrB,CAAC;IACH,QAAQ;KACN;IACF;IACA,IAAI,WAAW,QAAQ,WAAW,YAAY,QAAQ,eAAe,KAAK,YAAY;IACtF,MAAM,QAAQ,aAAa,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;GACpD;EACF,QAAQ,CAER;EAGF,IAAI;GACF,MAAM,QAAQ,UAAU,6BAA6B;IACnD,OAAO,KAAK;IACZ,kBAAkB,KAAK;IACvB,YAAY,KAAK;IACjB,2BAAW,IAAI,KAAK;GACtB,CAAC;EACH,QAAQ,CAER;EACA,IAAI;GACF,MAAM,QAAQ,UAAU,sCAAsC;IAC5D,OAAO,KAAK;IACZ,kBAAkB,KAAK;IACvB,YAAY,KAAK;IACjB,8BAAc,IAAI,KAAK;GACzB,CAAC;EACH,QAAQ,CAER;EACA,IAAI;GACF,MAAM,QAAQ,mBAAmB,IAAI;EACvC,QAAQ,CAER;CACF;AACF"}
|
package/dist/rules/tools.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RequestContext } from '@mastra/core/request-context';
|
|
2
|
+
import type { BoardRegistry } from '../boards/index.js';
|
|
2
3
|
import type { IntegrationTools } from '../integrations/base.js';
|
|
3
4
|
import type { WorkItemsStorage } from '../storage/domains/work-items/base.js';
|
|
4
5
|
import type { FactorySessionSourceLookup } from './binding-context.js';
|
|
@@ -8,5 +9,6 @@ export declare function createFactoryTransitionTools(options: {
|
|
|
8
9
|
storage: WorkItemsStorage;
|
|
9
10
|
transitionService: Pick<FactoryTransitionService, 'transition'>;
|
|
10
11
|
sessions?: FactorySessionSourceLookup;
|
|
12
|
+
boards?: BoardRegistry;
|
|
11
13
|
}): Promise<IntegrationTools>;
|
|
12
14
|
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/rules/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AA8BxE,wBAAsB,4BAA4B,CAAC,OAAO,EAAE;IAC1D,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,iBAAiB,EAAE,IAAI,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;IAChE,QAAQ,CAAC,EAAE,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/rules/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AA8BxE,wBAAsB,4BAA4B,CAAC,OAAO,EAAE;IAC1D,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,iBAAiB,EAAE,IAAI,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;IAChE,QAAQ,CAAC,EAAE,0BAA0B,CAAC;IACtC,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAoF5B"}
|
package/dist/rules/tools.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BOARD_IDENTIFIER_RE } from "./validation.js";
|
|
2
|
-
import { boardForWorkItem } from "../boards/semantics.js";
|
|
2
|
+
import { boardForWorkItem, workItemPhaseSemantics } from "../boards/semantics.js";
|
|
3
3
|
import { FACTORY_TRIAGE_TYPES } from "./types.js";
|
|
4
4
|
import "../boards/index.js";
|
|
5
5
|
import { resolveFactorySessionAddress } from "./binding-context.js";
|
|
@@ -22,7 +22,17 @@ async function createFactoryTransitionTools(options) {
|
|
|
22
22
|
});
|
|
23
23
|
if (!resolution) return {};
|
|
24
24
|
const availableBinding = resolution.binding ?? await options.storage.findActiveRunBinding(resolution.address);
|
|
25
|
-
if (!availableBinding)
|
|
25
|
+
if (!availableBinding) {
|
|
26
|
+
const retired = await options.storage.findRunBindingBySession(resolution.address);
|
|
27
|
+
if (retired && retired.status === "revoked" && options.boards) {
|
|
28
|
+
const item = await options.storage.get({
|
|
29
|
+
orgId: retired.orgId,
|
|
30
|
+
id: retired.workItemId
|
|
31
|
+
});
|
|
32
|
+
if (item && workItemPhaseSemantics(options.boards, item)?.kind === "terminal") return { factory_transition_work_item: createRetiredSessionTool(retired.workItemId, item.stages[0]) };
|
|
33
|
+
}
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
26
36
|
let isTriage = false;
|
|
27
37
|
if (availableBinding.role === "triage") {
|
|
28
38
|
const item = await options.storage.get({
|
|
@@ -76,6 +86,24 @@ async function createFactoryTransitionTools(options) {
|
|
|
76
86
|
}
|
|
77
87
|
}) };
|
|
78
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* A retired session's transition tool: it exists only to fail loudly. The run's
|
|
91
|
+
* binding was revoked when its work item settled at a terminal stage, so there
|
|
92
|
+
* is nothing to transition. Registering it (instead of dropping the tool) stops
|
|
93
|
+
* a resumed model from inventing a false "blocked" state when the affordance it
|
|
94
|
+
* expects has silently vanished.
|
|
95
|
+
*/
|
|
96
|
+
function createRetiredSessionTool(workItemId, stage) {
|
|
97
|
+
return createTool({
|
|
98
|
+
id: "factory_transition_work_item",
|
|
99
|
+
description: "This Factory session has been retired: its work item already reached a terminal stage and the run binding was revoked. No further transitions can be requested from this session.",
|
|
100
|
+
inputSchema: transitionInputSchema,
|
|
101
|
+
requireApproval: false,
|
|
102
|
+
execute: async () => {
|
|
103
|
+
throw new Error(`This Factory session has been retired: work item ${workItemId} reached a terminal stage${stage ? ` (${stage})` : ""} and its run binding was revoked. No transition can be requested from this session.`);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
79
107
|
//#endregion
|
|
80
108
|
export { createFactoryTransitionTools };
|
|
81
109
|
|
package/dist/rules/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","names":[],"sources":["../../src/rules/tools.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { IntegrationTools } from '../integrations/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { FactorySessionSourceLookup } from './binding-context.js';\nimport { resolveFactorySessionAddress } from './binding-context.js';\nimport type { FactoryTransitionService } from './transition-service.js';\nimport { FACTORY_TRIAGE_TYPES } from './types.js';\nimport { BOARD_IDENTIFIER_RE, MAX_BOARD_IDENTIFIER_LENGTH } from './validation.js';\n\nconst MAX_RATIONALE_LENGTH = 1_000;\n\nconst transitionInputSchema = z\n .object({\n stage: z.string().max(MAX_BOARD_IDENTIFIER_LENGTH).regex(BOARD_IDENTIFIER_RE),\n expectedRevision: z.number().int().positive(),\n // Providers strip maxLength from the JSON schema and models can't count characters, so a\n // hard cap invites overshoot-retry loops at the end of every run. Accept and clamp instead.\n rationale: z\n .string()\n .trim()\n .min(1)\n .transform(value =>\n value.length <= MAX_RATIONALE_LENGTH ? value : `${value.slice(0, MAX_RATIONALE_LENGTH - 1)}…`,\n ),\n // Sessions are shared across role rotations, so a non-triage agent sees the triage\n // agent's earlier call (with triageType) in its history and copies the shape. Accept\n // the key here and drop it in execute rather than fail the whole call on it.\n triageType: z.enum(FACTORY_TRIAGE_TYPES).optional(),\n })\n .strict();\n\nconst triageTransitionInputSchema = transitionInputSchema.extend({\n triageType: z.enum(FACTORY_TRIAGE_TYPES),\n});\n\nexport async function createFactoryTransitionTools(options: {\n requestContext: RequestContext;\n storage: WorkItemsStorage;\n transitionService: Pick<FactoryTransitionService, 'transition'>;\n sessions?: FactorySessionSourceLookup;\n}): Promise<IntegrationTools> {\n const resolution = await resolveFactorySessionAddress({\n requestContext: options.requestContext,\n storage: options.storage,\n sessions: options.sessions,\n });\n if (!resolution) return {};\n const availableBinding = resolution.binding ?? (await options.storage.findActiveRunBinding(resolution.address));\n if (!availableBinding) return {};\n let isTriage = false;\n if (availableBinding.role === 'triage') {\n const item = await options.storage.get({ orgId: availableBinding.orgId, id: availableBinding.workItemId });\n if (!item) return {};\n isTriage = boardForWorkItem(item) === 'work';\n }\n\n return {\n factory_transition_work_item: createTool({\n id: 'factory_transition_work_item',\n description: isTriage\n ? 'Report the triage classification and request a governed stage transition for the Factory work item exactly bound to this thread. Only bugs may request Planning autonomously; closure outcomes may request a terminal stage. Feature requests and other non-bug classifications that remain open must stay in their current Intake or Triage stage for maintainer approval.'\n : 'Request a governed stage transition for the Factory work item exactly bound to this thread. Use the current revision from the factory-phase signal and explain why the transition is appropriate.',\n inputSchema: isTriage ? triageTransitionInputSchema : transitionInputSchema,\n requireApproval: true,\n execute: async ({ stage, expectedRevision, rationale, triageType: requestedTriageType }, execution) => {\n const currentResolution = await resolveFactorySessionAddress({\n requestContext: execution.requestContext,\n storage: options.storage,\n sessions: options.sessions,\n });\n const currentAddress = currentResolution?.address ?? null;\n const toolCallId = execution.agent?.toolCallId;\n if (!currentAddress || !toolCallId) {\n throw new Error('Factory transitions require an authenticated bound agent tool call.');\n }\n const binding = await options.storage.findActiveRunBinding(currentAddress);\n // Authority is the work item this session is bound to, not the individual\n // binding row. Handing the next role its turn in an existing session\n // rotates the binding, and tools built for the previous role stay live\n // across that rotation; keying on row identity would strand the run that\n // the rotation exists to start. Re-pointing a session at a different item\n // is the hijack this guards against.\n if (!binding || binding.workItemId !== availableBinding.workItemId) {\n throw new Error('Factory agent binding is unavailable, revoked, or no longer matches this session.');\n }\n const item = await options.storage.get({ orgId: binding.orgId, id: binding.workItemId });\n if (!item) throw new Error('Bound Factory work item not found.');\n const board = boardForWorkItem(item);\n // Only a Work triage binding may classify; other roles can echo the key from history.\n const triageType = board === 'work' && binding.role === 'triage' ? requestedTriageType : undefined;\n\n const result = await options.transitionService.transition({\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n workItemId: binding.workItemId,\n board,\n stage,\n expectedRevision,\n actor: { type: 'agent', bindingId: binding.id, role: binding.role },\n ingress: { type: 'agent', identity: `${binding.id}:${toolCallId}` },\n cause: rationale,\n ...(triageType ? { triageType } : {}),\n });\n\n return result;\n },\n }),\n };\n}\n"],"mappings":";;;;;;;;AAaA,MAAM,uBAAuB;AAE7B,MAAM,wBAAwB,EAC3B,OAAO;CACN,OAAO,EAAE,OAAO,CAAC,CAAC,IAAA,GAA+B,CAAC,CAAC,MAAM,mBAAmB;CAC5E,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CAG5C,WAAW,EACR,OAAO,CAAC,CACR,KAAK,CAAC,CACN,IAAI,CAAC,CAAC,CACN,WAAU,UACT,MAAM,UAAU,uBAAuB,QAAQ,GAAG,MAAM,MAAM,GAAG,uBAAuB,CAAC,EAAE,EAC7F;CAIF,YAAY,EAAE,KAAK,oBAAoB,CAAC,CAAC,SAAS;AACpD,CAAC,CAAC,CACD,OAAO;AAEV,MAAM,8BAA8B,sBAAsB,OAAO,EAC/D,YAAY,EAAE,KAAK,oBAAoB,EACzC,CAAC;AAED,eAAsB,6BAA6B,SAKrB;CAC5B,MAAM,aAAa,MAAM,6BAA6B;EACpD,gBAAgB,QAAQ;EACxB,SAAS,QAAQ;EACjB,UAAU,QAAQ;CACpB,CAAC;CACD,IAAI,CAAC,YAAY,OAAO,CAAC;CACzB,MAAM,mBAAmB,WAAW,WAAY,MAAM,QAAQ,QAAQ,qBAAqB,WAAW,OAAO;CAC7G,IAAI,CAAC,kBAAkB,OAAO,CAAC;CAC/B,IAAI,WAAW;CACf,IAAI,iBAAiB,SAAS,UAAU;EACtC,MAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;GAAE,OAAO,iBAAiB;GAAO,IAAI,iBAAiB;EAAW,CAAC;EACzG,IAAI,CAAC,MAAM,OAAO,CAAC;EACnB,WAAW,iBAAiB,IAAI,MAAM;CACxC;CAEA,OAAO,EACL,8BAA8B,WAAW;EACvC,IAAI;EACJ,aAAa,WACT,gXACA;EACJ,aAAa,WAAW,8BAA8B;EACtD,iBAAiB;EACjB,SAAS,OAAO,EAAE,OAAO,kBAAkB,WAAW,YAAY,uBAAuB,cAAc;GAMrG,MAAM,kBAAiB,MALS,6BAA6B;IAC3D,gBAAgB,UAAU;IAC1B,SAAS,QAAQ;IACjB,UAAU,QAAQ;GACpB,CAAC,EAAA,EACyC,WAAW;GACrD,MAAM,aAAa,UAAU,OAAO;GACpC,IAAI,CAAC,kBAAkB,CAAC,YACtB,MAAM,IAAI,MAAM,qEAAqE;GAEvF,MAAM,UAAU,MAAM,QAAQ,QAAQ,qBAAqB,cAAc;GAOzE,IAAI,CAAC,WAAW,QAAQ,eAAe,iBAAiB,YACtD,MAAM,IAAI,MAAM,mFAAmF;GAErG,MAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;IAAE,OAAO,QAAQ;IAAO,IAAI,QAAQ;GAAW,CAAC;GACvF,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,oCAAoC;GAC/D,MAAM,QAAQ,iBAAiB,IAAI;GAEnC,MAAM,aAAa,UAAU,UAAU,QAAQ,SAAS,WAAW,sBAAsB,KAAA;GAezF,OAAO,MAbc,QAAQ,kBAAkB,WAAW;IACxD,OAAO,QAAQ;IACf,kBAAkB,QAAQ;IAC1B,YAAY,QAAQ;IACpB;IACA;IACA;IACA,OAAO;KAAE,MAAM;KAAS,WAAW,QAAQ;KAAI,MAAM,QAAQ;IAAK;IAClE,SAAS;KAAE,MAAM;KAAS,UAAU,GAAG,QAAQ,GAAG,GAAG;IAAa;IAClE,OAAO;IACP,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;GACrC,CAAC;EAGH;CACF,CAAC,EACH;AACF"}
|
|
1
|
+
{"version":3,"file":"tools.js","names":[],"sources":["../../src/rules/tools.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { boardForWorkItem, workItemPhaseSemantics } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { IntegrationTools } from '../integrations/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { FactorySessionSourceLookup } from './binding-context.js';\nimport { resolveFactorySessionAddress } from './binding-context.js';\nimport type { FactoryTransitionService } from './transition-service.js';\nimport { FACTORY_TRIAGE_TYPES } from './types.js';\nimport { BOARD_IDENTIFIER_RE, MAX_BOARD_IDENTIFIER_LENGTH } from './validation.js';\n\nconst MAX_RATIONALE_LENGTH = 1_000;\n\nconst transitionInputSchema = z\n .object({\n stage: z.string().max(MAX_BOARD_IDENTIFIER_LENGTH).regex(BOARD_IDENTIFIER_RE),\n expectedRevision: z.number().int().positive(),\n // Providers strip maxLength from the JSON schema and models can't count characters, so a\n // hard cap invites overshoot-retry loops at the end of every run. Accept and clamp instead.\n rationale: z\n .string()\n .trim()\n .min(1)\n .transform(value =>\n value.length <= MAX_RATIONALE_LENGTH ? value : `${value.slice(0, MAX_RATIONALE_LENGTH - 1)}…`,\n ),\n // Sessions are shared across role rotations, so a non-triage agent sees the triage\n // agent's earlier call (with triageType) in its history and copies the shape. Accept\n // the key here and drop it in execute rather than fail the whole call on it.\n triageType: z.enum(FACTORY_TRIAGE_TYPES).optional(),\n })\n .strict();\n\nconst triageTransitionInputSchema = transitionInputSchema.extend({\n triageType: z.enum(FACTORY_TRIAGE_TYPES),\n});\n\nexport async function createFactoryTransitionTools(options: {\n requestContext: RequestContext;\n storage: WorkItemsStorage;\n transitionService: Pick<FactoryTransitionService, 'transition'>;\n sessions?: FactorySessionSourceLookup;\n boards?: BoardRegistry;\n}): Promise<IntegrationTools> {\n const resolution = await resolveFactorySessionAddress({\n requestContext: options.requestContext,\n storage: options.storage,\n sessions: options.sessions,\n });\n if (!resolution) return {};\n const availableBinding = resolution.binding ?? (await options.storage.findActiveRunBinding(resolution.address));\n if (!availableBinding) {\n // No live binding for this session. A resumed session whose binding was\n // revoked when its work item reached a terminal stage was retired out from\n // under the model: rather than silently drop the tool — which leaves the\n // resumed run to rationalize a false blocked state — surface a tool that\n // fails with the concrete reason. Threads that were never bound (or whose\n // binding was rotated to a peer role, leaving the item still in flight) get\n // no tool as before.\n const retired = await options.storage.findRunBindingBySession(resolution.address);\n if (retired && retired.status === 'revoked' && options.boards) {\n const item = await options.storage.get({ orgId: retired.orgId, id: retired.workItemId });\n if (item && workItemPhaseSemantics(options.boards, item)?.kind === 'terminal') {\n return { factory_transition_work_item: createRetiredSessionTool(retired.workItemId, item.stages[0]) };\n }\n }\n return {};\n }\n let isTriage = false;\n if (availableBinding.role === 'triage') {\n const item = await options.storage.get({ orgId: availableBinding.orgId, id: availableBinding.workItemId });\n if (!item) return {};\n isTriage = boardForWorkItem(item) === 'work';\n }\n\n return {\n factory_transition_work_item: createTool({\n id: 'factory_transition_work_item',\n description: isTriage\n ? 'Report the triage classification and request a governed stage transition for the Factory work item exactly bound to this thread. Only bugs may request Planning autonomously; closure outcomes may request a terminal stage. Feature requests and other non-bug classifications that remain open must stay in their current Intake or Triage stage for maintainer approval.'\n : 'Request a governed stage transition for the Factory work item exactly bound to this thread. Use the current revision from the factory-phase signal and explain why the transition is appropriate.',\n inputSchema: isTriage ? triageTransitionInputSchema : transitionInputSchema,\n requireApproval: true,\n execute: async ({ stage, expectedRevision, rationale, triageType: requestedTriageType }, execution) => {\n const currentResolution = await resolveFactorySessionAddress({\n requestContext: execution.requestContext,\n storage: options.storage,\n sessions: options.sessions,\n });\n const currentAddress = currentResolution?.address ?? null;\n const toolCallId = execution.agent?.toolCallId;\n if (!currentAddress || !toolCallId) {\n throw new Error('Factory transitions require an authenticated bound agent tool call.');\n }\n const binding = await options.storage.findActiveRunBinding(currentAddress);\n // Authority is the work item this session is bound to, not the individual\n // binding row. Handing the next role its turn in an existing session\n // rotates the binding, and tools built for the previous role stay live\n // across that rotation; keying on row identity would strand the run that\n // the rotation exists to start. Re-pointing a session at a different item\n // is the hijack this guards against.\n if (!binding || binding.workItemId !== availableBinding.workItemId) {\n throw new Error('Factory agent binding is unavailable, revoked, or no longer matches this session.');\n }\n const item = await options.storage.get({ orgId: binding.orgId, id: binding.workItemId });\n if (!item) throw new Error('Bound Factory work item not found.');\n const board = boardForWorkItem(item);\n // Only a Work triage binding may classify; other roles can echo the key from history.\n const triageType = board === 'work' && binding.role === 'triage' ? requestedTriageType : undefined;\n\n const result = await options.transitionService.transition({\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n workItemId: binding.workItemId,\n board,\n stage,\n expectedRevision,\n actor: { type: 'agent', bindingId: binding.id, role: binding.role },\n ingress: { type: 'agent', identity: `${binding.id}:${toolCallId}` },\n cause: rationale,\n ...(triageType ? { triageType } : {}),\n });\n\n return result;\n },\n }),\n };\n}\n\n/**\n * A retired session's transition tool: it exists only to fail loudly. The run's\n * binding was revoked when its work item settled at a terminal stage, so there\n * is nothing to transition. Registering it (instead of dropping the tool) stops\n * a resumed model from inventing a false \"blocked\" state when the affordance it\n * expects has silently vanished.\n */\nfunction createRetiredSessionTool(workItemId: string, stage: string | undefined): IntegrationTools[string] {\n return createTool({\n id: 'factory_transition_work_item',\n description:\n 'This Factory session has been retired: its work item already reached a terminal stage and the run binding was revoked. No further transitions can be requested from this session.',\n inputSchema: transitionInputSchema,\n requireApproval: false,\n execute: async () => {\n throw new Error(\n `This Factory session has been retired: work item ${workItemId} reached a terminal stage${\n stage ? ` (${stage})` : ''\n } and its run binding was revoked. No transition can be requested from this session.`,\n );\n },\n });\n}\n"],"mappings":"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"}
|
|
@@ -49,6 +49,9 @@ export interface FactoryTransitionServiceOptions {
|
|
|
49
49
|
workItemId: string;
|
|
50
50
|
stage: FactoryRuleStage;
|
|
51
51
|
revision: number;
|
|
52
|
+
/** The actor that committed this terminal transition. Lets cleanup leave
|
|
53
|
+
* the seat that drove its own transition (an agent tool call) untouched. */
|
|
54
|
+
actor: FactoryRuleActor;
|
|
52
55
|
}) => Promise<void> | void;
|
|
53
56
|
/** Upper bound on how long a committed transition waits for
|
|
54
57
|
* `onTerminalStage` before returning (default 30s). The cleanup continues
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transition-service.d.ts","sourceRoot":"","sources":["../../src/rules/transition-service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC7G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAE3F,OAAO,KAAK,EAEV,gBAAgB,EAEhB,sBAAsB,EAEtB,gBAAgB,EAChB,iBAAiB,EAEjB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAsBpB,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,gBAAgB,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,gBAAgB,CAAC;IACxB,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,sEAAsE;IACtE,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjH,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAChD,iHAAiH;IACjH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qHAAqH;IACrH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAED,MAAM,WAAW,+BAA+B;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,yHAAyH;IACzH,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,gBAAgB,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"transition-service.d.ts","sourceRoot":"","sources":["../../src/rules/transition-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -357,7 +357,8 @@ var FactoryTransitionService = class {
|
|
|
357
357
|
const result = committed.result;
|
|
358
358
|
if (this.#onAccepted && options.accept && committed.status === "committed" && result.status === "accepted" && committed.item?.acceptedAt) {
|
|
359
359
|
const item = committed.item;
|
|
360
|
-
|
|
360
|
+
const onAccepted = this.#onAccepted;
|
|
361
|
+
Promise.resolve().then(() => onAccepted({
|
|
361
362
|
orgId: request.orgId,
|
|
362
363
|
factoryProjectId: request.factoryProjectId,
|
|
363
364
|
workItemId: request.workItemId,
|
|
@@ -374,7 +375,8 @@ var FactoryTransitionService = class {
|
|
|
374
375
|
factoryProjectId: request.factoryProjectId,
|
|
375
376
|
workItemId: request.workItemId,
|
|
376
377
|
stage: result.stage,
|
|
377
|
-
revision: result.revision
|
|
378
|
+
revision: result.revision,
|
|
379
|
+
actor: request.actor
|
|
378
380
|
}));
|
|
379
381
|
cleanup.catch(() => {});
|
|
380
382
|
await Promise.race([cleanup, new Promise((resolve) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transition-service.js","names":["#configVersion","#boards","#storage","#timeoutMs","#onTerminalStage","#terminalCleanupTimeoutMs","#onAccepted","#autoApprovePlans","#audit","#commitRejection","#recordTransition","#evaluateAndCommit","#commit"],"sources":["../../src/rules/transition-service.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { createBoardRegistry } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport { boardTransitionPolicyResultSchema, immutablePolicySnapshot } from '../boards/transition-policy.js';\nimport type { AuditActorProfileInput, AuditActorType, AuditContext } from '../storage/domains/audit/base.js';\nimport type { AuditRecorder } from '../storage/domains/audit/domain.js';\nimport { isAgentActor } from '../storage/domains/work-items/base.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport { resolveFactoryStageRules } from './resolve.js';\nimport type {\n FactoryCommitDecision,\n FactoryRuleActor,\n FactoryRuleBoard,\n FactoryRuleCausalEntry,\n FactoryRuleRejectionCode,\n FactoryRuleStage,\n FactoryTriageType,\n FactoryStageRuleContext,\n FactoryTransitionResult,\n} from './types.js';\nimport {\n externallyAuthoredWorkItem,\n factoryRuleSourceForWorkItem,\n isFactoryRuleStage,\n workItemSource,\n} from './types.js';\nimport {\n MAX_FACTORY_RULE_CAUSAL_DEPTH,\n assertFactoryDecisionTarget,\n validateFactoryRuleDecision,\n validateFactoryRuleDecisions,\n} from './validation.js';\n\nconst RULE_TIMEOUT_MS = 5_000;\nconst MAX_REJECTION_REASON = 512;\n/** Longest a committed transition waits for terminal resource cleanup. Cleanup\n * reattaches remote sandboxes, so a hung provider call must not leave the\n * already-committed transition request pending; past this bound the cleanup\n * keeps running in the background as pure best-effort. */\nconst TERMINAL_CLEANUP_TIMEOUT_MS = 30_000;\n\nexport interface FactoryTransitionRequest {\n orgId: string;\n factoryProjectId: string;\n workItemId: string;\n /** Installed board id; the service rejects boards that are not installed. */\n board: string;\n stage: FactoryRuleStage;\n expectedRevision: number;\n actor: FactoryRuleActor;\n actorProfile?: AuditActorProfileInput;\n /** Where a browser request came from; rules and agents carry none. */\n context?: AuditContext;\n ingress: { type: 'human' | 'agent' | 'toolResult' | 'github' | 'rule'; identity: string; transitionId?: string };\n cause: string;\n causalChain?: readonly FactoryRuleCausalEntry[];\n /** Internal materialization path: evaluate only the destination onEnter leaf even when already at that stage. */\n initialEntry?: boolean;\n /** Re-runs the stage's entry rules when the item already holds that stage, to restart work the entry invalidated. */\n reenter?: boolean;\n /** Structured verdict required from a bound triage-agent terminal request. */\n triageType?: FactoryTriageType;\n}\n\nexport interface FactoryTransitionServiceOptions {\n configVersion: string;\n storage: WorkItemsStorage;\n boards?: BoardRegistry;\n /** Every commit, accepted or rejected, lands here as `stage_moved` / `transition_rejected` under the request's actor. */\n audit?: AuditRecorder;\n timeoutMs?: number;\n /**\n * Called after a transition commits into a phase the board declares\n * terminal — the point where the item's sessions stop receiving runs, so\n * resources they hold (e.g. sandboxes) can be released for reuse. Awaited,\n * but failures are swallowed: releasing resources must never break or roll\n * back the committed transition.\n */\n onTerminalStage?: (args: {\n orgId: string;\n factoryProjectId: string;\n workItemId: string;\n stage: FactoryRuleStage;\n revision: number;\n }) => Promise<void> | void;\n /** Upper bound on how long a committed transition waits for\n * `onTerminalStage` before returning (default 30s). The cleanup continues\n * in the background past the bound. */\n terminalCleanupTimeoutMs?: number;\n /**\n * Called after a transition first records a person's acceptance of a\n * non-bug item (see `WorkItemRow.acceptedAt`). Fire-and-forget: failures\n * are swallowed, the committed transition never depends on it.\n */\n onAccepted?: (args: {\n orgId: string;\n factoryProjectId: string;\n workItemId: string;\n item: WorkItemRow;\n }) => Promise<void> | void;\n /**\n * Resolves whether a project auto-approves produced plans. Mirrors the\n * dispatcher's resolver so the two share a single authoritative predicate\n * (`plansPreapprovedAt` on the item, or this per-project setting). Unset means\n * off: a plan nobody armed for auto-advance is a plan a person must review.\n */\n autoApprovePlans?: (tenant: { orgId: string; factoryProjectId: string }) => Promise<boolean>;\n}\n\nfunction rejection(\n transitionId: string,\n itemId: string,\n code: FactoryRuleRejectionCode,\n reason: string,\n): FactoryTransitionResult {\n return { status: 'rejected', transitionId, itemId, code, reason: reason.slice(0, MAX_REJECTION_REASON) };\n}\n\nfunction actorId(actor: FactoryRuleActor): string {\n switch (actor.type) {\n case 'human':\n case 'system':\n return actor.id;\n case 'agent':\n return `agent:${actor.bindingId}`;\n case 'github':\n return `github:${actor.login}`;\n }\n}\n\n// The dispatcher executes an agent-approved decision as a human actor so its consent carries; the trail still names the agent.\nexport function auditActorOf(actor: FactoryRuleActor): { actorId: string; actorType: AuditActorType } {\n const id = actorId(actor);\n switch (actor.type) {\n case 'github':\n return { actorId: id, actorType: 'human' };\n case 'human':\n return { actorId: id, actorType: isAgentActor(id) ? 'agent' : 'human' };\n default:\n return { actorId: id, actorType: actor.type };\n }\n}\n\nexport function currentStage(stages: readonly string[]): FactoryRuleStage | undefined {\n if (stages.length !== 1) return undefined;\n const stage = stages[0];\n return isFactoryRuleStage(stage) ? stage : undefined;\n}\n\ninterface TransitionConsentOptions {\n autonomy?: 'arm' | 'disarm';\n consentedBy?: string;\n accept?: boolean;\n triageType?: FactoryTriageType;\n}\n\n// Entering a resting lane disarms whoever rests it; only a person's move into a working lane arms.\nfunction transitionConsent(working: boolean, humanMove: boolean): 'arm' | 'disarm' | undefined {\n if (!working) return 'disarm';\n return humanMove ? 'arm' : undefined;\n}\n\n// An event arriving as data (GitHub, sweeps) never pre-approves the runs its transition queues.\nfunction bearsConsent(actor: FactoryRuleActor): boolean {\n return actor.type === 'human' || actor.type === 'agent';\n}\n\n// Rides the transition's own revision-checked commit, so a stale or rejected commit flips nothing.\nfunction consentEffect(\n request: FactoryTransitionRequest,\n working: boolean,\n humanMove: boolean,\n): TransitionConsentOptions {\n const autonomy = transitionConsent(working, humanMove);\n return bearsConsent(request.actor) ? { autonomy, consentedBy: actorId(request.actor) } : { autonomy };\n}\n\ntype RunStartDecision = Extract<FactoryCommitDecision, { type: 'invokeSkill' | 'sendMessage' }>;\n\nfunction startsRun(decision: FactoryCommitDecision): decision is RunStartDecision {\n return decision.type === 'invokeSkill' || (decision.type === 'sendMessage' && decision.prepareBinding === true);\n}\n\n// Answering a recorded run start, or the role's own mid-run agent, with a run would start a second one.\nfunction runAlreadyUnderway(request: FactoryTransitionRequest, decision: RunStartDecision): boolean {\n if (request.cause === 'run_start') return true;\n return request.actor.type === 'agent' && request.actor.role === decision.role;\n}\n\nfunction stageTransitionMessage(fromStage: FactoryRuleStage, toStage: FactoryRuleStage): string {\n return `This work was moved from the ${fromStage} stage to the ${toStage} stage.`;\n}\n\nfunction isTriageAgent(actor: FactoryRuleActor): actor is Extract<FactoryRuleActor, { type: 'agent' }> {\n return actor.type === 'agent' && actor.role === 'triage';\n}\n\nfunction isHumanTransition(request: FactoryTransitionRequest): boolean {\n return request.actor.type === 'human' && request.ingress.type === 'human';\n}\n\nfunction ruleFailure(error: unknown): { code: FactoryRuleRejectionCode; reason: string } {\n return {\n code: 'rule_error',\n reason: error instanceof Error ? `Factory rule failed: ${error.message}` : 'Factory rule failed.',\n };\n}\n\nasync function withRuleTimeout<T>(operation: Promise<T>, timeoutMs: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error('FACTORY_RULE_TIMEOUT')), timeoutMs);\n });\n try {\n return await Promise.race([operation, timeout]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\nexport class FactoryTransitionService {\n readonly #configVersion: string;\n readonly #boards: BoardRegistry;\n readonly #storage: WorkItemsStorage;\n readonly #timeoutMs: number;\n readonly #onTerminalStage: FactoryTransitionServiceOptions['onTerminalStage'];\n readonly #terminalCleanupTimeoutMs: number;\n readonly #onAccepted: FactoryTransitionServiceOptions['onAccepted'];\n readonly #autoApprovePlans: FactoryTransitionServiceOptions['autoApprovePlans'];\n readonly #audit: AuditRecorder | undefined;\n\n constructor(options: FactoryTransitionServiceOptions) {\n this.#configVersion = options.configVersion;\n this.#boards = options.boards ?? createBoardRegistry();\n this.#storage = options.storage;\n this.#audit = options.audit;\n this.#timeoutMs = options.timeoutMs ?? RULE_TIMEOUT_MS;\n this.#onTerminalStage = options.onTerminalStage;\n this.#onAccepted = options.onAccepted;\n this.#autoApprovePlans = options.autoApprovePlans;\n this.#terminalCleanupTimeoutMs = options.terminalCleanupTimeoutMs ?? TERMINAL_CLEANUP_TIMEOUT_MS;\n }\n\n get configVersion(): string {\n return this.#configVersion;\n }\n\n async transition(request: FactoryTransitionRequest): Promise<FactoryTransitionResult> {\n const replay = await this.#storage.getTransitionResultByIngress(\n request.orgId,\n request.factoryProjectId,\n request.ingress.identity,\n );\n if (replay) return replay as unknown as FactoryTransitionResult;\n\n const transitionId = request.ingress.transitionId ?? randomUUID();\n const item = await this.#storage.get({ orgId: request.orgId, id: request.workItemId });\n if (!item) {\n const rejection = await this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n 'Work item not found.',\n );\n await this.#recordTransition(request, undefined, rejection);\n return rejection;\n }\n const result = await this.#evaluateAndCommit(request, transitionId, item);\n await this.#recordTransition(request, item, result);\n return result;\n }\n\n /** A rejection can outlive its work item: the row still names the id the caller asked for. */\n async #recordTransition(\n request: FactoryTransitionRequest,\n item: WorkItemRow | undefined,\n result: FactoryTransitionResult,\n ): Promise<void> {\n if (!this.#audit) return;\n const from = item ? currentStage(item.stages) : undefined;\n if (result.status === 'accepted' && result.stage === from && !request.reenter) return;\n const outcome =\n result.status === 'accepted'\n ? { action: 'factory.work_item.stage_moved' as const, to: result.stage, revision: result.revision }\n : {\n action: 'factory.work_item.transition_rejected' as const,\n to: request.stage,\n code: result.code,\n reason: result.reason,\n };\n const { action, ...detail } = outcome;\n await this.#audit\n .record({\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n ...auditActorOf(request.actor),\n actorProfile: request.actorProfile,\n ...(request.context ? { context: request.context } : {}),\n action,\n idempotencyKey: result.transitionId,\n targets: [{ type: 'work_item', id: item?.id ?? request.workItemId, ...(item ? { name: item.title } : {}) }],\n metadata: {\n transitionId: result.transitionId,\n ingressType: request.ingress.type,\n cause: request.cause,\n configVersion: this.#configVersion,\n ...(from ? { from } : {}),\n ...(request.reenter ? { reenter: true } : {}),\n ...detail,\n },\n })\n .catch(error => {\n console.warn(`[factory] audit failed for transition ${result.transitionId}:`, error);\n });\n }\n\n async #evaluateAndCommit(\n request: FactoryTransitionRequest,\n transitionId: string,\n item: WorkItemRow,\n ): Promise<FactoryTransitionResult> {\n if (request.causalChain && request.causalChain.length > MAX_FACTORY_RULE_CAUSAL_DEPTH) {\n return this.#commitRejection(\n request,\n transitionId,\n 'causal_depth_exceeded',\n 'Factory rule causal depth exceeded.',\n );\n }\n const itemSource = workItemSource(item.externalSource);\n const source = factoryRuleSourceForWorkItem(itemSource);\n const legacyBoard = source === 'pullRequest' ? 'review' : 'work';\n if (item.board === null && !this.#boards.has(legacyBoard)) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n 'This legacy work item has no assigned board. Assign an installed board and phase through the work-item PATCH endpoint before transitioning it.',\n );\n }\n const itemBoard = item.board ?? legacyBoard;\n if (request.board !== itemBoard) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n `The work item belongs to board \"${itemBoard}\", not \"${request.board}\".`,\n );\n }\n if ((itemBoard === 'review' && source !== 'pullRequest') || (itemBoard === 'work' && source === 'pullRequest')) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n 'The work item does not belong to the requested board.',\n );\n }\n const board = this.#boards.get(request.board);\n if (!board) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n `Board \"${request.board}\" is not installed.`,\n );\n }\n const fromStage = item.stages.length === 1 ? item.stages[0] : undefined;\n if (!fromStage || !Object.prototype.hasOwnProperty.call(board.phases, fromStage)) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n 'The work item does not have one canonical phase on the requested board.',\n );\n }\n if (\n !Object.prototype.hasOwnProperty.call(board.phases, request.stage) ||\n !board.allowsTransition(fromStage, request.stage)\n ) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n `The ${board.title} board does not allow moving from ${fromStage} to ${request.stage}.`,\n );\n }\n\n // The coordinator's own self-move at run start would otherwise inject a second run's kickoff.\n const humanMove = request.actor.type === 'human' && fromStage !== request.stage && request.cause !== 'run_start';\n // The board, not the phase name, says whether a seat is engaged on either side of this move.\n const entersWorking = board.isWorking(request.stage);\n const seatRole = board.roleForPhase(request.stage);\n\n const contextBase = {\n tenant: { orgId: request.orgId, projectId: request.factoryProjectId },\n actor: request.actor,\n ingress: { type: request.ingress.type, id: request.ingress.identity },\n cause: request.cause,\n causalChain: request.causalChain ?? [],\n configVersion: this.#configVersion,\n item: {\n id: item.id,\n source: itemSource,\n sourceKey: item.externalSource\n ? `${item.externalSource.integrationId}:${item.externalSource.type}:${item.externalSource.externalId}`\n : null,\n parentWorkItemId: item.parentWorkItemId,\n title: item.title,\n url: item.externalSource?.url ?? null,\n stages: [...item.stages],\n acceptedAt: item.acceptedAt,\n metadata: item.metadata,\n },\n board: request.board,\n itemRevision: item.revision,\n source,\n fromStage,\n toStage: request.stage,\n } satisfies Omit<FactoryStageRuleContext, 'stage'>;\n\n let evaluation:\n | { outcome: 'accepted'; decisions: Record<string, unknown>[]; intents: TransitionConsentOptions }\n | { outcome: 'rejected'; code: string; reason: string };\n try {\n evaluation = await withRuleTimeout(\n (async () => {\n // Single authoritative plan-approval predicate, shared with the dispatcher's\n // `#plansAreAutoApproved`: a per-item preapproval, or the project setting.\n // Resolved inside the timed block so a resolver rejection surfaces as a\n // committed rule_error and a slow lookup is bounded by RULE_TIMEOUT_MS.\n const plansAutoApproved =\n item.plansPreapprovedAt != null ||\n (this.#autoApprovePlans\n ? await this.#autoApprovePlans({ orgId: request.orgId, factoryProjectId: request.factoryProjectId })\n : false);\n const policy = boardTransitionPolicyResultSchema.parse(\n await board.transitionPolicy?.(\n immutablePolicySnapshot({\n ...contextBase,\n item: { ...contextBase.item, triageType: item.triageType },\n initialEntry: request.initialEntry ?? false,\n reenter: request.reenter ?? false,\n isHumanTransition: isHumanTransition(request),\n plansAutoApproved,\n requestedTriageType: request.triageType,\n }),\n ),\n );\n if (policy?.type === 'reject') {\n return { outcome: 'rejected' as const, code: policy.code, reason: policy.reason };\n }\n if (\n policy?.triageType !== undefined &&\n (!isTriageAgent(request.actor) ||\n policy.triageType !== request.triageType ||\n (item.triageType !== null && item.triageType !== policy.triageType))\n ) {\n throw new Error('Board policy requested an unauthorized classification.');\n }\n if (policy?.accept && !isHumanTransition(request)) {\n throw new Error('Board policy requested unauthorized acceptance.');\n }\n // External content can steer a bound agent; board allowance cannot bypass this guard.\n if (\n request.actor.type === 'agent' &&\n !board.isWorking(fromStage) &&\n entersWorking &&\n externallyAuthoredWorkItem(item)\n ) {\n return {\n outcome: 'rejected' as const,\n code: 'approval_required',\n reason:\n 'This card comes from outside the write-access circle; a person must resume it from the Factory board.',\n };\n }\n const decisions: FactoryCommitDecision[] = [];\n for (const rule of resolveFactoryStageRules(this.#boards, {\n board: request.board,\n source,\n fromStage,\n toStage: request.stage,\n initialEntry: request.initialEntry,\n reenter: request.reenter,\n })) {\n const context: FactoryStageRuleContext = Object.freeze({\n ...contextBase,\n stage: rule.phase === 'exit' ? fromStage : request.stage,\n });\n const raw = await rule.handler(context);\n if (raw === undefined) continue;\n const decision = validateFactoryRuleDecision(raw, context.causalChain.length);\n if (decision.type === 'reject') {\n return { outcome: 'rejected' as const, code: decision.code, reason: decision.reason };\n }\n assertFactoryDecisionTarget(decision, this.#boards, itemBoard);\n if (startsRun(decision) && runAlreadyUnderway(request, decision)) continue;\n decisions.push(decision);\n }\n const validated = validateFactoryRuleDecisions(decisions);\n if (humanMove) {\n const message = stageTransitionMessage(fromStage, request.stage);\n const skill = validated.find(decision => decision.type === 'invokeSkill');\n if (skill) {\n skill.precedingMessage = message;\n } else {\n validated.unshift({\n type: 'sendMessage',\n idempotencyKey: `factory-stage:${transitionId}`,\n message,\n priority: 'urgent',\n idleBehavior: 'wake',\n // Parking a card says stop: no seat is right by construction, so\n // the notice goes to whichever session is live — or nobody.\n ...(entersWorking && seatRole !== undefined ? { role: seatRole, prepareBinding: true } : {}),\n });\n }\n }\n return {\n outcome: 'accepted' as const,\n intents: { triageType: policy?.triageType, accept: policy?.accept === true && !item.acceptedAt },\n decisions: validateFactoryRuleDecisions(validated) as unknown as Record<string, unknown>[],\n };\n })(),\n this.#timeoutMs,\n );\n } catch (error) {\n const failed =\n error instanceof Error && error.message === 'FACTORY_RULE_TIMEOUT'\n ? { code: 'timeout' as const, reason: 'Factory rule evaluation timed out.' }\n : ruleFailure(error);\n evaluation = { outcome: 'rejected', ...failed };\n }\n return this.#commit(\n request,\n transitionId,\n evaluation,\n evaluation.outcome === 'accepted'\n ? { ...consentEffect(request, entersWorking, humanMove), ...evaluation.intents }\n : {},\n );\n }\n\n async #commitRejection(\n request: FactoryTransitionRequest,\n transitionId: string,\n code: FactoryRuleRejectionCode,\n reason: string,\n ): Promise<FactoryTransitionResult> {\n return this.#commit(request, transitionId, { outcome: 'rejected', code, reason });\n }\n\n async #commit(\n request: FactoryTransitionRequest,\n transitionId: string,\n evaluation:\n | { outcome: 'accepted'; decisions: Record<string, unknown>[] }\n | { outcome: 'rejected'; code: string; reason: string },\n options: TransitionConsentOptions = {},\n ): Promise<FactoryTransitionResult> {\n const committed = await this.#storage.commitTransition({\n autonomy: options.autonomy,\n consentedBy: options.consentedBy,\n ...(options.accept ? { accept: true } : {}),\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n workItemId: request.workItemId,\n expectedRevision: request.expectedRevision,\n destinationStage: request.stage,\n actorId: actorId(request.actor),\n ingress: { identity: request.ingress.identity, triggerType: request.ingress.type, transitionId },\n configVersion: this.#configVersion,\n causalChain: [...(request.causalChain ?? [])],\n evaluation,\n ...(options.triageType ? { triageType: options.triageType } : {}),\n });\n if (committed.status === 'missing') {\n return rejection(transitionId, request.workItemId, 'invalid_transition', 'Work item not found.');\n }\n const result = committed.result as unknown as FactoryTransitionResult;\n if (\n this.#onAccepted &&\n options.accept &&\n committed.status === 'committed' &&\n result.status === 'accepted' &&\n committed.item?.acceptedAt\n ) {\n const item = committed.item;\n void Promise.resolve(\n this.#onAccepted({\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n workItemId: request.workItemId,\n item,\n }),\n ).catch(error => {\n console.warn(`[factory] acceptance hook failed for work item ${request.workItemId}:`, error);\n });\n }\n // Only an installed board's declaration releases resources; an unknown board or phase never does.\n if (\n this.#onTerminalStage &&\n result.status === 'accepted' &&\n this.#boards.get(request.board)?.isTerminal(result.stage) === true\n ) {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n const cleanup = Promise.resolve(\n this.#onTerminalStage({\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n workItemId: request.workItemId,\n stage: result.stage,\n revision: result.revision,\n }),\n );\n // A late rejection after the timeout wins the race must not surface\n // as an unhandled rejection.\n cleanup.catch(() => {});\n await Promise.race([\n cleanup,\n new Promise<void>(resolve => {\n timer = setTimeout(resolve, this.#terminalCleanupTimeoutMs);\n }),\n ]);\n } catch {\n // Resource release is best-effort — never fail a committed transition.\n } finally {\n clearTimeout(timer);\n }\n }\n return result;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transition-service.js","names":["#configVersion","#boards","#storage","#timeoutMs","#onTerminalStage","#terminalCleanupTimeoutMs","#onAccepted","#autoApprovePlans","#audit","#commitRejection","#recordTransition","#evaluateAndCommit","#commit"],"sources":["../../src/rules/transition-service.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { createBoardRegistry } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport { boardTransitionPolicyResultSchema, immutablePolicySnapshot } from '../boards/transition-policy.js';\nimport type { AuditActorProfileInput, AuditActorType, AuditContext } from '../storage/domains/audit/base.js';\nimport type { AuditRecorder } from '../storage/domains/audit/domain.js';\nimport { isAgentActor } from '../storage/domains/work-items/base.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport { resolveFactoryStageRules } from './resolve.js';\nimport type {\n FactoryCommitDecision,\n FactoryRuleActor,\n FactoryRuleBoard,\n FactoryRuleCausalEntry,\n FactoryRuleRejectionCode,\n FactoryRuleStage,\n FactoryTriageType,\n FactoryStageRuleContext,\n FactoryTransitionResult,\n} from './types.js';\nimport {\n externallyAuthoredWorkItem,\n factoryRuleSourceForWorkItem,\n isFactoryRuleStage,\n workItemSource,\n} from './types.js';\nimport {\n MAX_FACTORY_RULE_CAUSAL_DEPTH,\n assertFactoryDecisionTarget,\n validateFactoryRuleDecision,\n validateFactoryRuleDecisions,\n} from './validation.js';\n\nconst RULE_TIMEOUT_MS = 5_000;\nconst MAX_REJECTION_REASON = 512;\n/** Longest a committed transition waits for terminal resource cleanup. Cleanup\n * reattaches remote sandboxes, so a hung provider call must not leave the\n * already-committed transition request pending; past this bound the cleanup\n * keeps running in the background as pure best-effort. */\nconst TERMINAL_CLEANUP_TIMEOUT_MS = 30_000;\n\nexport interface FactoryTransitionRequest {\n orgId: string;\n factoryProjectId: string;\n workItemId: string;\n /** Installed board id; the service rejects boards that are not installed. */\n board: string;\n stage: FactoryRuleStage;\n expectedRevision: number;\n actor: FactoryRuleActor;\n actorProfile?: AuditActorProfileInput;\n /** Where a browser request came from; rules and agents carry none. */\n context?: AuditContext;\n ingress: { type: 'human' | 'agent' | 'toolResult' | 'github' | 'rule'; identity: string; transitionId?: string };\n cause: string;\n causalChain?: readonly FactoryRuleCausalEntry[];\n /** Internal materialization path: evaluate only the destination onEnter leaf even when already at that stage. */\n initialEntry?: boolean;\n /** Re-runs the stage's entry rules when the item already holds that stage, to restart work the entry invalidated. */\n reenter?: boolean;\n /** Structured verdict required from a bound triage-agent terminal request. */\n triageType?: FactoryTriageType;\n}\n\nexport interface FactoryTransitionServiceOptions {\n configVersion: string;\n storage: WorkItemsStorage;\n boards?: BoardRegistry;\n /** Every commit, accepted or rejected, lands here as `stage_moved` / `transition_rejected` under the request's actor. */\n audit?: AuditRecorder;\n timeoutMs?: number;\n /**\n * Called after a transition commits into a phase the board declares\n * terminal — the point where the item's sessions stop receiving runs, so\n * resources they hold (e.g. sandboxes) can be released for reuse. Awaited,\n * but failures are swallowed: releasing resources must never break or roll\n * back the committed transition.\n */\n onTerminalStage?: (args: {\n orgId: string;\n factoryProjectId: string;\n workItemId: string;\n stage: FactoryRuleStage;\n revision: number;\n /** The actor that committed this terminal transition. Lets cleanup leave\n * the seat that drove its own transition (an agent tool call) untouched. */\n actor: FactoryRuleActor;\n }) => Promise<void> | void;\n /** Upper bound on how long a committed transition waits for\n * `onTerminalStage` before returning (default 30s). The cleanup continues\n * in the background past the bound. */\n terminalCleanupTimeoutMs?: number;\n /**\n * Called after a transition first records a person's acceptance of a\n * non-bug item (see `WorkItemRow.acceptedAt`). Fire-and-forget: failures\n * are swallowed, the committed transition never depends on it.\n */\n onAccepted?: (args: {\n orgId: string;\n factoryProjectId: string;\n workItemId: string;\n item: WorkItemRow;\n }) => Promise<void> | void;\n /**\n * Resolves whether a project auto-approves produced plans. Mirrors the\n * dispatcher's resolver so the two share a single authoritative predicate\n * (`plansPreapprovedAt` on the item, or this per-project setting). Unset means\n * off: a plan nobody armed for auto-advance is a plan a person must review.\n */\n autoApprovePlans?: (tenant: { orgId: string; factoryProjectId: string }) => Promise<boolean>;\n}\n\nfunction rejection(\n transitionId: string,\n itemId: string,\n code: FactoryRuleRejectionCode,\n reason: string,\n): FactoryTransitionResult {\n return { status: 'rejected', transitionId, itemId, code, reason: reason.slice(0, MAX_REJECTION_REASON) };\n}\n\nfunction actorId(actor: FactoryRuleActor): string {\n switch (actor.type) {\n case 'human':\n case 'system':\n return actor.id;\n case 'agent':\n return `agent:${actor.bindingId}`;\n case 'github':\n return `github:${actor.login}`;\n }\n}\n\n// The dispatcher executes an agent-approved decision as a human actor so its consent carries; the trail still names the agent.\nexport function auditActorOf(actor: FactoryRuleActor): { actorId: string; actorType: AuditActorType } {\n const id = actorId(actor);\n switch (actor.type) {\n case 'github':\n return { actorId: id, actorType: 'human' };\n case 'human':\n return { actorId: id, actorType: isAgentActor(id) ? 'agent' : 'human' };\n default:\n return { actorId: id, actorType: actor.type };\n }\n}\n\nexport function currentStage(stages: readonly string[]): FactoryRuleStage | undefined {\n if (stages.length !== 1) return undefined;\n const stage = stages[0];\n return isFactoryRuleStage(stage) ? stage : undefined;\n}\n\ninterface TransitionConsentOptions {\n autonomy?: 'arm' | 'disarm';\n consentedBy?: string;\n accept?: boolean;\n triageType?: FactoryTriageType;\n}\n\n// Entering a resting lane disarms whoever rests it; only a person's move into a working lane arms.\nfunction transitionConsent(working: boolean, humanMove: boolean): 'arm' | 'disarm' | undefined {\n if (!working) return 'disarm';\n return humanMove ? 'arm' : undefined;\n}\n\n// An event arriving as data (GitHub, sweeps) never pre-approves the runs its transition queues.\nfunction bearsConsent(actor: FactoryRuleActor): boolean {\n return actor.type === 'human' || actor.type === 'agent';\n}\n\n// Rides the transition's own revision-checked commit, so a stale or rejected commit flips nothing.\nfunction consentEffect(\n request: FactoryTransitionRequest,\n working: boolean,\n humanMove: boolean,\n): TransitionConsentOptions {\n const autonomy = transitionConsent(working, humanMove);\n return bearsConsent(request.actor) ? { autonomy, consentedBy: actorId(request.actor) } : { autonomy };\n}\n\ntype RunStartDecision = Extract<FactoryCommitDecision, { type: 'invokeSkill' | 'sendMessage' }>;\n\nfunction startsRun(decision: FactoryCommitDecision): decision is RunStartDecision {\n return decision.type === 'invokeSkill' || (decision.type === 'sendMessage' && decision.prepareBinding === true);\n}\n\n// Answering a recorded run start, or the role's own mid-run agent, with a run would start a second one.\nfunction runAlreadyUnderway(request: FactoryTransitionRequest, decision: RunStartDecision): boolean {\n if (request.cause === 'run_start') return true;\n return request.actor.type === 'agent' && request.actor.role === decision.role;\n}\n\nfunction stageTransitionMessage(fromStage: FactoryRuleStage, toStage: FactoryRuleStage): string {\n return `This work was moved from the ${fromStage} stage to the ${toStage} stage.`;\n}\n\nfunction isTriageAgent(actor: FactoryRuleActor): actor is Extract<FactoryRuleActor, { type: 'agent' }> {\n return actor.type === 'agent' && actor.role === 'triage';\n}\n\nfunction isHumanTransition(request: FactoryTransitionRequest): boolean {\n return request.actor.type === 'human' && request.ingress.type === 'human';\n}\n\nfunction ruleFailure(error: unknown): { code: FactoryRuleRejectionCode; reason: string } {\n return {\n code: 'rule_error',\n reason: error instanceof Error ? `Factory rule failed: ${error.message}` : 'Factory rule failed.',\n };\n}\n\nasync function withRuleTimeout<T>(operation: Promise<T>, timeoutMs: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error('FACTORY_RULE_TIMEOUT')), timeoutMs);\n });\n try {\n return await Promise.race([operation, timeout]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\nexport class FactoryTransitionService {\n readonly #configVersion: string;\n readonly #boards: BoardRegistry;\n readonly #storage: WorkItemsStorage;\n readonly #timeoutMs: number;\n readonly #onTerminalStage: FactoryTransitionServiceOptions['onTerminalStage'];\n readonly #terminalCleanupTimeoutMs: number;\n readonly #onAccepted: FactoryTransitionServiceOptions['onAccepted'];\n readonly #autoApprovePlans: FactoryTransitionServiceOptions['autoApprovePlans'];\n readonly #audit: AuditRecorder | undefined;\n\n constructor(options: FactoryTransitionServiceOptions) {\n this.#configVersion = options.configVersion;\n this.#boards = options.boards ?? createBoardRegistry();\n this.#storage = options.storage;\n this.#audit = options.audit;\n this.#timeoutMs = options.timeoutMs ?? RULE_TIMEOUT_MS;\n this.#onTerminalStage = options.onTerminalStage;\n this.#onAccepted = options.onAccepted;\n this.#autoApprovePlans = options.autoApprovePlans;\n this.#terminalCleanupTimeoutMs = options.terminalCleanupTimeoutMs ?? TERMINAL_CLEANUP_TIMEOUT_MS;\n }\n\n get configVersion(): string {\n return this.#configVersion;\n }\n\n async transition(request: FactoryTransitionRequest): Promise<FactoryTransitionResult> {\n const replay = await this.#storage.getTransitionResultByIngress(\n request.orgId,\n request.factoryProjectId,\n request.ingress.identity,\n );\n if (replay) return replay as unknown as FactoryTransitionResult;\n\n const transitionId = request.ingress.transitionId ?? randomUUID();\n const item = await this.#storage.get({ orgId: request.orgId, id: request.workItemId });\n if (!item) {\n const rejection = await this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n 'Work item not found.',\n );\n await this.#recordTransition(request, undefined, rejection);\n return rejection;\n }\n const result = await this.#evaluateAndCommit(request, transitionId, item);\n await this.#recordTransition(request, item, result);\n return result;\n }\n\n /** A rejection can outlive its work item: the row still names the id the caller asked for. */\n async #recordTransition(\n request: FactoryTransitionRequest,\n item: WorkItemRow | undefined,\n result: FactoryTransitionResult,\n ): Promise<void> {\n if (!this.#audit) return;\n const from = item ? currentStage(item.stages) : undefined;\n if (result.status === 'accepted' && result.stage === from && !request.reenter) return;\n const outcome =\n result.status === 'accepted'\n ? { action: 'factory.work_item.stage_moved' as const, to: result.stage, revision: result.revision }\n : {\n action: 'factory.work_item.transition_rejected' as const,\n to: request.stage,\n code: result.code,\n reason: result.reason,\n };\n const { action, ...detail } = outcome;\n await this.#audit\n .record({\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n ...auditActorOf(request.actor),\n actorProfile: request.actorProfile,\n ...(request.context ? { context: request.context } : {}),\n action,\n idempotencyKey: result.transitionId,\n targets: [{ type: 'work_item', id: item?.id ?? request.workItemId, ...(item ? { name: item.title } : {}) }],\n metadata: {\n transitionId: result.transitionId,\n ingressType: request.ingress.type,\n cause: request.cause,\n configVersion: this.#configVersion,\n ...(from ? { from } : {}),\n ...(request.reenter ? { reenter: true } : {}),\n ...detail,\n },\n })\n .catch(error => {\n console.warn(`[factory] audit failed for transition ${result.transitionId}:`, error);\n });\n }\n\n async #evaluateAndCommit(\n request: FactoryTransitionRequest,\n transitionId: string,\n item: WorkItemRow,\n ): Promise<FactoryTransitionResult> {\n if (request.causalChain && request.causalChain.length > MAX_FACTORY_RULE_CAUSAL_DEPTH) {\n return this.#commitRejection(\n request,\n transitionId,\n 'causal_depth_exceeded',\n 'Factory rule causal depth exceeded.',\n );\n }\n const itemSource = workItemSource(item.externalSource);\n const source = factoryRuleSourceForWorkItem(itemSource);\n const legacyBoard = source === 'pullRequest' ? 'review' : 'work';\n if (item.board === null && !this.#boards.has(legacyBoard)) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n 'This legacy work item has no assigned board. Assign an installed board and phase through the work-item PATCH endpoint before transitioning it.',\n );\n }\n const itemBoard = item.board ?? legacyBoard;\n if (request.board !== itemBoard) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n `The work item belongs to board \"${itemBoard}\", not \"${request.board}\".`,\n );\n }\n if ((itemBoard === 'review' && source !== 'pullRequest') || (itemBoard === 'work' && source === 'pullRequest')) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n 'The work item does not belong to the requested board.',\n );\n }\n const board = this.#boards.get(request.board);\n if (!board) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n `Board \"${request.board}\" is not installed.`,\n );\n }\n const fromStage = item.stages.length === 1 ? item.stages[0] : undefined;\n if (!fromStage || !Object.prototype.hasOwnProperty.call(board.phases, fromStage)) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n 'The work item does not have one canonical phase on the requested board.',\n );\n }\n if (\n !Object.prototype.hasOwnProperty.call(board.phases, request.stage) ||\n !board.allowsTransition(fromStage, request.stage)\n ) {\n return this.#commitRejection(\n request,\n transitionId,\n 'invalid_transition',\n `The ${board.title} board does not allow moving from ${fromStage} to ${request.stage}.`,\n );\n }\n\n // The coordinator's own self-move at run start would otherwise inject a second run's kickoff.\n const humanMove = request.actor.type === 'human' && fromStage !== request.stage && request.cause !== 'run_start';\n // The board, not the phase name, says whether a seat is engaged on either side of this move.\n const entersWorking = board.isWorking(request.stage);\n const seatRole = board.roleForPhase(request.stage);\n\n const contextBase = {\n tenant: { orgId: request.orgId, projectId: request.factoryProjectId },\n actor: request.actor,\n ingress: { type: request.ingress.type, id: request.ingress.identity },\n cause: request.cause,\n causalChain: request.causalChain ?? [],\n configVersion: this.#configVersion,\n item: {\n id: item.id,\n source: itemSource,\n sourceKey: item.externalSource\n ? `${item.externalSource.integrationId}:${item.externalSource.type}:${item.externalSource.externalId}`\n : null,\n parentWorkItemId: item.parentWorkItemId,\n title: item.title,\n url: item.externalSource?.url ?? null,\n stages: [...item.stages],\n acceptedAt: item.acceptedAt,\n metadata: item.metadata,\n },\n board: request.board,\n itemRevision: item.revision,\n source,\n fromStage,\n toStage: request.stage,\n } satisfies Omit<FactoryStageRuleContext, 'stage'>;\n\n let evaluation:\n | { outcome: 'accepted'; decisions: Record<string, unknown>[]; intents: TransitionConsentOptions }\n | { outcome: 'rejected'; code: string; reason: string };\n try {\n evaluation = await withRuleTimeout(\n (async () => {\n // Single authoritative plan-approval predicate, shared with the dispatcher's\n // `#plansAreAutoApproved`: a per-item preapproval, or the project setting.\n // Resolved inside the timed block so a resolver rejection surfaces as a\n // committed rule_error and a slow lookup is bounded by RULE_TIMEOUT_MS.\n const plansAutoApproved =\n item.plansPreapprovedAt != null ||\n (this.#autoApprovePlans\n ? await this.#autoApprovePlans({ orgId: request.orgId, factoryProjectId: request.factoryProjectId })\n : false);\n const policy = boardTransitionPolicyResultSchema.parse(\n await board.transitionPolicy?.(\n immutablePolicySnapshot({\n ...contextBase,\n item: { ...contextBase.item, triageType: item.triageType },\n initialEntry: request.initialEntry ?? false,\n reenter: request.reenter ?? false,\n isHumanTransition: isHumanTransition(request),\n plansAutoApproved,\n requestedTriageType: request.triageType,\n }),\n ),\n );\n if (policy?.type === 'reject') {\n return { outcome: 'rejected' as const, code: policy.code, reason: policy.reason };\n }\n if (\n policy?.triageType !== undefined &&\n (!isTriageAgent(request.actor) ||\n policy.triageType !== request.triageType ||\n (item.triageType !== null && item.triageType !== policy.triageType))\n ) {\n throw new Error('Board policy requested an unauthorized classification.');\n }\n if (policy?.accept && !isHumanTransition(request)) {\n throw new Error('Board policy requested unauthorized acceptance.');\n }\n // External content can steer a bound agent; board allowance cannot bypass this guard.\n if (\n request.actor.type === 'agent' &&\n !board.isWorking(fromStage) &&\n entersWorking &&\n externallyAuthoredWorkItem(item)\n ) {\n return {\n outcome: 'rejected' as const,\n code: 'approval_required',\n reason:\n 'This card comes from outside the write-access circle; a person must resume it from the Factory board.',\n };\n }\n const decisions: FactoryCommitDecision[] = [];\n for (const rule of resolveFactoryStageRules(this.#boards, {\n board: request.board,\n source,\n fromStage,\n toStage: request.stage,\n initialEntry: request.initialEntry,\n reenter: request.reenter,\n })) {\n const context: FactoryStageRuleContext = Object.freeze({\n ...contextBase,\n stage: rule.phase === 'exit' ? fromStage : request.stage,\n });\n const raw = await rule.handler(context);\n if (raw === undefined) continue;\n const decision = validateFactoryRuleDecision(raw, context.causalChain.length);\n if (decision.type === 'reject') {\n return { outcome: 'rejected' as const, code: decision.code, reason: decision.reason };\n }\n assertFactoryDecisionTarget(decision, this.#boards, itemBoard);\n if (startsRun(decision) && runAlreadyUnderway(request, decision)) continue;\n decisions.push(decision);\n }\n const validated = validateFactoryRuleDecisions(decisions);\n if (humanMove) {\n const message = stageTransitionMessage(fromStage, request.stage);\n const skill = validated.find(decision => decision.type === 'invokeSkill');\n if (skill) {\n skill.precedingMessage = message;\n } else {\n validated.unshift({\n type: 'sendMessage',\n idempotencyKey: `factory-stage:${transitionId}`,\n message,\n priority: 'urgent',\n idleBehavior: 'wake',\n // Parking a card says stop: no seat is right by construction, so\n // the notice goes to whichever session is live — or nobody.\n ...(entersWorking && seatRole !== undefined ? { role: seatRole, prepareBinding: true } : {}),\n });\n }\n }\n return {\n outcome: 'accepted' as const,\n intents: { triageType: policy?.triageType, accept: policy?.accept === true && !item.acceptedAt },\n decisions: validateFactoryRuleDecisions(validated) as unknown as Record<string, unknown>[],\n };\n })(),\n this.#timeoutMs,\n );\n } catch (error) {\n const failed =\n error instanceof Error && error.message === 'FACTORY_RULE_TIMEOUT'\n ? { code: 'timeout' as const, reason: 'Factory rule evaluation timed out.' }\n : ruleFailure(error);\n evaluation = { outcome: 'rejected', ...failed };\n }\n return this.#commit(\n request,\n transitionId,\n evaluation,\n evaluation.outcome === 'accepted'\n ? { ...consentEffect(request, entersWorking, humanMove), ...evaluation.intents }\n : {},\n );\n }\n\n async #commitRejection(\n request: FactoryTransitionRequest,\n transitionId: string,\n code: FactoryRuleRejectionCode,\n reason: string,\n ): Promise<FactoryTransitionResult> {\n return this.#commit(request, transitionId, { outcome: 'rejected', code, reason });\n }\n\n async #commit(\n request: FactoryTransitionRequest,\n transitionId: string,\n evaluation:\n | { outcome: 'accepted'; decisions: Record<string, unknown>[] }\n | { outcome: 'rejected'; code: string; reason: string },\n options: TransitionConsentOptions = {},\n ): Promise<FactoryTransitionResult> {\n const committed = await this.#storage.commitTransition({\n autonomy: options.autonomy,\n consentedBy: options.consentedBy,\n ...(options.accept ? { accept: true } : {}),\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n workItemId: request.workItemId,\n expectedRevision: request.expectedRevision,\n destinationStage: request.stage,\n actorId: actorId(request.actor),\n ingress: { identity: request.ingress.identity, triggerType: request.ingress.type, transitionId },\n configVersion: this.#configVersion,\n causalChain: [...(request.causalChain ?? [])],\n evaluation,\n ...(options.triageType ? { triageType: options.triageType } : {}),\n });\n if (committed.status === 'missing') {\n return rejection(transitionId, request.workItemId, 'invalid_transition', 'Work item not found.');\n }\n const result = committed.result as unknown as FactoryTransitionResult;\n if (\n this.#onAccepted &&\n options.accept &&\n committed.status === 'committed' &&\n result.status === 'accepted' &&\n committed.item?.acceptedAt\n ) {\n const item = committed.item;\n const onAccepted = this.#onAccepted;\n // Invoke inside the chain so a synchronous throw is isolated the same way an async rejection is.\n void Promise.resolve()\n .then(() =>\n onAccepted({\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n workItemId: request.workItemId,\n item,\n }),\n )\n .catch(error => {\n console.warn(`[factory] acceptance hook failed for work item ${request.workItemId}:`, error);\n });\n }\n // Only an installed board's declaration releases resources; an unknown board or phase never does.\n if (\n this.#onTerminalStage &&\n result.status === 'accepted' &&\n this.#boards.get(request.board)?.isTerminal(result.stage) === true\n ) {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n const cleanup = Promise.resolve(\n this.#onTerminalStage({\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n workItemId: request.workItemId,\n stage: result.stage,\n revision: result.revision,\n actor: request.actor,\n }),\n );\n // A late rejection after the timeout wins the race must not surface\n // as an unhandled rejection.\n cleanup.catch(() => {});\n await Promise.race([\n cleanup,\n new Promise<void>(resolve => {\n timer = setTimeout(resolve, this.#terminalCleanupTimeoutMs);\n }),\n ]);\n } catch {\n // Resource release is best-effort — never fail a committed transition.\n } finally {\n clearTimeout(timer);\n }\n }\n return result;\n }\n}\n"],"mappings":";;;;;;;;;AAkCA,MAAM,kBAAkB;AACxB,MAAM,uBAAuB;;;;;AAK7B,MAAM,8BAA8B;AAyEpC,SAAS,UACP,cACA,QACA,MACA,QACyB;CACzB,OAAO;EAAE,QAAQ;EAAY;EAAc;EAAQ;EAAM,QAAQ,OAAO,MAAM,GAAG,oBAAoB;CAAE;AACzG;AAEA,SAAS,QAAQ,OAAiC;CAChD,QAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK,UACH,OAAO,MAAM;EACf,KAAK,SACH,OAAO,SAAS,MAAM;EACxB,KAAK,UACH,OAAO,UAAU,MAAM;CAC3B;AACF;AAGA,SAAgB,aAAa,OAAyE;CACpG,MAAM,KAAK,QAAQ,KAAK;CACxB,QAAQ,MAAM,MAAd;EACE,KAAK,UACH,OAAO;GAAE,SAAS;GAAI,WAAW;EAAQ;EAC3C,KAAK,SACH,OAAO;GAAE,SAAS;GAAI,WAAW,aAAa,EAAE,IAAI,UAAU;EAAQ;EACxE,SACE,OAAO;GAAE,SAAS;GAAI,WAAW,MAAM;EAAK;CAChD;AACF;AAEA,SAAgB,aAAa,QAAyD;CACpF,IAAI,OAAO,WAAW,GAAG,OAAO,KAAA;CAChC,MAAM,QAAQ,OAAO;CACrB,OAAO,mBAAmB,KAAK,IAAI,QAAQ,KAAA;AAC7C;AAUA,SAAS,kBAAkB,SAAkB,WAAkD;CAC7F,IAAI,CAAC,SAAS,OAAO;CACrB,OAAO,YAAY,QAAQ,KAAA;AAC7B;AAGA,SAAS,aAAa,OAAkC;CACtD,OAAO,MAAM,SAAS,WAAW,MAAM,SAAS;AAClD;AAGA,SAAS,cACP,SACA,SACA,WAC0B;CAC1B,MAAM,WAAW,kBAAkB,SAAS,SAAS;CACrD,OAAO,aAAa,QAAQ,KAAK,IAAI;EAAE;EAAU,aAAa,QAAQ,QAAQ,KAAK;CAAE,IAAI,EAAE,SAAS;AACtG;AAIA,SAAS,UAAU,UAA+D;CAChF,OAAO,SAAS,SAAS,iBAAkB,SAAS,SAAS,iBAAiB,SAAS,mBAAmB;AAC5G;AAGA,SAAS,mBAAmB,SAAmC,UAAqC;CAClG,IAAI,QAAQ,UAAU,aAAa,OAAO;CAC1C,OAAO,QAAQ,MAAM,SAAS,WAAW,QAAQ,MAAM,SAAS,SAAS;AAC3E;AAEA,SAAS,uBAAuB,WAA6B,SAAmC;CAC9F,OAAO,gCAAgC,UAAU,gBAAgB,QAAQ;AAC3E;AAEA,SAAS,cAAc,OAAgF;CACrG,OAAO,MAAM,SAAS,WAAW,MAAM,SAAS;AAClD;AAEA,SAAS,kBAAkB,SAA4C;CACrE,OAAO,QAAQ,MAAM,SAAS,WAAW,QAAQ,QAAQ,SAAS;AACpE;AAEA,SAAS,YAAY,OAAoE;CACvF,OAAO;EACL,MAAM;EACN,QAAQ,iBAAiB,QAAQ,wBAAwB,MAAM,YAAY;CAC7E;AACF;AAEA,eAAe,gBAAmB,WAAuB,WAA+B;CACtF,IAAI;CACJ,MAAM,UAAU,IAAI,SAAgB,GAAG,WAAW;EAChD,QAAQ,iBAAiB,uBAAO,IAAI,MAAM,sBAAsB,CAAC,GAAG,SAAS;CAC/E,CAAC;CACD,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CAAC,WAAW,OAAO,CAAC;CAChD,UAAU;EACR,IAAI,OAAO,aAAa,KAAK;CAC/B;AACF;AAEA,IAAa,2BAAb,MAAsC;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,SAA0C;EACpD,KAAKA,iBAAiB,QAAQ;EAC9B,KAAKC,UAAU,QAAQ,UAAU,oBAAoB;EACrD,KAAKC,WAAW,QAAQ;EACxB,KAAKM,SAAS,QAAQ;EACtB,KAAKL,aAAa,QAAQ,aAAa;EACvC,KAAKC,mBAAmB,QAAQ;EAChC,KAAKE,cAAc,QAAQ;EAC3B,KAAKC,oBAAoB,QAAQ;EACjC,KAAKF,4BAA4B,QAAQ,4BAA4B;CACvE;CAEA,IAAI,gBAAwB;EAC1B,OAAO,KAAKL;CACd;CAEA,MAAM,WAAW,SAAqE;EACpF,MAAM,SAAS,MAAM,KAAKE,SAAS,6BACjC,QAAQ,OACR,QAAQ,kBACR,QAAQ,QAAQ,QAClB;EACA,IAAI,QAAQ,OAAO;EAEnB,MAAM,eAAe,QAAQ,QAAQ,gBAAgB,WAAW;EAChE,MAAM,OAAO,MAAM,KAAKA,SAAS,IAAI;GAAE,OAAO,QAAQ;GAAO,IAAI,QAAQ;EAAW,CAAC;EACrF,IAAI,CAAC,MAAM;GACT,MAAM,YAAY,MAAM,KAAKO,iBAC3B,SACA,cACA,sBACA,sBACF;GACA,MAAM,KAAKC,kBAAkB,SAAS,KAAA,GAAW,SAAS;GAC1D,OAAO;EACT;EACA,MAAM,SAAS,MAAM,KAAKC,mBAAmB,SAAS,cAAc,IAAI;EACxE,MAAM,KAAKD,kBAAkB,SAAS,MAAM,MAAM;EAClD,OAAO;CACT;;CAGA,MAAMA,kBACJ,SACA,MACA,QACe;EACf,IAAI,CAAC,KAAKF,QAAQ;EAClB,MAAM,OAAO,OAAO,aAAa,KAAK,MAAM,IAAI,KAAA;EAChD,IAAI,OAAO,WAAW,cAAc,OAAO,UAAU,QAAQ,CAAC,QAAQ,SAAS;EAU/E,MAAM,EAAE,QAAQ,GAAG,WARjB,OAAO,WAAW,aACd;GAAE,QAAQ;GAA0C,IAAI,OAAO;GAAO,UAAU,OAAO;EAAS,IAChG;GACE,QAAQ;GACR,IAAI,QAAQ;GACZ,MAAM,OAAO;GACb,QAAQ,OAAO;EACjB;EAEN,MAAM,KAAKA,OACR,OAAO;GACN,OAAO,QAAQ;GACf,kBAAkB,QAAQ;GAC1B,GAAG,aAAa,QAAQ,KAAK;GAC7B,cAAc,QAAQ;GACtB,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;GACtD;GACA,gBAAgB,OAAO;GACvB,SAAS,CAAC;IAAE,MAAM;IAAa,IAAI,MAAM,MAAM,QAAQ;IAAY,GAAI,OAAO,EAAE,MAAM,KAAK,MAAM,IAAI,CAAC;GAAG,CAAC;GAC1G,UAAU;IACR,cAAc,OAAO;IACrB,aAAa,QAAQ,QAAQ;IAC7B,OAAO,QAAQ;IACf,eAAe,KAAKR;IACpB,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;IACvB,GAAI,QAAQ,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;IAC3C,GAAG;GACL;EACF,CAAC,CAAC,CACD,OAAM,UAAS;GACd,QAAQ,KAAK,yCAAyC,OAAO,aAAa,IAAI,KAAK;EACrF,CAAC;CACL;CAEA,MAAMW,mBACJ,SACA,cACA,MACkC;EAClC,IAAI,QAAQ,eAAe,QAAQ,YAAY,SAAA,GAC7C,OAAO,KAAKF,iBACV,SACA,cACA,yBACA,qCACF;EAEF,MAAM,aAAa,eAAe,KAAK,cAAc;EACrD,MAAM,SAAS,6BAA6B,UAAU;EACtD,MAAM,cAAc,WAAW,gBAAgB,WAAW;EAC1D,IAAI,KAAK,UAAU,QAAQ,CAAC,KAAKR,QAAQ,IAAI,WAAW,GACtD,OAAO,KAAKQ,iBACV,SACA,cACA,sBACA,gJACF;EAEF,MAAM,YAAY,KAAK,SAAS;EAChC,IAAI,QAAQ,UAAU,WACpB,OAAO,KAAKA,iBACV,SACA,cACA,sBACA,mCAAmC,UAAU,UAAU,QAAQ,MAAM,GACvE;EAEF,IAAK,cAAc,YAAY,WAAW,iBAAmB,cAAc,UAAU,WAAW,eAC9F,OAAO,KAAKA,iBACV,SACA,cACA,sBACA,uDACF;EAEF,MAAM,QAAQ,KAAKR,QAAQ,IAAI,QAAQ,KAAK;EAC5C,IAAI,CAAC,OACH,OAAO,KAAKQ,iBACV,SACA,cACA,sBACA,UAAU,QAAQ,MAAM,oBAC1B;EAEF,MAAM,YAAY,KAAK,OAAO,WAAW,IAAI,KAAK,OAAO,KAAK,KAAA;EAC9D,IAAI,CAAC,aAAa,CAAC,OAAO,UAAU,eAAe,KAAK,MAAM,QAAQ,SAAS,GAC7E,OAAO,KAAKA,iBACV,SACA,cACA,sBACA,yEACF;EAEF,IACE,CAAC,OAAO,UAAU,eAAe,KAAK,MAAM,QAAQ,QAAQ,KAAK,KACjE,CAAC,MAAM,iBAAiB,WAAW,QAAQ,KAAK,GAEhD,OAAO,KAAKA,iBACV,SACA,cACA,sBACA,OAAO,MAAM,MAAM,oCAAoC,UAAU,MAAM,QAAQ,MAAM,EACvF;EAIF,MAAM,YAAY,QAAQ,MAAM,SAAS,WAAW,cAAc,QAAQ,SAAS,QAAQ,UAAU;EAErG,MAAM,gBAAgB,MAAM,UAAU,QAAQ,KAAK;EACnD,MAAM,WAAW,MAAM,aAAa,QAAQ,KAAK;EAEjD,MAAM,cAAc;GAClB,QAAQ;IAAE,OAAO,QAAQ;IAAO,WAAW,QAAQ;GAAiB;GACpE,OAAO,QAAQ;GACf,SAAS;IAAE,MAAM,QAAQ,QAAQ;IAAM,IAAI,QAAQ,QAAQ;GAAS;GACpE,OAAO,QAAQ;GACf,aAAa,QAAQ,eAAe,CAAC;GACrC,eAAe,KAAKT;GACpB,MAAM;IACJ,IAAI,KAAK;IACT,QAAQ;IACR,WAAW,KAAK,iBACZ,GAAG,KAAK,eAAe,cAAc,GAAG,KAAK,eAAe,KAAK,GAAG,KAAK,eAAe,eACxF;IACJ,kBAAkB,KAAK;IACvB,OAAO,KAAK;IACZ,KAAK,KAAK,gBAAgB,OAAO;IACjC,QAAQ,CAAC,GAAG,KAAK,MAAM;IACvB,YAAY,KAAK;IACjB,UAAU,KAAK;GACjB;GACA,OAAO,QAAQ;GACf,cAAc,KAAK;GACnB;GACA;GACA,SAAS,QAAQ;EACnB;EAEA,IAAI;EAGJ,IAAI;GACF,aAAa,MAAM,iBAChB,YAAY;IAKX,MAAM,oBACJ,KAAK,sBAAsB,SAC1B,KAAKO,oBACF,MAAM,KAAKA,kBAAkB;KAAE,OAAO,QAAQ;KAAO,kBAAkB,QAAQ;IAAiB,CAAC,IACjG;IACN,MAAM,SAAS,kCAAkC,MAC/C,MAAM,MAAM,mBACV,wBAAwB;KACtB,GAAG;KACH,MAAM;MAAE,GAAG,YAAY;MAAM,YAAY,KAAK;KAAW;KACzD,cAAc,QAAQ,gBAAgB;KACtC,SAAS,QAAQ,WAAW;KAC5B,mBAAmB,kBAAkB,OAAO;KAC5C;KACA,qBAAqB,QAAQ;IAC/B,CAAC,CACH,CACF;IACA,IAAI,QAAQ,SAAS,UACnB,OAAO;KAAE,SAAS;KAAqB,MAAM,OAAO;KAAM,QAAQ,OAAO;IAAO;IAElF,IACE,QAAQ,eAAe,KAAA,MACtB,CAAC,cAAc,QAAQ,KAAK,KAC3B,OAAO,eAAe,QAAQ,cAC7B,KAAK,eAAe,QAAQ,KAAK,eAAe,OAAO,aAE1D,MAAM,IAAI,MAAM,wDAAwD;IAE1E,IAAI,QAAQ,UAAU,CAAC,kBAAkB,OAAO,GAC9C,MAAM,IAAI,MAAM,iDAAiD;IAGnE,IACE,QAAQ,MAAM,SAAS,WACvB,CAAC,MAAM,UAAU,SAAS,KAC1B,iBACA,2BAA2B,IAAI,GAE/B,OAAO;KACL,SAAS;KACT,MAAM;KACN,QACE;IACJ;IAEF,MAAM,YAAqC,CAAC;IAC5C,KAAK,MAAM,QAAQ,yBAAyB,KAAKN,SAAS;KACxD,OAAO,QAAQ;KACf;KACA;KACA,SAAS,QAAQ;KACjB,cAAc,QAAQ;KACtB,SAAS,QAAQ;IACnB,CAAC,GAAG;KACF,MAAM,UAAmC,OAAO,OAAO;MACrD,GAAG;MACH,OAAO,KAAK,UAAU,SAAS,YAAY,QAAQ;KACrD,CAAC;KACD,MAAM,MAAM,MAAM,KAAK,QAAQ,OAAO;KACtC,IAAI,QAAQ,KAAA,GAAW;KACvB,MAAM,WAAW,4BAA4B,KAAK,QAAQ,YAAY,MAAM;KAC5E,IAAI,SAAS,SAAS,UACpB,OAAO;MAAE,SAAS;MAAqB,MAAM,SAAS;MAAM,QAAQ,SAAS;KAAO;KAEtF,4BAA4B,UAAU,KAAKA,SAAS,SAAS;KAC7D,IAAI,UAAU,QAAQ,KAAK,mBAAmB,SAAS,QAAQ,GAAG;KAClE,UAAU,KAAK,QAAQ;IACzB;IACA,MAAM,YAAY,6BAA6B,SAAS;IACxD,IAAI,WAAW;KACb,MAAM,UAAU,uBAAuB,WAAW,QAAQ,KAAK;KAC/D,MAAM,QAAQ,UAAU,MAAK,aAAY,SAAS,SAAS,aAAa;KACxE,IAAI,OACF,MAAM,mBAAmB;UAEzB,UAAU,QAAQ;MAChB,MAAM;MACN,gBAAgB,iBAAiB;MACjC;MACA,UAAU;MACV,cAAc;MAGd,GAAI,iBAAiB,aAAa,KAAA,IAAY;OAAE,MAAM;OAAU,gBAAgB;MAAK,IAAI,CAAC;KAC5F,CAAC;IAEL;IACA,OAAO;KACL,SAAS;KACT,SAAS;MAAE,YAAY,QAAQ;MAAY,QAAQ,QAAQ,WAAW,QAAQ,CAAC,KAAK;KAAW;KAC/F,WAAW,6BAA6B,SAAS;IACnD;GACF,EAAA,CAAG,GACH,KAAKE,UACP;EACF,SAAS,OAAO;GAKd,aAAa;IAAE,SAAS;IAAY,GAHlC,iBAAiB,SAAS,MAAM,YAAY,yBACxC;KAAE,MAAM;KAAoB,QAAQ;IAAqC,IACzE,YAAY,KAAK;GACuB;EAChD;EACA,OAAO,KAAKS,QACV,SACA,cACA,YACA,WAAW,YAAY,aACnB;GAAE,GAAG,cAAc,SAAS,eAAe,SAAS;GAAG,GAAG,WAAW;EAAQ,IAC7E,CAAC,CACP;CACF;CAEA,MAAMH,iBACJ,SACA,cACA,MACA,QACkC;EAClC,OAAO,KAAKG,QAAQ,SAAS,cAAc;GAAE,SAAS;GAAY;GAAM;EAAO,CAAC;CAClF;CAEA,MAAMA,QACJ,SACA,cACA,YAGA,UAAoC,CAAC,GACH;EAClC,MAAM,YAAY,MAAM,KAAKV,SAAS,iBAAiB;GACrD,UAAU,QAAQ;GAClB,aAAa,QAAQ;GACrB,GAAI,QAAQ,SAAS,EAAE,QAAQ,KAAK,IAAI,CAAC;GACzC,OAAO,QAAQ;GACf,kBAAkB,QAAQ;GAC1B,YAAY,QAAQ;GACpB,kBAAkB,QAAQ;GAC1B,kBAAkB,QAAQ;GAC1B,SAAS,QAAQ,QAAQ,KAAK;GAC9B,SAAS;IAAE,UAAU,QAAQ,QAAQ;IAAU,aAAa,QAAQ,QAAQ;IAAM;GAAa;GAC/F,eAAe,KAAKF;GACpB,aAAa,CAAC,GAAI,QAAQ,eAAe,CAAC,CAAE;GAC5C;GACA,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;EACjE,CAAC;EACD,IAAI,UAAU,WAAW,WACvB,OAAO,UAAU,cAAc,QAAQ,YAAY,sBAAsB,sBAAsB;EAEjG,MAAM,SAAS,UAAU;EACzB,IACE,KAAKM,eACL,QAAQ,UACR,UAAU,WAAW,eACrB,OAAO,WAAW,cAClB,UAAU,MAAM,YAChB;GACA,MAAM,OAAO,UAAU;GACvB,MAAM,aAAa,KAAKA;GAExB,QAAa,QAAQ,CAAC,CACnB,WACC,WAAW;IACT,OAAO,QAAQ;IACf,kBAAkB,QAAQ;IAC1B,YAAY,QAAQ;IACpB;GACF,CAAC,CACH,CAAC,CACA,OAAM,UAAS;IACd,QAAQ,KAAK,kDAAkD,QAAQ,WAAW,IAAI,KAAK;GAC7F,CAAC;EACL;EAEA,IACE,KAAKF,oBACL,OAAO,WAAW,cAClB,KAAKH,QAAQ,IAAI,QAAQ,KAAK,CAAC,EAAE,WAAW,OAAO,KAAK,MAAM,MAC9D;GACA,IAAI;GACJ,IAAI;IACF,MAAM,UAAU,QAAQ,QACtB,KAAKG,iBAAiB;KACpB,OAAO,QAAQ;KACf,kBAAkB,QAAQ;KAC1B,YAAY,QAAQ;KACpB,OAAO,OAAO;KACd,UAAU,OAAO;KACjB,OAAO,QAAQ;IACjB,CAAC,CACH;IAGA,QAAQ,YAAY,CAAC,CAAC;IACtB,MAAM,QAAQ,KAAK,CACjB,SACA,IAAI,SAAc,YAAW;KAC3B,QAAQ,WAAW,SAAS,KAAKC,yBAAyB;IAC5D,CAAC,CACH,CAAC;GACH,QAAQ,CAER,UAAU;IACR,aAAa,KAAK;GACpB;EACF;EACA,OAAO;CACT;AACF"}
|
package/dist/rules/types.d.ts
CHANGED
|
@@ -267,6 +267,13 @@ export interface FactoryUpsertLinkedWorkItemDecision extends FactoryCommitDecisi
|
|
|
267
267
|
board: FactoryRuleBoard;
|
|
268
268
|
source: WorkItemSource;
|
|
269
269
|
sourceKey: string;
|
|
270
|
+
/**
|
|
271
|
+
* Org-wide ownership key for the external record, when one Factory at a time
|
|
272
|
+
* may hold a live card for it (a stable Linear issue id, for instance). The
|
|
273
|
+
* store enforces it with a unique index, so a second project's materialization
|
|
274
|
+
* is refused rather than duplicated.
|
|
275
|
+
*/
|
|
276
|
+
claimKey?: string;
|
|
270
277
|
title: string;
|
|
271
278
|
url: string | null;
|
|
272
279
|
stage: FactoryRuleStage;
|
|
@@ -289,9 +296,17 @@ interface FactoryInvokeSkillDecisionBase extends FactoryCommitDecisionBase {
|
|
|
289
296
|
export type FactoryInvokeSkillDecision = FactoryInvokeSkillDecisionBase & ({
|
|
290
297
|
skillName: string;
|
|
291
298
|
prompt?: never;
|
|
299
|
+
/**
|
|
300
|
+
* Same-stage re-entry: the skill is already active in the card's live session,
|
|
301
|
+
* so deliver a compact continuation that references it by name and carries only
|
|
302
|
+
* the fresh arguments, instead of re-pasting the whole skill document. Only valid
|
|
303
|
+
* for named-skill decisions — a plain prompt run has no active skill to resume.
|
|
304
|
+
*/
|
|
305
|
+
resume?: boolean;
|
|
292
306
|
} | {
|
|
293
307
|
prompt: string;
|
|
294
308
|
skillName?: never;
|
|
309
|
+
resume?: never;
|
|
295
310
|
});
|
|
296
311
|
export interface FactorySendMessageDecision extends FactoryCommitDecisionBase {
|
|
297
312
|
type: 'sendMessage';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rules/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAEpF,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,WAAW,GAAG,cAAc,GAAG,QAAQ,CAAC;AAEtF,oGAAoG;AACpG,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAC7D,eAAO,MAAM,kBAAkB,yBAAyB,CAAC;AAIzD,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACnC,GAAG,OAAO,CAQV;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,GAAG,cAAc,CAOpF;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,CAI9G;AAGD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,CAE/G;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,cAAc,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC1C,GAAG,OAAO,CAEV;AAED,eAAO,MAAM,mBAAmB,oFAAqF,CAAC;AACtH,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAIpF,eAAO,MAAM,mBAAmB;;;;;CAKqB,CAAC;AACtD,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,mBAAmB,CAAC;AAE3D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,WAAW,CAEjE;AAED,eAAO,MAAM,oBAAoB,qJAYvB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,GAAG,SAAS,CAGxF;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAG7E;AAED,yFAAyF;AACzF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAE1E;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE7E;AAED,eAAO,MAAM,mBAAmB,6BAA8B,CAAC;AAC/D,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAEpF,eAAO,MAAM,oBAAoB,4DAA6D,CAAC;AAC/F,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,eAAO,MAAM,qBAAqB,0SAcxB,CAAC;AACX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,eAAO,MAAM,qBAAqB,2CAA4C,CAAC;AAC/E,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,MAAM,MAAM,oBAAoB,GAC5B,IAAI,GACJ,OAAO,GACP,MAAM,GACN,MAAM,GACN,oBAAoB,EAAE,GACtB;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAAA;CAAE,CAAC;AAE5C,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,GAC7E;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACtE,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,qBAAqB,CAAC,MAAM,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,0BAA0B,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC/C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAwB,SAAQ,sBAAsB;IACrE,IAAI,EAAE,sBAAsB,CAAC;IAC7B,KAAK,EAAE,gBAAgB,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,gBAAgB,CAAC;IACxB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA6B,SAAQ,uBAAuB;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE;QACN,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;QAC5B,KAAK,EAAE,oBAAoB,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,wBAAyB,SAAQ,sBAAsB;IACtE,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,KAAK,CAAC,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;QAC1B,uEAAuE;QACvE,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAChD,YAAY,CAAC,EAAE;QACb,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;QACzB,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,EAAE,OAAO,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,OAAO,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,mFAAmF;IACnF,aAAa,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/D,qEAAqE;IACrE,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,QAAQ,GAAG,WAAW,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,gFAAgF;IAChF,MAAM,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAyB,SAAQ,sBAAsB;IACtE,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,KAAK,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QAC1B,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,MAAM,kBAAkB,CAAC,QAAQ,IAAI,CACzC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,KACxB,mBAAmB,GAAG,IAAI,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,kBAAkB,CAAC,uBAAuB,CAAC,CAAC;IACtD,MAAM,CAAC,EAAE,kBAAkB,CAAC,uBAAuB,CAAC,CAAC;CACtD;AAED,MAAM,MAAM,wBAAwB,GAChC,WAAW,GACX,oBAAoB,GACpB,iBAAiB,GACjB,OAAO,GACP,SAAS,GACT,YAAY,GACZ,uBAAuB,GACvB,qBAAqB,GACrB,mBAAmB,CAAC;AAExB,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,wBAAwB,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,yBAAyB;IACjC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,yBAA0B,SAAQ,yBAAyB;IAC1E,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mCAAoC,SAAQ,yBAAyB;IACpF,IAAI,EAAE,sBAAsB,CAAC;IAC7B,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CACjD;AAED,UAAU,8BAA+B,SAAQ,yBAAyB;IACxE,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,0BAA0B,GAAG,8BAA8B,GACrE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rules/types.ts"],"names":[],"mappings":"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"}
|
package/dist/rules/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../src/rules/types.ts"],"sourcesContent":["import type { ExternalWorkItemSource } from '../storage/domains/work-items/base.js';\n\nexport type WorkItemSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'manual';\n\n/** The source label that holds an issue at rest until a maintainer decides; compared lowercased. */\nexport const NEEDS_APPROVAL_LABEL = 'status: needs approval';\nexport const AUTO_TRIAGED_LABEL = 'status: auto-triaged';\n\n// The label only holds a card at rest: once a person accepted it, or it sits in a working\n// lane only a person could have moved it into, the label is stale until the source catches up.\nexport function needsApproval(item: {\n metadata: Record<string, unknown> | null;\n stages?: readonly string[];\n acceptedAt?: Date | string | null;\n}): boolean {\n const labels = item.metadata?.labels;\n if (!Array.isArray(labels)) return false;\n return (\n labels.some(label => typeof label === 'string' && label.toLowerCase() === NEEDS_APPROVAL_LABEL) &&\n !item.acceptedAt &&\n (item.stages ?? ['intake']).every(stage => stage === 'intake' || stage === 'triage')\n );\n}\n\nexport function workItemSource(source: ExternalWorkItemSource | null): WorkItemSource {\n if (!source) return 'manual';\n if (source.integrationId === 'linear') return 'linear-issue';\n // Only GitHub and Linear have provider-specific rules; anything else (a Slack\n // thread, say) is a plain work item, not a mislabeled GitHub issue.\n if (source.integrationId !== 'github') return 'manual';\n return source.type === 'pull-request' ? 'github-pr' : 'github-issue';\n}\n\n// Authored outside the write-access circle: a missing trust stamp fails closed until\n// the reconcile sweep backfills it, and Factory's own PRs pass through `factoryAuthored`.\nexport function externallyAuthored(item: { source: string; metadata: Record<string, unknown> | null }): boolean {\n if (item.source !== 'github-pr' && item.source !== 'github-issue') return false;\n if (item.metadata?.factoryAuthored === true) return false;\n return item.metadata?.authorTrusted !== true;\n}\n\n// The board mark claims only what GitHub answered: a missing stamp is silence, not an outside contribution.\nexport function knownExternalAuthor(item: { source: string; metadata: Record<string, unknown> | null }): boolean {\n return externallyAuthored(item) && item.metadata?.authorTrusted === false;\n}\n\nexport function externallyAuthoredWorkItem(item: {\n externalSource: ExternalWorkItemSource | null;\n metadata: Record<string, unknown> | null;\n}): boolean {\n return externallyAuthored({ source: workItemSource(item.externalSource), metadata: item.metadata });\n}\n\nexport const FACTORY_RULE_STAGES = ['intake', 'triage', 'planning', 'execute', 'review', 'done', 'canceled'] as const;\nexport type FactoryRuleStage = (typeof FACTORY_RULE_STAGES)[number] | (string & {});\n\n// Each role and the working stage its run holds the card in. Key order is the\n// seat pipeline order — Resume depth derives from it.\nexport const FACTORY_ROLE_STAGES = {\n triage: 'triage',\n plan: 'planning',\n work: 'execute',\n review: 'review',\n} as const satisfies Record<string, FactoryRuleStage>;\nexport type FactoryRole = keyof typeof FACTORY_ROLE_STAGES;\n\nexport function isFactoryRole(value: string): value is FactoryRole {\n return value in FACTORY_ROLE_STAGES;\n}\n\nexport const FACTORY_TRIAGE_TYPES = [\n 'bug',\n 'feature request',\n 'docs',\n 'question/support',\n 'maintenance',\n 'duplicate',\n 'resolved',\n 'invalid',\n 'spam',\n 'out-of-scope',\n 'other',\n] as const;\nexport type FactoryTriageType = (typeof FACTORY_TRIAGE_TYPES)[number];\n\nexport function isFactoryTriageType(value: unknown): value is FactoryTriageType {\n return typeof value === 'string' && FACTORY_TRIAGE_TYPES.some(type => type === value);\n}\n\nexport function isFactoryRuleStage(value: unknown): value is FactoryRuleStage {\n return typeof value === 'string' && FACTORY_RULE_STAGES.some(stage => stage === value);\n}\n\nexport function factoryRuleStage(stages: readonly string[]): FactoryRuleStage | undefined {\n const stage = stages.length === 1 ? stages[0] : undefined;\n return typeof stage === 'string' && stage.length > 0 ? stage : undefined;\n}\n\nexport function isTerminalFactoryRuleStage(stages: readonly string[]): boolean {\n const stage = factoryRuleStage(stages);\n return stage === 'done' || stage === 'canceled';\n}\n\n/** Working lanes hold cards with a seat engaged; Intake, Done and Canceled rest them. */\nexport function isWorkingFactoryRuleStage(stage: FactoryRuleStage): boolean {\n return stage !== 'intake' && !isTerminalFactoryRuleStage([stage]);\n}\n\n// Consulted only for the Intake exit: roles don't own lanes, so a card already\n// in a working or terminal lane stays put when a run starts.\nexport function factoryLaneForRole(role: string): FactoryRuleStage | undefined {\n return isFactoryRole(role) ? FACTORY_ROLE_STAGES[role] : undefined;\n}\n\nexport const FACTORY_RULE_BOARDS = ['work', 'review'] as const;\nexport type FactoryRuleBoard = (typeof FACTORY_RULE_BOARDS)[number] | (string & {});\n\nexport const FACTORY_RULE_SOURCES = ['issue', 'pullRequest', 'linearIssue', 'manual'] as const;\nexport type FactoryRuleSource = (typeof FACTORY_RULE_SOURCES)[number];\n\nexport const FACTORY_GITHUB_EVENTS = [\n 'issueOpened',\n 'issueEdited',\n 'issueClosed',\n 'issueCommentCreated',\n 'issueCommentEdited',\n 'issueCommentDeleted',\n 'pullRequestOpened',\n 'pullRequestUpdated',\n 'pullRequestCommentCreated',\n 'pullRequestReviewRequested',\n 'pullRequestReviewSubmitted',\n 'pullRequestMerged',\n 'pullRequestClosed',\n] as const;\nexport type FactoryGithubEventName = (typeof FACTORY_GITHUB_EVENTS)[number];\n\nexport const FACTORY_LINEAR_EVENTS = ['issueObserved', 'issueClosed'] as const;\nexport type FactoryLinearEventName = (typeof FACTORY_LINEAR_EVENTS)[number];\n\nexport type FactoryRuleJsonValue =\n | null\n | boolean\n | number\n | string\n | FactoryRuleJsonValue[]\n | { [key: string]: FactoryRuleJsonValue };\n\nexport interface FactoryRuleItemContext {\n id: string;\n source: WorkItemSource;\n sourceKey: string | null;\n parentWorkItemId: string | null;\n title: string;\n url: string | null;\n stages: readonly string[];\n acceptedAt: Date | null;\n /** Intake-stamped facts about the source — repository id, reporter login, labels. */\n metadata: Record<string, unknown> | null;\n}\n\nexport type FactoryRuleActor =\n | { type: 'human'; id: string }\n | { type: 'agent'; bindingId: string; role: string }\n | { type: 'github'; login: string; trusted: boolean; factoryAuthored: boolean }\n | { type: 'system'; id: string };\n\nexport interface FactoryRuleIngressIdentity {\n type: 'human' | 'agent' | 'toolResult' | 'github' | 'linear' | 'rule';\n id: string;\n}\n\nexport interface FactoryRuleCausalEntry {\n ingressId: string;\n decisionType: FactoryCommitDecision['type'];\n}\n\nexport interface FactoryRuleContextBase {\n tenant: { orgId: string; projectId: string };\n actor: FactoryRuleActor;\n ingress: FactoryRuleIngressIdentity;\n cause: string;\n causalChain: readonly FactoryRuleCausalEntry[];\n configVersion: string;\n}\n\nexport interface FactoryBoundRuleContext extends FactoryRuleContextBase {\n item: FactoryRuleItemContext;\n board: FactoryRuleBoard;\n itemRevision: number;\n}\n\nexport interface FactoryStageRuleContext extends FactoryBoundRuleContext {\n source: FactoryRuleSource;\n stage: FactoryRuleStage;\n fromStage: FactoryRuleStage;\n toStage: FactoryRuleStage;\n}\n\nexport interface FactoryToolResultRuleContext extends FactoryBoundRuleContext {\n toolName: string;\n threadId: string;\n assistantMessageId: string;\n toolCallId: string;\n result: {\n status: 'success' | 'error';\n value: FactoryRuleJsonValue;\n };\n}\n\nexport interface FactoryGithubRuleContext extends FactoryRuleContextBase {\n item?: FactoryRuleItemContext;\n board?: FactoryRuleBoard;\n itemRevision?: number;\n /**\n * Board an issue's labels route it to, when the project has a matching label route and that board\n * is installed. Absent for pull requests and for issues whose labels select nothing.\n */\n intake?: FactoryRuleIntakeTarget;\n event: FactoryGithubEventName;\n deliveryId: string;\n factory: { createdAt: string };\n repository: { id: number; fullName: string };\n issue?: {\n number: number;\n title: string;\n url: string;\n createdAt?: string;\n updatedAt?: string;\n assignees?: string[];\n labels?: string[];\n state?: 'open' | 'closed';\n /** GitHub close reason: `completed`, `not_planned`, or `duplicate`. */\n stateReason?: string;\n };\n issueChange?: { title: boolean; body: boolean };\n issueComment?: {\n id: number;\n body?: string;\n url?: string;\n author?: string;\n authorType?: string;\n createdAt?: string;\n updatedAt?: string;\n };\n pullRequest?: {\n number: number;\n title: string;\n url: string;\n createdAt?: string;\n state: 'open' | 'closed';\n draft: boolean;\n merged: boolean;\n assignees?: string[];\n requestedReviewers?: string[];\n labels?: string[];\n author?: string;\n factoryAuthored: boolean;\n headBranch: string;\n baseBranch: string;\n };\n /** Present on `pullRequestReviewRequested`: who review was (re-)requested from. */\n reviewRequest?: { reviewer: string; factoryReviewer: boolean };\n /** Present when a PR comment uses Factory's exact review command. */\n reviewCommand?: { command: 'review' | 're-review'; target: string };\n /** Present on `pullRequestReviewSubmitted`: the review that was just posted. */\n review?: { id: number; state: string; url: string };\n}\n\n/**\n * Where an intake source binding says new items from this source should land.\n * Absent when the source is unbound or bound without a board (built-in routing).\n */\nexport interface FactoryRuleIntakeTarget {\n board: string;\n initialPhase: string;\n}\n\nexport interface FactoryLinearRuleContext extends FactoryRuleContextBase {\n item?: FactoryRuleItemContext;\n board?: FactoryRuleBoard;\n itemRevision?: number;\n /** Bound board for the source this issue came from, when one is configured and installed. */\n intake?: FactoryRuleIntakeTarget;\n event: FactoryLinearEventName;\n issue: {\n id: string;\n identifier: string;\n title: string;\n url: string;\n state: string;\n stateType: string;\n priorityLabel: string;\n assignee: string | null;\n creator: string | null;\n team: string | null;\n labels: readonly string[];\n createdAt: string;\n updatedAt: string;\n };\n}\n\nexport type FactoryRuleHandler<TContext> = (\n context: Readonly<TContext>,\n) => FactoryRuleDecision | void | Promise<FactoryRuleDecision | void>;\n\nexport interface FactoryBoardRuleLeaf {\n onEnter?: FactoryRuleHandler<FactoryStageRuleContext>;\n onExit?: FactoryRuleHandler<FactoryStageRuleContext>;\n}\n\nexport type FactoryRuleRejectionCode =\n | 'forbidden'\n | 'invalid_transition'\n | 'missing_binding'\n | 'stale'\n | 'timeout'\n | 'rule_error'\n | 'causal_depth_exceeded'\n | 'repeated_transition'\n | 'approval_required';\n\nexport interface FactoryRuleRejectDecision {\n type: 'reject';\n code: FactoryRuleRejectionCode;\n reason: string;\n}\n\ninterface FactoryCommitDecisionBase {\n idempotencyKey: string;\n}\n\nexport interface FactoryTransitionDecision extends FactoryCommitDecisionBase {\n type: 'transition';\n board: FactoryRuleBoard;\n stage: FactoryRuleStage;\n /**\n * Delivered to the item's active session (waking it if idle) after the\n * transition commits. Skipped when the item has no active run binding, so\n * informational messages never fail the transition.\n */\n message?: { text: string; role?: string };\n /**\n * Runs the stage's entry rules even when the item is already in that stage.\n * A transition to the current stage is normally inert, because most callers\n * are correcting a board into a state it already holds. Re-entry is for the\n * opposite case: the stage's work is in flight and has been invalidated, so\n * it has to start over.\n */\n reenter?: boolean;\n}\n\nexport interface FactoryUpsertLinkedWorkItemDecision extends FactoryCommitDecisionBase {\n type: 'upsertLinkedWorkItem';\n board: FactoryRuleBoard;\n source: WorkItemSource;\n sourceKey: string;\n title: string;\n url: string | null;\n stage: FactoryRuleStage;\n metadata?: Record<string, FactoryRuleJsonValue>;\n}\n\ninterface FactoryInvokeSkillDecisionBase extends FactoryCommitDecisionBase {\n type: 'invokeSkill';\n role: string;\n arguments?: string;\n precedingMessage?: string;\n cancelInFlight?: boolean;\n}\n\n/**\n * Starting an agent run. Most runs activate a skill, because the skill carries\n * the handoff contract later rules match on. A run whose completion is already\n * signalled some other way — Building finishes by opening a pull request, which\n * arrives as its own event — needs no contract, so it can carry a plain prompt\n * instead of an otherwise empty skill.\n */\nexport type FactoryInvokeSkillDecision = FactoryInvokeSkillDecisionBase &\n ({ skillName: string; prompt?: never } | { prompt: string; skillName?: never });\n\nexport interface FactorySendMessageDecision extends FactoryCommitDecisionBase {\n type: 'sendMessage';\n /** Omitted: the card's live session, whichever seat holds it. Required with `prepareBinding`. */\n role?: string;\n message: string;\n priority?: 'medium' | 'high' | 'urgent';\n idleBehavior?: 'persist' | 'wake';\n prepareBinding?: boolean;\n}\n\nexport interface FactoryNotifyDecision extends FactoryCommitDecisionBase {\n type: 'notify';\n title: string;\n body?: string;\n level?: 'info' | 'warning' | 'error';\n}\n\nexport type FactoryCommitDecision =\n | FactoryTransitionDecision\n | FactoryUpsertLinkedWorkItemDecision\n | FactoryInvokeSkillDecision\n | FactorySendMessageDecision\n | FactoryNotifyDecision;\n\nexport type FactoryRuleDecision = FactoryRuleRejectDecision | FactoryCommitDecision;\n\nexport interface FactoryTransitionResultAccepted {\n status: 'accepted';\n transitionId: string;\n itemId: string;\n revision: number;\n stage: FactoryRuleStage;\n decisions: FactoryCommitDecision[];\n}\n\nexport interface FactoryTransitionResultRejected {\n status: 'rejected';\n transitionId: string;\n itemId: string;\n code: FactoryRuleRejectionCode;\n reason: string;\n}\n\nexport type FactoryTransitionResult = FactoryTransitionResultAccepted | FactoryTransitionResultRejected;\n\nexport function factoryRuleSourceForWorkItem(source: WorkItemSource): FactoryRuleSource {\n switch (source) {\n case 'github-issue':\n return 'issue';\n case 'github-pr':\n return 'pullRequest';\n case 'linear-issue':\n return 'linearIssue';\n case 'manual':\n return 'manual';\n }\n}\n"],"mappings":";;AAKA,MAAa,uBAAuB;AACpC,MAAa,qBAAqB;AAIlC,SAAgB,cAAc,MAIlB;CACV,MAAM,SAAS,KAAK,UAAU;CAC9B,IAAI,CAAC,MAAM,QAAQ,MAAM,GAAG,OAAO;CACnC,OACE,OAAO,MAAK,UAAS,OAAO,UAAU,YAAY,MAAM,YAAY,MAAA,wBAA0B,KAC9F,CAAC,KAAK,eACL,KAAK,UAAU,CAAC,QAAQ,EAAA,CAAG,OAAM,UAAS,UAAU,YAAY,UAAU,QAAQ;AAEvF;AAEA,SAAgB,eAAe,QAAuD;CACpF,IAAI,CAAC,QAAQ,OAAO;CACpB,IAAI,OAAO,kBAAkB,UAAU,OAAO;CAG9C,IAAI,OAAO,kBAAkB,UAAU,OAAO;CAC9C,OAAO,OAAO,SAAS,iBAAiB,cAAc;AACxD;AAIA,SAAgB,mBAAmB,MAA6E;CAC9G,IAAI,KAAK,WAAW,eAAe,KAAK,WAAW,gBAAgB,OAAO;CAC1E,IAAI,KAAK,UAAU,oBAAoB,MAAM,OAAO;CACpD,OAAO,KAAK,UAAU,kBAAkB;AAC1C;AAGA,SAAgB,oBAAoB,MAA6E;CAC/G,OAAO,mBAAmB,IAAI,KAAK,KAAK,UAAU,kBAAkB;AACtE;AAEA,SAAgB,2BAA2B,MAG/B;CACV,OAAO,mBAAmB;EAAE,QAAQ,eAAe,KAAK,cAAc;EAAG,UAAU,KAAK;CAAS,CAAC;AACpG;AAEA,MAAa,sBAAsB;CAAC;CAAU;CAAU;CAAY;CAAW;CAAU;CAAQ;AAAU;AAK3G,MAAa,sBAAsB;CACjC,QAAQ;CACR,MAAM;CACN,MAAM;CACN,QAAQ;AACV;AAGA,SAAgB,cAAc,OAAqC;CACjE,OAAO,SAAS;AAClB;AAEA,MAAa,uBAAuB;CAClC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,SAAgB,oBAAoB,OAA4C;CAC9E,OAAO,OAAO,UAAU,YAAY,qBAAqB,MAAK,SAAQ,SAAS,KAAK;AACtF;AAEA,SAAgB,mBAAmB,OAA2C;CAC5E,OAAO,OAAO,UAAU,YAAY,oBAAoB,MAAK,UAAS,UAAU,KAAK;AACvF;AAEA,SAAgB,iBAAiB,QAAyD;CACxF,MAAM,QAAQ,OAAO,WAAW,IAAI,OAAO,KAAK,KAAA;CAChD,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ,KAAA;AACjE;AAEA,SAAgB,2BAA2B,QAAoC;CAC7E,MAAM,QAAQ,iBAAiB,MAAM;CACrC,OAAO,UAAU,UAAU,UAAU;AACvC;;AAGA,SAAgB,0BAA0B,OAAkC;CAC1E,OAAO,UAAU,YAAY,CAAC,2BAA2B,CAAC,KAAK,CAAC;AAClE;AAIA,SAAgB,mBAAmB,MAA4C;CAC7E,OAAO,cAAc,IAAI,IAAI,oBAAoB,QAAQ,KAAA;AAC3D;AAEA,MAAa,sBAAsB,CAAC,QAAQ,QAAQ;AAGpD,MAAa,uBAAuB;CAAC;CAAS;CAAe;CAAe;AAAQ;AAGpF,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,wBAAwB,CAAC,iBAAiB,aAAa;AAiSpE,SAAgB,6BAA6B,QAA2C;CACtF,QAAQ,QAAR;EACE,KAAK,gBACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,gBACH,OAAO;EACT,KAAK,UACH,OAAO;CACX;AACF"}
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../src/rules/types.ts"],"sourcesContent":["import type { ExternalWorkItemSource } from '../storage/domains/work-items/base.js';\n\nexport type WorkItemSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'manual';\n\n/** The source label that holds an issue at rest until a maintainer decides; compared lowercased. */\nexport const NEEDS_APPROVAL_LABEL = 'status: needs approval';\nexport const AUTO_TRIAGED_LABEL = 'status: auto-triaged';\n\n// The label only holds a card at rest: once a person accepted it, or it sits in a working\n// lane only a person could have moved it into, the label is stale until the source catches up.\nexport function needsApproval(item: {\n metadata: Record<string, unknown> | null;\n stages?: readonly string[];\n acceptedAt?: Date | string | null;\n}): boolean {\n const labels = item.metadata?.labels;\n if (!Array.isArray(labels)) return false;\n return (\n labels.some(label => typeof label === 'string' && label.toLowerCase() === NEEDS_APPROVAL_LABEL) &&\n !item.acceptedAt &&\n (item.stages ?? ['intake']).every(stage => stage === 'intake' || stage === 'triage')\n );\n}\n\nexport function workItemSource(source: ExternalWorkItemSource | null): WorkItemSource {\n if (!source) return 'manual';\n if (source.integrationId === 'linear') return 'linear-issue';\n // Only GitHub and Linear have provider-specific rules; anything else (a Slack\n // thread, say) is a plain work item, not a mislabeled GitHub issue.\n if (source.integrationId !== 'github') return 'manual';\n return source.type === 'pull-request' ? 'github-pr' : 'github-issue';\n}\n\n// Authored outside the write-access circle: a missing trust stamp fails closed until\n// the reconcile sweep backfills it, and Factory's own PRs pass through `factoryAuthored`.\nexport function externallyAuthored(item: { source: string; metadata: Record<string, unknown> | null }): boolean {\n if (item.source !== 'github-pr' && item.source !== 'github-issue') return false;\n if (item.metadata?.factoryAuthored === true) return false;\n return item.metadata?.authorTrusted !== true;\n}\n\n// The board mark claims only what GitHub answered: a missing stamp is silence, not an outside contribution.\nexport function knownExternalAuthor(item: { source: string; metadata: Record<string, unknown> | null }): boolean {\n return externallyAuthored(item) && item.metadata?.authorTrusted === false;\n}\n\nexport function externallyAuthoredWorkItem(item: {\n externalSource: ExternalWorkItemSource | null;\n metadata: Record<string, unknown> | null;\n}): boolean {\n return externallyAuthored({ source: workItemSource(item.externalSource), metadata: item.metadata });\n}\n\nexport const FACTORY_RULE_STAGES = ['intake', 'triage', 'planning', 'execute', 'review', 'done', 'canceled'] as const;\nexport type FactoryRuleStage = (typeof FACTORY_RULE_STAGES)[number] | (string & {});\n\n// Each role and the working stage its run holds the card in. Key order is the\n// seat pipeline order — Resume depth derives from it.\nexport const FACTORY_ROLE_STAGES = {\n triage: 'triage',\n plan: 'planning',\n work: 'execute',\n review: 'review',\n} as const satisfies Record<string, FactoryRuleStage>;\nexport type FactoryRole = keyof typeof FACTORY_ROLE_STAGES;\n\nexport function isFactoryRole(value: string): value is FactoryRole {\n return value in FACTORY_ROLE_STAGES;\n}\n\nexport const FACTORY_TRIAGE_TYPES = [\n 'bug',\n 'feature request',\n 'docs',\n 'question/support',\n 'maintenance',\n 'duplicate',\n 'resolved',\n 'invalid',\n 'spam',\n 'out-of-scope',\n 'other',\n] as const;\nexport type FactoryTriageType = (typeof FACTORY_TRIAGE_TYPES)[number];\n\nexport function isFactoryTriageType(value: unknown): value is FactoryTriageType {\n return typeof value === 'string' && FACTORY_TRIAGE_TYPES.some(type => type === value);\n}\n\nexport function isFactoryRuleStage(value: unknown): value is FactoryRuleStage {\n return typeof value === 'string' && FACTORY_RULE_STAGES.some(stage => stage === value);\n}\n\nexport function factoryRuleStage(stages: readonly string[]): FactoryRuleStage | undefined {\n const stage = stages.length === 1 ? stages[0] : undefined;\n return typeof stage === 'string' && stage.length > 0 ? stage : undefined;\n}\n\nexport function isTerminalFactoryRuleStage(stages: readonly string[]): boolean {\n const stage = factoryRuleStage(stages);\n return stage === 'done' || stage === 'canceled';\n}\n\n/** Working lanes hold cards with a seat engaged; Intake, Done and Canceled rest them. */\nexport function isWorkingFactoryRuleStage(stage: FactoryRuleStage): boolean {\n return stage !== 'intake' && !isTerminalFactoryRuleStage([stage]);\n}\n\n// Consulted only for the Intake exit: roles don't own lanes, so a card already\n// in a working or terminal lane stays put when a run starts.\nexport function factoryLaneForRole(role: string): FactoryRuleStage | undefined {\n return isFactoryRole(role) ? FACTORY_ROLE_STAGES[role] : undefined;\n}\n\nexport const FACTORY_RULE_BOARDS = ['work', 'review'] as const;\nexport type FactoryRuleBoard = (typeof FACTORY_RULE_BOARDS)[number] | (string & {});\n\nexport const FACTORY_RULE_SOURCES = ['issue', 'pullRequest', 'linearIssue', 'manual'] as const;\nexport type FactoryRuleSource = (typeof FACTORY_RULE_SOURCES)[number];\n\nexport const FACTORY_GITHUB_EVENTS = [\n 'issueOpened',\n 'issueEdited',\n 'issueClosed',\n 'issueCommentCreated',\n 'issueCommentEdited',\n 'issueCommentDeleted',\n 'pullRequestOpened',\n 'pullRequestUpdated',\n 'pullRequestCommentCreated',\n 'pullRequestReviewRequested',\n 'pullRequestReviewSubmitted',\n 'pullRequestMerged',\n 'pullRequestClosed',\n] as const;\nexport type FactoryGithubEventName = (typeof FACTORY_GITHUB_EVENTS)[number];\n\nexport const FACTORY_LINEAR_EVENTS = ['issueObserved', 'issueClosed'] as const;\nexport type FactoryLinearEventName = (typeof FACTORY_LINEAR_EVENTS)[number];\n\nexport type FactoryRuleJsonValue =\n | null\n | boolean\n | number\n | string\n | FactoryRuleJsonValue[]\n | { [key: string]: FactoryRuleJsonValue };\n\nexport interface FactoryRuleItemContext {\n id: string;\n source: WorkItemSource;\n sourceKey: string | null;\n parentWorkItemId: string | null;\n title: string;\n url: string | null;\n stages: readonly string[];\n acceptedAt: Date | null;\n /** Intake-stamped facts about the source — repository id, reporter login, labels. */\n metadata: Record<string, unknown> | null;\n}\n\nexport type FactoryRuleActor =\n | { type: 'human'; id: string }\n | { type: 'agent'; bindingId: string; role: string }\n | { type: 'github'; login: string; trusted: boolean; factoryAuthored: boolean }\n | { type: 'system'; id: string };\n\nexport interface FactoryRuleIngressIdentity {\n type: 'human' | 'agent' | 'toolResult' | 'github' | 'linear' | 'rule';\n id: string;\n}\n\nexport interface FactoryRuleCausalEntry {\n ingressId: string;\n decisionType: FactoryCommitDecision['type'];\n}\n\nexport interface FactoryRuleContextBase {\n tenant: { orgId: string; projectId: string };\n actor: FactoryRuleActor;\n ingress: FactoryRuleIngressIdentity;\n cause: string;\n causalChain: readonly FactoryRuleCausalEntry[];\n configVersion: string;\n}\n\nexport interface FactoryBoundRuleContext extends FactoryRuleContextBase {\n item: FactoryRuleItemContext;\n board: FactoryRuleBoard;\n itemRevision: number;\n}\n\nexport interface FactoryStageRuleContext extends FactoryBoundRuleContext {\n source: FactoryRuleSource;\n stage: FactoryRuleStage;\n fromStage: FactoryRuleStage;\n toStage: FactoryRuleStage;\n}\n\nexport interface FactoryToolResultRuleContext extends FactoryBoundRuleContext {\n toolName: string;\n threadId: string;\n assistantMessageId: string;\n toolCallId: string;\n result: {\n status: 'success' | 'error';\n value: FactoryRuleJsonValue;\n };\n}\n\nexport interface FactoryGithubRuleContext extends FactoryRuleContextBase {\n item?: FactoryRuleItemContext;\n board?: FactoryRuleBoard;\n itemRevision?: number;\n /**\n * Board an issue's labels route it to, when the project has a matching label route and that board\n * is installed. Absent for pull requests and for issues whose labels select nothing.\n */\n intake?: FactoryRuleIntakeTarget;\n event: FactoryGithubEventName;\n deliveryId: string;\n factory: { createdAt: string };\n repository: { id: number; fullName: string };\n issue?: {\n number: number;\n title: string;\n url: string;\n createdAt?: string;\n updatedAt?: string;\n assignees?: string[];\n labels?: string[];\n state?: 'open' | 'closed';\n /** GitHub close reason: `completed`, `not_planned`, or `duplicate`. */\n stateReason?: string;\n };\n issueChange?: { title: boolean; body: boolean };\n issueComment?: {\n id: number;\n body?: string;\n url?: string;\n author?: string;\n authorType?: string;\n createdAt?: string;\n updatedAt?: string;\n };\n pullRequest?: {\n number: number;\n title: string;\n url: string;\n createdAt?: string;\n state: 'open' | 'closed';\n draft: boolean;\n merged: boolean;\n assignees?: string[];\n requestedReviewers?: string[];\n labels?: string[];\n author?: string;\n factoryAuthored: boolean;\n headBranch: string;\n baseBranch: string;\n };\n /** Present on `pullRequestReviewRequested`: who review was (re-)requested from. */\n reviewRequest?: { reviewer: string; factoryReviewer: boolean };\n /** Present when a PR comment uses Factory's exact review command. */\n reviewCommand?: { command: 'review' | 're-review'; target: string };\n /** Present on `pullRequestReviewSubmitted`: the review that was just posted. */\n review?: { id: number; state: string; url: string };\n}\n\n/**\n * Where an intake source binding says new items from this source should land.\n * Absent when the source is unbound or bound without a board (built-in routing).\n */\nexport interface FactoryRuleIntakeTarget {\n board: string;\n initialPhase: string;\n}\n\nexport interface FactoryLinearRuleContext extends FactoryRuleContextBase {\n item?: FactoryRuleItemContext;\n board?: FactoryRuleBoard;\n itemRevision?: number;\n /** Bound board for the source this issue came from, when one is configured and installed. */\n intake?: FactoryRuleIntakeTarget;\n event: FactoryLinearEventName;\n issue: {\n id: string;\n identifier: string;\n title: string;\n url: string;\n state: string;\n stateType: string;\n priorityLabel: string;\n assignee: string | null;\n creator: string | null;\n team: string | null;\n labels: readonly string[];\n createdAt: string;\n updatedAt: string;\n };\n}\n\nexport type FactoryRuleHandler<TContext> = (\n context: Readonly<TContext>,\n) => FactoryRuleDecision | void | Promise<FactoryRuleDecision | void>;\n\nexport interface FactoryBoardRuleLeaf {\n onEnter?: FactoryRuleHandler<FactoryStageRuleContext>;\n onExit?: FactoryRuleHandler<FactoryStageRuleContext>;\n}\n\nexport type FactoryRuleRejectionCode =\n | 'forbidden'\n | 'invalid_transition'\n | 'missing_binding'\n | 'stale'\n | 'timeout'\n | 'rule_error'\n | 'causal_depth_exceeded'\n | 'repeated_transition'\n | 'approval_required';\n\nexport interface FactoryRuleRejectDecision {\n type: 'reject';\n code: FactoryRuleRejectionCode;\n reason: string;\n}\n\ninterface FactoryCommitDecisionBase {\n idempotencyKey: string;\n}\n\nexport interface FactoryTransitionDecision extends FactoryCommitDecisionBase {\n type: 'transition';\n board: FactoryRuleBoard;\n stage: FactoryRuleStage;\n /**\n * Delivered to the item's active session (waking it if idle) after the\n * transition commits. Skipped when the item has no active run binding, so\n * informational messages never fail the transition.\n */\n message?: { text: string; role?: string };\n /**\n * Runs the stage's entry rules even when the item is already in that stage.\n * A transition to the current stage is normally inert, because most callers\n * are correcting a board into a state it already holds. Re-entry is for the\n * opposite case: the stage's work is in flight and has been invalidated, so\n * it has to start over.\n */\n reenter?: boolean;\n}\n\nexport interface FactoryUpsertLinkedWorkItemDecision extends FactoryCommitDecisionBase {\n type: 'upsertLinkedWorkItem';\n board: FactoryRuleBoard;\n source: WorkItemSource;\n sourceKey: string;\n /**\n * Org-wide ownership key for the external record, when one Factory at a time\n * may hold a live card for it (a stable Linear issue id, for instance). The\n * store enforces it with a unique index, so a second project's materialization\n * is refused rather than duplicated.\n */\n claimKey?: string;\n title: string;\n url: string | null;\n stage: FactoryRuleStage;\n metadata?: Record<string, FactoryRuleJsonValue>;\n}\n\ninterface FactoryInvokeSkillDecisionBase extends FactoryCommitDecisionBase {\n type: 'invokeSkill';\n role: string;\n arguments?: string;\n precedingMessage?: string;\n cancelInFlight?: boolean;\n}\n\n/**\n * Starting an agent run. Most runs activate a skill, because the skill carries\n * the handoff contract later rules match on. A run whose completion is already\n * signalled some other way — Building finishes by opening a pull request, which\n * arrives as its own event — needs no contract, so it can carry a plain prompt\n * instead of an otherwise empty skill.\n */\nexport type FactoryInvokeSkillDecision = FactoryInvokeSkillDecisionBase &\n (\n | {\n skillName: string;\n prompt?: never;\n /**\n * Same-stage re-entry: the skill is already active in the card's live session,\n * so deliver a compact continuation that references it by name and carries only\n * the fresh arguments, instead of re-pasting the whole skill document. Only valid\n * for named-skill decisions — a plain prompt run has no active skill to resume.\n */\n resume?: boolean;\n }\n | { prompt: string; skillName?: never; resume?: never }\n );\n\nexport interface FactorySendMessageDecision extends FactoryCommitDecisionBase {\n type: 'sendMessage';\n /** Omitted: the card's live session, whichever seat holds it. Required with `prepareBinding`. */\n role?: string;\n message: string;\n priority?: 'medium' | 'high' | 'urgent';\n idleBehavior?: 'persist' | 'wake';\n prepareBinding?: boolean;\n}\n\nexport interface FactoryNotifyDecision extends FactoryCommitDecisionBase {\n type: 'notify';\n title: string;\n body?: string;\n level?: 'info' | 'warning' | 'error';\n}\n\nexport type FactoryCommitDecision =\n | FactoryTransitionDecision\n | FactoryUpsertLinkedWorkItemDecision\n | FactoryInvokeSkillDecision\n | FactorySendMessageDecision\n | FactoryNotifyDecision;\n\nexport type FactoryRuleDecision = FactoryRuleRejectDecision | FactoryCommitDecision;\n\nexport interface FactoryTransitionResultAccepted {\n status: 'accepted';\n transitionId: string;\n itemId: string;\n revision: number;\n stage: FactoryRuleStage;\n decisions: FactoryCommitDecision[];\n}\n\nexport interface FactoryTransitionResultRejected {\n status: 'rejected';\n transitionId: string;\n itemId: string;\n code: FactoryRuleRejectionCode;\n reason: string;\n}\n\nexport type FactoryTransitionResult = FactoryTransitionResultAccepted | FactoryTransitionResultRejected;\n\nexport function factoryRuleSourceForWorkItem(source: WorkItemSource): FactoryRuleSource {\n switch (source) {\n case 'github-issue':\n return 'issue';\n case 'github-pr':\n return 'pullRequest';\n case 'linear-issue':\n return 'linearIssue';\n case 'manual':\n return 'manual';\n }\n}\n"],"mappings":";;AAKA,MAAa,uBAAuB;AACpC,MAAa,qBAAqB;AAIlC,SAAgB,cAAc,MAIlB;CACV,MAAM,SAAS,KAAK,UAAU;CAC9B,IAAI,CAAC,MAAM,QAAQ,MAAM,GAAG,OAAO;CACnC,OACE,OAAO,MAAK,UAAS,OAAO,UAAU,YAAY,MAAM,YAAY,MAAA,wBAA0B,KAC9F,CAAC,KAAK,eACL,KAAK,UAAU,CAAC,QAAQ,EAAA,CAAG,OAAM,UAAS,UAAU,YAAY,UAAU,QAAQ;AAEvF;AAEA,SAAgB,eAAe,QAAuD;CACpF,IAAI,CAAC,QAAQ,OAAO;CACpB,IAAI,OAAO,kBAAkB,UAAU,OAAO;CAG9C,IAAI,OAAO,kBAAkB,UAAU,OAAO;CAC9C,OAAO,OAAO,SAAS,iBAAiB,cAAc;AACxD;AAIA,SAAgB,mBAAmB,MAA6E;CAC9G,IAAI,KAAK,WAAW,eAAe,KAAK,WAAW,gBAAgB,OAAO;CAC1E,IAAI,KAAK,UAAU,oBAAoB,MAAM,OAAO;CACpD,OAAO,KAAK,UAAU,kBAAkB;AAC1C;AAGA,SAAgB,oBAAoB,MAA6E;CAC/G,OAAO,mBAAmB,IAAI,KAAK,KAAK,UAAU,kBAAkB;AACtE;AAEA,SAAgB,2BAA2B,MAG/B;CACV,OAAO,mBAAmB;EAAE,QAAQ,eAAe,KAAK,cAAc;EAAG,UAAU,KAAK;CAAS,CAAC;AACpG;AAEA,MAAa,sBAAsB;CAAC;CAAU;CAAU;CAAY;CAAW;CAAU;CAAQ;AAAU;AAK3G,MAAa,sBAAsB;CACjC,QAAQ;CACR,MAAM;CACN,MAAM;CACN,QAAQ;AACV;AAGA,SAAgB,cAAc,OAAqC;CACjE,OAAO,SAAS;AAClB;AAEA,MAAa,uBAAuB;CAClC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,SAAgB,oBAAoB,OAA4C;CAC9E,OAAO,OAAO,UAAU,YAAY,qBAAqB,MAAK,SAAQ,SAAS,KAAK;AACtF;AAEA,SAAgB,mBAAmB,OAA2C;CAC5E,OAAO,OAAO,UAAU,YAAY,oBAAoB,MAAK,UAAS,UAAU,KAAK;AACvF;AAEA,SAAgB,iBAAiB,QAAyD;CACxF,MAAM,QAAQ,OAAO,WAAW,IAAI,OAAO,KAAK,KAAA;CAChD,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ,KAAA;AACjE;AAEA,SAAgB,2BAA2B,QAAoC;CAC7E,MAAM,QAAQ,iBAAiB,MAAM;CACrC,OAAO,UAAU,UAAU,UAAU;AACvC;;AAGA,SAAgB,0BAA0B,OAAkC;CAC1E,OAAO,UAAU,YAAY,CAAC,2BAA2B,CAAC,KAAK,CAAC;AAClE;AAIA,SAAgB,mBAAmB,MAA4C;CAC7E,OAAO,cAAc,IAAI,IAAI,oBAAoB,QAAQ,KAAA;AAC3D;AAEA,MAAa,sBAAsB,CAAC,QAAQ,QAAQ;AAGpD,MAAa,uBAAuB;CAAC;CAAS;CAAe;CAAe;AAAQ;AAGpF,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,wBAAwB,CAAC,iBAAiB,aAAa;AAqTpE,SAAgB,6BAA6B,QAA2C;CACtF,QAAQ,QAAR;EACE,KAAK,gBACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,gBACH,OAAO;EACT,KAAK,UACH,OAAO;CACX;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/rules/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAQ/C,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAQxC,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,aAAa,QAA2B,CAAC;AACtD,eAAO,MAAM,mBAAmB,QAAgB,CAAC;AAejD,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,0BAA0B;gBAE3B,OAAO,EAAE,MAAM;CAI5B;AAwBD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEjE;AASD,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,EACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,IAAI,CAUN;AAcD,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,EACd,KAAK,SAAI,EACT,IAAI,cAAoB,GACvB,oBAAoB,CAkCtB;AAYD,eAAO,MAAM,8BAA8B,sBAAsB,CAAC;AAElE,mGAAmG;AACnG,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjE;AAQD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,SAAI,GAAG,mBAAmB,
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/rules/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAQ/C,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAQxC,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,aAAa,QAA2B,CAAC;AACtD,eAAO,MAAM,mBAAmB,QAAgB,CAAC;AAejD,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,0BAA0B;gBAE3B,OAAO,EAAE,MAAM;CAI5B;AAwBD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEjE;AASD,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,aAAa,EACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,IAAI,CAUN;AAcD,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,EACd,KAAK,SAAI,EACT,IAAI,cAAoB,GACvB,oBAAoB,CAkCtB;AAYD,eAAO,MAAM,8BAA8B,sBAAsB,CAAC;AAElE,mGAAmG;AACnG,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjE;AAQD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,SAAI,GAAG,mBAAmB,CAyLhG;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,EAAE,WAAW,SAAI,GAAG,qBAAqB,EAAE,CAiBjH"}
|