@mastra/factory 0.26.0-alpha.0 → 0.26.0-alpha.1
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/README.md +158 -57
- package/dist/auth.d.ts.map +1 -1
- package/dist/boards/card-facts.d.ts +5 -0
- package/dist/boards/card-facts.d.ts.map +1 -0
- package/dist/boards/card-facts.js +19 -0
- package/dist/boards/card-facts.js.map +1 -0
- package/dist/boards/define-board.d.ts +109 -13
- package/dist/boards/define-board.d.ts.map +1 -1
- package/dist/boards/define-board.js +163 -21
- package/dist/boards/define-board.js.map +1 -1
- package/dist/boards/index.d.ts +4 -3
- package/dist/boards/index.d.ts.map +1 -1
- package/dist/boards/index.js +3 -2
- package/dist/boards/index.js.map +1 -1
- package/dist/boards/legacy-plan-role.d.ts +14 -0
- package/dist/boards/legacy-plan-role.d.ts.map +1 -0
- package/dist/boards/legacy-plan-role.js +32 -0
- package/dist/boards/legacy-plan-role.js.map +1 -0
- package/dist/boards/phase-automation.d.ts +13 -0
- package/dist/boards/phase-automation.d.ts.map +1 -0
- package/dist/boards/phase-automation.js +25 -0
- package/dist/boards/phase-automation.js.map +1 -0
- package/dist/boards/phase-runner.d.ts +13 -0
- package/dist/boards/phase-runner.d.ts.map +1 -0
- package/dist/boards/phase-runner.js +44 -0
- package/dist/boards/phase-runner.js.map +1 -0
- package/dist/boards/relocate.d.ts.map +1 -1
- package/dist/boards/relocate.js +2 -0
- package/dist/boards/relocate.js.map +1 -1
- package/dist/boards/review.d.ts +1 -1
- package/dist/boards/review.d.ts.map +1 -1
- package/dist/boards/review.js +18 -18
- package/dist/boards/review.js.map +1 -1
- package/dist/boards/semantics.d.ts.map +1 -1
- package/dist/boards/semantics.js +11 -7
- package/dist/boards/semantics.js.map +1 -1
- package/dist/boards/transition-policy.d.ts +10 -10
- package/dist/boards/work-tool-rules.d.ts +3 -3
- package/dist/boards/work-tool-rules.d.ts.map +1 -1
- package/dist/boards/work-tool-rules.js +1 -1
- package/dist/boards/work-tool-rules.js.map +1 -1
- package/dist/boards/work.d.ts +3 -3
- package/dist/boards/work.d.ts.map +1 -1
- package/dist/boards/work.js +31 -29
- package/dist/boards/work.js.map +1 -1
- package/dist/environment/build-runner.d.ts +4 -4
- package/dist/environment/build-runner.d.ts.map +1 -1
- package/dist/environment/build-workflow.d.ts +6 -6
- package/dist/environment/build-workflow.js +1 -1
- package/dist/environment/build.d.ts +1 -1
- package/dist/environment/build.d.ts.map +1 -1
- package/dist/factory.d.ts +8 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +6 -0
- package/dist/factory.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/integrations/github/app-identity.d.ts.map +1 -1
- package/dist/integrations/github/default-rules.d.ts +71 -71
- package/dist/integrations/github/default-rules.d.ts.map +1 -1
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/reconcile-worker.d.ts.map +1 -1
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/sandbox.d.ts.map +1 -1
- package/dist/integrations/gitlab/api.d.ts.map +1 -1
- package/dist/integrations/gitlab/default-rules.d.ts +38 -38
- package/dist/integrations/gitlab/default-rules.d.ts.map +1 -1
- package/dist/integrations/gitlab/integration.d.ts.map +1 -1
- package/dist/integrations/gitlab/rules.d.ts.map +1 -1
- package/dist/integrations/incidentio/api.d.ts.map +1 -1
- package/dist/integrations/incidentio/default-rules.d.ts +3 -3
- package/dist/integrations/incidentio/default-rules.d.ts.map +1 -1
- package/dist/integrations/incidentio/integration.d.ts.map +1 -1
- package/dist/integrations/incidentio/rules.d.ts.map +1 -1
- package/dist/integrations/issue-reconcile-worker.d.ts.map +1 -1
- package/dist/integrations/jira/api.d.ts +1 -1
- package/dist/integrations/jira/api.d.ts.map +1 -1
- package/dist/integrations/jira/default-rules.d.ts +3 -3
- package/dist/integrations/jira/default-rules.d.ts.map +1 -1
- package/dist/integrations/jira/integration.d.ts.map +1 -1
- package/dist/integrations/jira/rules.d.ts.map +1 -1
- package/dist/integrations/linear/default-rules.d.ts +8 -8
- package/dist/integrations/linear/default-rules.d.ts.map +1 -1
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/rules.d.ts.map +1 -1
- package/dist/integrations/platform/api-client.d.ts.map +1 -1
- package/dist/integrations/platform/github/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/gitlab/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/gitlab/integration.d.ts.map +1 -1
- package/dist/integrations/platform/incidentio/integration.d.ts.map +1 -1
- package/dist/integrations/platform/jira/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/slack/channel-reply-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.d.ts.map +1 -1
- package/dist/integrations/slack/feed-publisher.d.ts.map +1 -1
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/reply-reminder-processor.d.ts.map +1 -1
- package/dist/integrations/slack/reply-tool.d.ts.map +1 -1
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/workos/integration.d.ts.map +1 -1
- package/dist/mcp/events.d.ts +3 -3
- package/dist/mcp/routes.js +1 -1
- package/dist/routes/attention-activity.d.ts +1 -1
- package/dist/routes/attention-activity.d.ts.map +1 -1
- package/dist/routes/attention-parked.d.ts +1 -1
- package/dist/routes/attention-parked.d.ts.map +1 -1
- package/dist/routes/attention-providers.d.ts +1 -1
- package/dist/routes/attention-providers.d.ts.map +1 -1
- package/dist/routes/automation-runs.d.ts.map +1 -1
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/contracts.d.ts +159 -136
- package/dist/routes/contracts.d.ts.map +1 -1
- package/dist/routes/contracts.js +23 -0
- package/dist/routes/contracts.js.map +1 -1
- package/dist/routes/fs.d.ts.map +1 -1
- package/dist/routes/fs.js +24 -0
- package/dist/routes/fs.js.map +1 -1
- package/dist/routes/intake.d.ts.map +1 -1
- package/dist/routes/knowledge.d.ts.map +1 -1
- package/dist/routes/oauth.d.ts.map +1 -1
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/route.d.ts.map +1 -1
- package/dist/routes/skills.d.ts +3 -0
- package/dist/routes/skills.d.ts.map +1 -1
- package/dist/routes/skills.js +1 -1
- package/dist/routes/skills.js.map +1 -1
- package/dist/routes/surface.d.ts +3 -0
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +23 -22
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/telemetry.d.ts.map +1 -1
- package/dist/routes/tenant-credentials.d.ts.map +1 -1
- package/dist/routes/work-items.d.ts.map +1 -1
- package/dist/routes/work-items.js +19 -3
- package/dist/routes/work-items.js.map +1 -1
- package/dist/rules/decision-applicability.d.ts.map +1 -1
- package/dist/rules/decision-applicability.js +3 -1
- package/dist/rules/decision-applicability.js.map +1 -1
- package/dist/rules/dispatch-errors.d.ts.map +1 -1
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +17 -3
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/processor.d.ts.map +1 -1
- package/dist/rules/processor.js +4 -2
- package/dist/rules/processor.js.map +1 -1
- package/dist/rules/rule-group.d.ts +29 -0
- package/dist/rules/rule-group.d.ts.map +1 -0
- package/dist/rules/rule-group.js +141 -0
- package/dist/rules/rule-group.js.map +1 -0
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/terminal-cleanup.d.ts.map +1 -1
- package/dist/rules/tools.d.ts +1 -1
- package/dist/rules/tools.d.ts.map +1 -1
- package/dist/rules/transition-service.d.ts.map +1 -1
- package/dist/rules/transition-service.js +5 -3
- package/dist/rules/transition-service.js.map +1 -1
- package/dist/rules/types.d.ts +25 -14
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.d.ts +2 -0
- package/dist/rules/validation.d.ts.map +1 -1
- package/dist/rules/validation.js +6 -3
- package/dist/rules/validation.js.map +1 -1
- package/dist/sandbox/callback-factory-sandbox.d.ts.map +1 -1
- package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -1
- package/dist/sandbox/session-retirement.d.ts.map +1 -1
- package/dist/session/environment-state-processor.d.ts.map +1 -1
- package/dist/session/factory-session.d.ts.map +1 -1
- package/dist/session/live-sessions.d.ts.map +1 -1
- package/dist/session/reply-credential-processor.d.ts.map +1 -1
- package/dist/session/run-audit.d.ts +1 -1
- package/dist/session/run-audit.d.ts.map +1 -1
- package/dist/skills/app-skills.d.ts +11 -0
- package/dist/skills/app-skills.d.ts.map +1 -0
- package/dist/skills/app-skills.js +37 -0
- package/dist/skills/app-skills.js.map +1 -0
- package/dist/skills/catalog.d.ts +9 -3
- package/dist/skills/catalog.d.ts.map +1 -1
- package/dist/skills/catalog.js +35 -19
- package/dist/skills/catalog.js.map +1 -1
- package/dist/skills/service.d.ts.map +1 -1
- package/dist/spa-static.d.ts.map +1 -1
- package/dist/storage/domains/audit/actions.d.ts +6 -6
- package/dist/storage/domains/audit/actions.d.ts.map +1 -1
- package/dist/storage/domains/audit/actors.d.ts +1 -1
- package/dist/storage/domains/audit/actors.d.ts.map +1 -1
- package/dist/storage/domains/audit/base.d.ts.map +1 -1
- package/dist/storage/domains/audit/domain.d.ts.map +1 -1
- package/dist/storage/domains/channel-identity/base.d.ts.map +1 -1
- package/dist/storage/domains/comments/base.d.ts.map +1 -1
- package/dist/storage/domains/comments/domain.d.ts.map +1 -1
- package/dist/storage/domains/comments/feed-context.d.ts.map +1 -1
- package/dist/storage/domains/credentials/base.d.ts.map +1 -1
- package/dist/storage/domains/custom-providers/base.d.ts.map +1 -1
- package/dist/storage/domains/filesystem/base.d.ts.map +1 -1
- package/dist/storage/domains/intake/base.d.ts.map +1 -1
- package/dist/storage/domains/integrations/base.d.ts.map +1 -1
- package/dist/storage/domains/memory-settings/base.d.ts.map +1 -1
- package/dist/storage/domains/model-defaults/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.d.ts +1 -1
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/queue-health/base.d.ts.map +1 -1
- package/dist/storage/domains/source-control/base.d.ts.map +1 -1
- package/dist/storage/domains/source-control/inmemory.d.ts +5 -5
- package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +1 -1
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/board-version.d.ts.map +1 -1
- package/dist/telemetry-types.d.ts +1 -1
- package/dist/telemetry-types.d.ts.map +1 -1
- package/dist/timing.d.ts.map +1 -1
- package/dist/tools/session-tools.d.ts.map +1 -1
- package/dist/tools/session-tools.js +3 -1
- package/dist/tools/session-tools.js.map +1 -1
- package/dist/tools/sessions-state-processor.d.ts.map +1 -1
- package/dist/tools/work-item-tools.js +1 -1
- package/dist/workspace.d.ts +13 -6
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +66 -14
- package/dist/workspace.js.map +1 -1
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processor.js","names":[],"sources":["../../src/rules/processor.ts"],"sourcesContent":["import { resolveRequestThinkingLevel } from '@mastra/code-sdk/agents/model';\nimport type { ThinkingLevel } from '@mastra/code-sdk/providers/openai-codex';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { MastraDBMessage, MessageList } from '@mastra/core/agent/message-list';\nimport type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type {\n ComputeStateSignalArgs,\n ComputeStateSignalResult,\n ProcessInputArgs,\n ProcessInputStepArgs,\n Processor,\n} from '@mastra/core/processors';\n\nimport { boardForWorkItem, resolveBoardToolRule, workItemPhaseSemantics } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { FactoryRunBindingRecord, WorkItemsStorage, WorkItemRow } from '../storage/domains/work-items/base.js';\nimport { findSessionRunBinding, getFactorySessionCoordinates } from './binding-context.js';\nimport type { FactoryTransitionService } from './transition-service.js';\nimport { workItemSource } from './types.js';\nimport type {\n FactoryCommitDecision,\n FactoryRuleDecision,\n FactoryRuleJsonValue,\n FactoryRuleStage,\n FactoryToolResultRuleContext,\n} from './types.js';\nimport {\n assertFactoryDecisionTarget,\n normalizeFactoryRuleJsonValue,\n validateFactoryRuleDecisions,\n} from './validation.js';\n\nconst STATE_ID = 'factory-phase';\nconst RULE_TIMEOUT_MS = 5_000;\nconst TRANSCRIPT_PAGE_SIZE = 50;\nconst MAX_LINKED_ITEMS = 5;\nfunction ruleStage(boards: BoardRegistry, item: WorkItemRow | null | undefined): string | undefined {\n return item && workItemPhaseSemantics(boards, item) ? item.stages[0] : undefined;\n}\n\nfunction itemInRuleStage(boards: BoardRegistry, item: WorkItemRow | null | undefined): item is WorkItemRow {\n return ruleStage(boards, item) !== undefined;\n}\n\ntype PersistedMessageReader = {\n listMessages(input: {\n threadId: string;\n resourceId?: string;\n page: number;\n perPage: number;\n filter?: { dateRange?: { start?: Date } };\n orderBy: { field: 'createdAt'; direction: 'ASC' };\n }): Promise<{ messages: MastraDBMessage[]; hasMore: boolean }>;\n};\n\ntype CompletedToolResult = {\n assistantMessageId: string;\n messageCreatedAt: Date;\n toolCallId: string;\n toolName: string;\n input: FactoryRuleJsonValue;\n status: 'success' | 'error';\n value: FactoryRuleJsonValue;\n};\n\nfunction isApprovedPlanResult(result: CompletedToolResult): boolean {\n if (result.toolName !== 'submit_plan' || result.status !== 'success') return false;\n if (typeof result.value === 'string') return result.value.startsWith('Plan approved.');\n if (!result.value || typeof result.value !== 'object' || Array.isArray(result.value)) return false;\n const content = result.value.content;\n return typeof content === 'string' && content.startsWith('Plan approved.');\n}\n\ntype RuntimeSnapshot = {\n modelId: string;\n thinkingLevel: ThinkingLevel;\n};\n\ntype ActivePhaseSnapshotBase = {\n bindingId: string;\n itemId: string;\n revision: number;\n stage: FactoryRuleStage;\n role: string;\n configVersion: string;\n status: 'active';\n};\n\ntype ActivePhaseSnapshotValue = ActivePhaseSnapshotBase & {\n board: string;\n modelId?: string;\n thinkingLevel?: ThinkingLevel;\n};\n\ntype PhaseSnapshotValue = ActivePhaseSnapshotValue | { bindingId?: string; status: 'none' };\n\nfunction reviewRuntimeFromRequestContext(\n requestContext: ComputeStateSignalArgs['requestContext'],\n defaultThinkingLevel: ThinkingLevel | undefined,\n): RuntimeSnapshot {\n if (!requestContext || typeof requestContext.get !== 'function') {\n throw new Error('Factory review phase requires a controller request context.');\n }\n const context = requestContext.get<'controller', AgentControllerRequestContext<MastraCodeState>>('controller');\n const modelId = context?.session?.modelId.trim();\n if (!modelId) {\n throw new Error('Factory review phase requires a selected session model.');\n }\n return {\n modelId,\n thinkingLevel: resolveRequestThinkingLevel({ state: context?.state }, undefined, defaultThinkingLevel),\n };\n}\n\nfunction workItemSourceKey(item: WorkItemRow): string | null {\n const source = item.externalSource;\n return source ? `${source.integrationId}:${source.type}:${source.externalId}` : null;\n}\n\nfunction boundedError(value: unknown): FactoryRuleJsonValue {\n const message = value instanceof Error ? value.message : typeof value === 'string' ? value : 'Tool execution failed.';\n return { message: message.slice(0, 2_000) };\n}\n\nfunction boundedResult(value: unknown): FactoryRuleJsonValue {\n try {\n return normalizeFactoryRuleJsonValue(value);\n } catch {\n return { message: 'Tool result was not serializable.' };\n }\n}\n\nfunction messageParts(message: MastraDBMessage): unknown[] {\n const content = message.content as { parts?: unknown[]; toolInvocations?: unknown[] } | unknown[] | undefined;\n if (Array.isArray(content)) return content;\n if (Array.isArray(content?.parts)) return content.parts;\n return Array.isArray(content?.toolInvocations) ? content.toolInvocations : [];\n}\n\nfunction completedStepToolCallIds(steps: unknown[]): Set<string> {\n const ids = new Set<string>();\n for (const rawStep of steps) {\n if (!rawStep || typeof rawStep !== 'object') continue;\n const toolResults = (rawStep as { toolResults?: unknown[] }).toolResults;\n if (!Array.isArray(toolResults)) continue;\n for (const rawResult of toolResults) {\n if (!rawResult || typeof rawResult !== 'object') continue;\n const toolCallId = (rawResult as { toolCallId?: unknown }).toolCallId;\n if (typeof toolCallId === 'string') ids.add(toolCallId);\n }\n }\n return ids;\n}\n\nfunction completedToolResults(message: MastraDBMessage): CompletedToolResult[] {\n if (message.role !== 'assistant') return [];\n const createdAt = message.createdAt instanceof Date ? message.createdAt : new Date(message.createdAt);\n const completed: CompletedToolResult[] = [];\n for (const rawPart of messageParts(message)) {\n if (!rawPart || typeof rawPart !== 'object') continue;\n const part = rawPart as Record<string, unknown>;\n const invocation =\n part.type === 'tool-invocation' && part.toolInvocation && typeof part.toolInvocation === 'object'\n ? (part.toolInvocation as Record<string, unknown>)\n : part;\n const state = invocation.state;\n if (state !== 'result' && state !== 'error') continue;\n const toolCallId = invocation.toolCallId;\n const toolName = invocation.toolName ?? invocation.name;\n if (typeof toolCallId !== 'string' || typeof toolName !== 'string') continue;\n completed.push({\n assistantMessageId: message.id,\n messageCreatedAt: createdAt,\n toolCallId,\n toolName: toolName.slice(0, 256),\n input: boundedResult(invocation.args ?? {}),\n status: state === 'error' ? 'error' : 'success',\n value: state === 'error' ? boundedError(invocation.result ?? invocation.error) : boundedResult(invocation.result),\n });\n }\n return completed;\n}\n\nfunction currentCompletedToolMessage(\n messages: MastraDBMessage[],\n toolCallIds: ReadonlySet<string>,\n): MastraDBMessage | undefined {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index]!;\n if (completedToolResults(message).some(result => toolCallIds.has(result.toolCallId))) return message;\n }\n return undefined;\n}\n\nasync function phaseCacheKey(value: ActivePhaseSnapshotValue, linked: WorkItemRow[]): Promise<string> {\n const serialized = JSON.stringify({\n ...value,\n linked: linked.map(item => [item.id, item.revision, item.stages[0]]),\n });\n return Buffer.from(await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(serialized))).toString(\n 'hex',\n );\n}\n\nfunction escapeText(value: string): string {\n return value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');\n}\n\nfunction phaseFromSignal(signal: { metadata?: Record<string, unknown> } | undefined): PhaseSnapshotValue | undefined {\n return (signal?.metadata?.value as { phase?: PhaseSnapshotValue } | undefined)?.phase;\n}\n\nfunction latestPhase(args: ComputeStateSignalArgs): PhaseSnapshotValue | undefined {\n for (const signal of [...args.activeStateSignals].reverse()) {\n const phase = phaseFromSignal(signal);\n if (phase) return phase;\n }\n return phaseFromSignal(args.lastSnapshot);\n}\n\nasync function withRuleTimeout<T>(operation: Promise<T>): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n operation,\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error('FACTORY_RULE_TIMEOUT')), RULE_TIMEOUT_MS);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\nconst reportedUnavailableMemorySettings = new WeakSet<object>();\n\n/**\n * Marks this run's Factory memory settings as unavailable so memory falls back\n * to auto, and tells the thread once per request that saved choices were not\n * applied. The reserved request-context key keeps clients from spoofing it.\n */\nexport function reportMemorySettingsUnavailable(\n requestContext: NonNullable<ProcessInputArgs['requestContext']>,\n reason: string,\n): void {\n requestContext.set('mastra__factoryMemorySettings', { status: 'unavailable', reason });\n console.warn('[Factory Memory Settings] Failed to load settings for run', { error: reason });\n if (reportedUnavailableMemorySettings.has(requestContext)) return;\n reportedUnavailableMemorySettings.add(requestContext);\n const controller = requestContext.get('controller') as\n | Pick<AgentControllerRequestContext<MastraCodeState>, 'emitEvent'>\n | undefined;\n controller?.emitEvent?.({\n type: 'error',\n error: new Error(\n 'Memory settings could not be loaded for this run, so observational memory is using Auto models and default thresholds.',\n ),\n errorType: 'factory_memory_settings_unavailable',\n retryable: false,\n });\n}\n\nexport class FactoryPhaseStateProcessor implements Processor<'factory-phase'> {\n readonly id = STATE_ID;\n readonly stateId = STATE_ID;\n /** Request contexts whose caller row is already resolved for this request. */\n private readonly loadedMemorySettings = new WeakSet<object>();\n\n constructor(\n private readonly options: {\n configVersion: string;\n storage: WorkItemsStorage;\n boards: BoardRegistry;\n loadMemorySettings?: (args: {\n requestContext: ProcessInputStepArgs['requestContext'];\n binding: FactoryRunBindingRecord | null;\n }) => Promise<void>;\n /** The session's routed thinking default, used when the session has not picked a level. */\n defaultThinkingLevel?: (requestContext: ComputeStateSignalArgs['requestContext']) => Promise<ThinkingLevel>;\n transitionService?: Pick<FactoryTransitionService, 'transition'>;\n messageReader?: PersistedMessageReader;\n recordPullRequestProvenance?: (input: {\n binding: FactoryRunBindingRecord;\n item: WorkItemRow;\n assistantMessageId: string;\n toolCallId: string;\n toolName: string;\n toolInput: FactoryRuleJsonValue;\n toolResult: FactoryRuleJsonValue;\n status: 'success' | 'error';\n }) => Promise<void>;\n },\n ) {}\n\n /**\n * Memory settings are caller state, not run state. Factory invokes this while\n * resolving its configured processor list, before Agent resolves dynamic\n * Memory and enumerates Memory's processors. This guarantees both the Memory\n * options and its model callbacks see the authoritative row for this\n * invocation. Doing this in `processInputStep` would be too late: Memory's\n * input-step hook runs before configured processors.\n */\n async prepareMemorySettings(requestContext: ProcessInputArgs['requestContext']): Promise<void> {\n await this.loadCallerMemorySettings(requestContext, undefined, true);\n }\n\n async processInput(args: ProcessInputArgs): Promise<MessageList> {\n await this.loadCallerMemorySettings(args.requestContext);\n return args.messageList;\n }\n\n async processInputStep(args: ProcessInputStepArgs): Promise<MessageList | undefined> {\n const address = getFactorySessionCoordinates(args.requestContext);\n let binding: FactoryRunBindingRecord | null | undefined;\n try {\n binding = address ? await this.options.storage.findRunBindingBySession(address) : undefined;\n } catch {\n await this.loadCallerMemorySettings(args.requestContext, undefined);\n return;\n }\n // Resumed runs skip the input-processor phase, so re-check here: it is a\n // no-op once `processInput` already placed the row for this request. Passing\n // `undefined` (not `null`) keeps the recovery lookup inside the loader, so a\n // recovered session reaches its project row from this hook too.\n await this.loadCallerMemorySettings(args.requestContext, binding);\n if (!binding || binding.status !== 'active') return;\n const completedToolCallIds = completedStepToolCallIds(args.steps);\n const completedMessage = currentCompletedToolMessage(args.messages, completedToolCallIds);\n if (completedMessage) {\n await this.ingestMessages(binding, [completedMessage], completedToolCallIds);\n }\n }\n\n /**\n * Loads the caller's row once per invocation. The input hook always refreshes\n * it in case the controller reused a request context; later step hooks reuse\n * that value (`undefined` means it has not been loaded yet; `null` means an\n * empty row).\n *\n * The WeakSet covers loaders that do not set the context key themselves, so a\n * request is still loaded once. A failed load records an unavailable sentinel\n * (memory then runs both roles on auto with default thresholds) and is not\n * marked loaded so the next step can retry.\n */\n private async loadCallerMemorySettings(\n requestContext: ProcessInputStepArgs['requestContext'] | ProcessInputArgs['requestContext'],\n binding?: FactoryRunBindingRecord | null,\n force = false,\n ): Promise<void> {\n if (!requestContext || !this.options.loadMemorySettings) return;\n const currentSettings = requestContext.get('mastra__factoryMemorySettings') as\n | { status?: unknown }\n | null\n | undefined;\n if (force) this.loadedMemorySettings.delete(requestContext);\n if (!force && currentSettings !== undefined && currentSettings?.status !== 'unavailable') return;\n if (!force && this.loadedMemorySettings.has(requestContext)) return;\n try {\n let runBinding = binding ?? null;\n if (binding === undefined) {\n const address = getFactorySessionCoordinates(requestContext);\n runBinding = address\n ? await this.options.storage.findRunBindingBySession(address)\n : // Crash-recovered sessions come back with empty state, so the binding\n // table is the last source of the project whose row applies. Without\n // this the run would silently read the caller's personal row.\n await findSessionRunBinding(requestContext, this.options.storage);\n }\n await this.options.loadMemorySettings({ requestContext, binding: runBinding });\n this.loadedMemorySettings.add(requestContext);\n } catch (error) {\n reportMemorySettingsUnavailable(requestContext, error instanceof Error ? error.message : String(error));\n }\n }\n\n async computeStateSignal(args: ComputeStateSignalArgs): Promise<ComputeStateSignalResult> {\n const address = getFactorySessionCoordinates(args.requestContext);\n if (!address) return;\n const binding = await this.options.storage.findRunBindingBySession(address);\n const prior = latestPhase(args);\n const hasBase = Boolean(args.lastSnapshot) && args.contextWindow.hasSnapshot;\n\n if (!binding) return;\n if (binding.status !== 'active') {\n if (!hasBase || prior?.status !== 'active') return;\n return {\n id: STATE_ID,\n cacheKey: `factory:none:${prior.bindingId ?? 'revoked'}`,\n mode: 'snapshot',\n tagName: 'factory-phase',\n contents: '\\n',\n value: { phase: { status: 'none' } },\n attributes: { status: 'none' },\n metadata: { value: { phase: { status: 'none' } } },\n };\n }\n\n const item = await this.options.storage.get({ orgId: binding.orgId, id: binding.workItemId });\n const stage = ruleStage(this.options.boards, item);\n if (!item || !stage) return;\n const allItems = await this.options.storage.list({\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n });\n const linked = allItems\n .filter(candidate => candidate.parentWorkItemId === item.id || item.parentWorkItemId === candidate.id)\n .slice(0, MAX_LINKED_ITEMS);\n const board = boardForWorkItem(item);\n const baseValue: ActivePhaseSnapshotBase = {\n status: 'active',\n bindingId: binding.id,\n itemId: item.id,\n revision: item.revision,\n stage,\n role: binding.role,\n configVersion: this.options.configVersion,\n };\n const value: ActivePhaseSnapshotValue =\n board === 'review'\n ? {\n ...baseValue,\n board,\n ...reviewRuntimeFromRequestContext(\n args.requestContext,\n await this.options.defaultThinkingLevel?.(args.requestContext),\n ),\n }\n : { ...baseValue, board };\n const cacheKey = await phaseCacheKey(value, linked);\n if (hasBase && (args.tracking?.currentCacheKey ?? args.lastSnapshot?.metadata?.state?.cacheKey) === cacheKey)\n return;\n\n const linkedText = linked.length\n ? `\\nLinked items: ${linked.map(candidate => `${workItemSource(candidate.externalSource)} ${candidate.title}`).join('; ')}`\n : '';\n const phaseLabel = this.options.boards.get(board)?.phases[stage]?.title ?? stage;\n const runtime =\n value.modelId && value.thinkingLevel ? { modelId: value.modelId, thinkingLevel: value.thinkingLevel } : null;\n const snapshotContents =\n `Factory ${board} phase: ${escapeText(phaseLabel)} (${escapeText(stage)})\\n` +\n `Work item: ${escapeText(item.title)} (${item.id})\\n` +\n `Role: ${escapeText(binding.role)}\\nRevision: ${item.revision}\\nConfig: ${escapeText(this.options.configVersion)}\\n` +\n (runtime\n ? `Runtime: model=${escapeText(runtime.modelId)}, reasoning-setting=${escapeText(runtime.thinkingLevel)}\\n`\n : '') +\n ((board === 'work' || board === 'review') && stage === 'intake'\n ? 'This card rests in Intake: its work is paused. Answer questions without moving it; when the user asks to resume, request the transition into the working stage first, then continue the work in this session.\\n'\n : '') +\n `Use factory_transition_work_item with expectedRevision ${item.revision} to request a phase change.${escapeText(linkedText)}`;\n const isDelta = hasBase && prior?.status === 'active';\n return {\n id: STATE_ID,\n cacheKey,\n mode: isDelta ? 'delta' : 'snapshot',\n tagName: 'factory-phase',\n contents: isDelta ? `Factory phase update:\\n${snapshotContents}` : snapshotContents,\n value: { phase: value },\n ...(isDelta ? { delta: { phase: value } } : {}),\n attributes: {\n status: 'active',\n board,\n stage,\n role: binding.role,\n revision: item.revision,\n ...(runtime ?? {}),\n },\n metadata: { value: { phase: value } },\n };\n }\n\n async reconcileAllBoundThreads(): Promise<void> {\n if (!this.options.messageReader) return;\n const bindings = await this.options.storage.listActiveRunBindings();\n for (const binding of bindings) await this.reconcileBinding(binding);\n }\n\n async reconcileBinding(binding: FactoryRunBindingRecord): Promise<void> {\n const reader = this.options.messageReader;\n if (!reader || binding.status !== 'active') return;\n // One keyed read up front: a binding whose item is gone or no longer in a\n // single rule stage would ingest nothing, so skip the cursor and message\n // reads entirely instead of paying them on every walk.\n const item = await this.options.storage.get({ orgId: binding.orgId, id: binding.workItemId });\n if (!itemInRuleStage(this.options.boards, item)) return;\n const cursor = await this.options.storage.getToolResultCursor(binding.orgId, binding.factoryProjectId, binding.id);\n let page = 0;\n while (true) {\n const result = await reader.listMessages({\n threadId: binding.threadId,\n resourceId: binding.resourceId,\n page,\n perPage: TRANSCRIPT_PAGE_SIZE,\n ...(cursor ? { filter: { dateRange: { start: cursor.lastMessageCreatedAt } } } : {}),\n orderBy: { field: 'createdAt', direction: 'ASC' },\n });\n await this.ingestMessages(binding, result.messages, undefined, item);\n const last = result.messages.at(-1);\n if (last) {\n await this.options.storage.advanceToolResultCursor({\n bindingId: binding.id,\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n lastMessageId: last.id,\n lastMessageCreatedAt: last.createdAt instanceof Date ? last.createdAt : new Date(last.createdAt),\n updatedAt: new Date(),\n });\n }\n if (!result.hasMore) break;\n page += 1;\n }\n }\n\n private async ingestMessages(\n binding: FactoryRunBindingRecord,\n messages: MastraDBMessage[],\n toolCallIds?: ReadonlySet<string>,\n preloadedItem?: WorkItemRow,\n ): Promise<void> {\n const item = preloadedItem ?? (await this.options.storage.get({ orgId: binding.orgId, id: binding.workItemId }));\n if (!itemInRuleStage(this.options.boards, item)) return;\n for (const message of messages) {\n for (const toolResult of completedToolResults(message)) {\n if (toolCallIds && !toolCallIds.has(toolResult.toolCallId)) continue;\n try {\n await this.options.recordPullRequestProvenance?.({\n binding,\n item,\n assistantMessageId: toolResult.assistantMessageId,\n toolCallId: toolResult.toolCallId,\n toolName: toolResult.toolName,\n toolInput: toolResult.input,\n toolResult: toolResult.value,\n status: toolResult.status,\n });\n } catch {\n // Provenance is supporting evidence and must not block authoritative rule ingress.\n }\n await this.ingestToolResult(binding, item, toolResult);\n }\n }\n }\n\n private async ingestToolResult(\n binding: FactoryRunBindingRecord,\n item: WorkItemRow,\n toolResult: CompletedToolResult,\n ): Promise<void> {\n const board = boardForWorkItem(item);\n const rule = resolveBoardToolRule(this.options.boards, board, toolResult.toolName);\n if (!rule) return;\n const ingressId = JSON.stringify([\n binding.id,\n binding.threadId,\n toolResult.assistantMessageId,\n toolResult.toolCallId,\n ]);\n const prior = await this.options.storage.getTransitionResultByIngress(\n binding.orgId,\n binding.factoryProjectId,\n ingressId,\n );\n if (prior) return;\n const context: FactoryToolResultRuleContext = {\n tenant: { orgId: binding.orgId, projectId: binding.factoryProjectId },\n actor: { type: 'agent', bindingId: binding.id, role: binding.role },\n ingress: { type: 'toolResult', id: ingressId },\n cause: `Completed ${toolResult.toolName}`,\n causalChain: [],\n configVersion: this.options.configVersion,\n item: {\n id: item.id,\n source: workItemSource(item.externalSource),\n sourceKey: workItemSourceKey(item),\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,\n itemRevision: item.revision,\n toolName: toolResult.toolName,\n threadId: binding.threadId,\n assistantMessageId: toolResult.assistantMessageId,\n toolCallId: toolResult.toolCallId,\n result: { status: toolResult.status, value: toolResult.value },\n };\n\n let decision: FactoryRuleDecision | void = undefined;\n let decisions: FactoryCommitDecision[] = [];\n let outcome: { status: 'accepted' | 'rejected'; code?: string; reason?: string } = { status: 'accepted' };\n try {\n decision = await withRuleTimeout(Promise.resolve(rule(Object.freeze(context))));\n if (decision?.type === 'reject') {\n outcome = { status: 'rejected', code: decision.code, reason: decision.reason };\n } else if (decision) {\n const validated = validateFactoryRuleDecisions([decision]);\n for (const entry of validated) assertFactoryDecisionTarget(entry, this.options.boards, board);\n decisions = validated;\n }\n } catch (error) {\n const timedOut = error instanceof Error && error.message === 'FACTORY_RULE_TIMEOUT';\n outcome = {\n status: 'rejected',\n code: timedOut ? 'timeout' : 'rule_error',\n reason: timedOut\n ? 'Factory rule evaluation timed out.'\n : error instanceof Error\n ? error.message.slice(0, 2_000)\n : 'Factory tool-result rule failed.',\n };\n }\n const committed = await this.options.storage.commitRuleEvaluation({\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n workItemId: item.id,\n ingress: { identity: ingressId, triggerType: 'tool.result' },\n configVersion: this.options.configVersion,\n expectedRevision: item.revision,\n actor: { ...context.actor },\n outcome,\n decisions: decisions.map(entry => ({ ...entry })),\n causalChain: [],\n now: new Date(),\n // The bound agent's own tool call carries the same consent as its governed moves.\n consentedBy: `agent:${binding.id}`,\n });\n if (committed.status !== 'committed' || !this.options.transitionService) return;\n for (const entry of decisions) {\n if (entry.type !== 'transition') continue;\n await this.options.transitionService.transition({\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n workItemId: item.id,\n board: entry.board,\n stage: entry.stage,\n expectedRevision: item.revision,\n actor: { type: 'system', id: 'factory-tool-result-rule' },\n ingress: { type: 'rule', identity: `decision:${entry.idempotencyKey}` },\n cause: 'tool_result_rule',\n causalChain: [{ ingressId, decisionType: entry.type }],\n ...(isApprovedPlanResult(toolResult) ? { planApproved: true } : {}),\n });\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"processor.js","names":[],"sources":["../../src/rules/processor.ts"],"sourcesContent":["import { resolveRequestThinkingLevel } from '@mastra/code-sdk/agents/model';\nimport type { ThinkingLevel } from '@mastra/code-sdk/providers/openai-codex';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { MastraDBMessage, MessageList } from '@mastra/core/agent/message-list';\nimport type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type {\n ComputeStateSignalArgs,\n ComputeStateSignalResult,\n ProcessInputArgs,\n ProcessInputStepArgs,\n Processor,\n} from '@mastra/core/processors';\n\nimport { boardForWorkItem, resolveBoardToolRule, workItemPhaseSemantics } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { FactoryRunBindingRecord, WorkItemsStorage, WorkItemRow } from '../storage/domains/work-items/base.js';\nimport { findSessionRunBinding, getFactorySessionCoordinates } from './binding-context.js';\nimport type { FactoryTransitionService } from './transition-service.js';\nimport { workItemSource } from './types.js';\nimport type {\n FactoryCommitDecision,\n FactoryRuleDecision,\n FactoryRuleJsonValue,\n FactoryRuleStage,\n FactoryToolResultRuleContext,\n} from './types.js';\nimport {\n assertFactoryDecisionTarget,\n normalizeFactoryRuleJsonValue,\n validateFactoryRuleDecisions,\n} from './validation.js';\n\nconst STATE_ID = 'factory-phase';\nconst RULE_TIMEOUT_MS = 5_000;\nconst TRANSCRIPT_PAGE_SIZE = 50;\nconst MAX_LINKED_ITEMS = 5;\nfunction ruleStage(boards: BoardRegistry, item: WorkItemRow | null | undefined): string | undefined {\n return item && workItemPhaseSemantics(boards, item) ? item.stages[0] : undefined;\n}\n\nfunction itemInRuleStage(boards: BoardRegistry, item: WorkItemRow | null | undefined): item is WorkItemRow {\n return ruleStage(boards, item) !== undefined;\n}\n\ntype PersistedMessageReader = {\n listMessages(input: {\n threadId: string;\n resourceId?: string;\n page: number;\n perPage: number;\n filter?: { dateRange?: { start?: Date } };\n orderBy: { field: 'createdAt'; direction: 'ASC' };\n }): Promise<{ messages: MastraDBMessage[]; hasMore: boolean }>;\n};\n\ntype CompletedToolResult = {\n assistantMessageId: string;\n messageCreatedAt: Date;\n toolCallId: string;\n toolName: string;\n input: FactoryRuleJsonValue;\n status: 'success' | 'error';\n value: FactoryRuleJsonValue;\n};\n\nfunction isApprovedPlanResult(result: CompletedToolResult): boolean {\n if (result.toolName !== 'submit_plan' || result.status !== 'success') return false;\n if (typeof result.value === 'string') return result.value.startsWith('Plan approved.');\n if (!result.value || typeof result.value !== 'object' || Array.isArray(result.value)) return false;\n const content = result.value.content;\n return typeof content === 'string' && content.startsWith('Plan approved.');\n}\n\ntype RuntimeSnapshot = {\n modelId: string;\n thinkingLevel: ThinkingLevel;\n};\n\ntype ActivePhaseSnapshotBase = {\n bindingId: string;\n itemId: string;\n revision: number;\n stage: FactoryRuleStage;\n role: string;\n configVersion: string;\n status: 'active';\n};\n\ntype ActivePhaseSnapshotValue = ActivePhaseSnapshotBase & {\n board: string;\n modelId?: string;\n thinkingLevel?: ThinkingLevel;\n};\n\ntype PhaseSnapshotValue = ActivePhaseSnapshotValue | { bindingId?: string; status: 'none' };\n\nfunction reviewRuntimeFromRequestContext(\n requestContext: ComputeStateSignalArgs['requestContext'],\n defaultThinkingLevel: ThinkingLevel | undefined,\n): RuntimeSnapshot {\n if (!requestContext || typeof requestContext.get !== 'function') {\n throw new Error('Factory review phase requires a controller request context.');\n }\n const context = requestContext.get<'controller', AgentControllerRequestContext<MastraCodeState>>('controller');\n const modelId = context?.session?.modelId.trim();\n if (!modelId) {\n throw new Error('Factory review phase requires a selected session model.');\n }\n return {\n modelId,\n thinkingLevel: resolveRequestThinkingLevel({ state: context?.state }, undefined, defaultThinkingLevel),\n };\n}\n\nfunction workItemSourceKey(item: WorkItemRow): string | null {\n const source = item.externalSource;\n return source ? `${source.integrationId}:${source.type}:${source.externalId}` : null;\n}\n\nfunction boundedError(value: unknown): FactoryRuleJsonValue {\n const message = value instanceof Error ? value.message : typeof value === 'string' ? value : 'Tool execution failed.';\n return { message: message.slice(0, 2_000) };\n}\n\nfunction boundedResult(value: unknown): FactoryRuleJsonValue {\n try {\n return normalizeFactoryRuleJsonValue(value);\n } catch {\n return { message: 'Tool result was not serializable.' };\n }\n}\n\nfunction messageParts(message: MastraDBMessage): unknown[] {\n const content = message.content as { parts?: unknown[]; toolInvocations?: unknown[] } | unknown[] | undefined;\n if (Array.isArray(content)) return content;\n if (Array.isArray(content?.parts)) return content.parts;\n return Array.isArray(content?.toolInvocations) ? content.toolInvocations : [];\n}\n\nfunction completedStepToolCallIds(steps: unknown[]): Set<string> {\n const ids = new Set<string>();\n for (const rawStep of steps) {\n if (!rawStep || typeof rawStep !== 'object') continue;\n const toolResults = (rawStep as { toolResults?: unknown[] }).toolResults;\n if (!Array.isArray(toolResults)) continue;\n for (const rawResult of toolResults) {\n if (!rawResult || typeof rawResult !== 'object') continue;\n const toolCallId = (rawResult as { toolCallId?: unknown }).toolCallId;\n if (typeof toolCallId === 'string') ids.add(toolCallId);\n }\n }\n return ids;\n}\n\nfunction completedToolResults(message: MastraDBMessage): CompletedToolResult[] {\n if (message.role !== 'assistant') return [];\n const createdAt = message.createdAt instanceof Date ? message.createdAt : new Date(message.createdAt);\n const completed: CompletedToolResult[] = [];\n for (const rawPart of messageParts(message)) {\n if (!rawPart || typeof rawPart !== 'object') continue;\n const part = rawPart as Record<string, unknown>;\n const invocation =\n part.type === 'tool-invocation' && part.toolInvocation && typeof part.toolInvocation === 'object'\n ? (part.toolInvocation as Record<string, unknown>)\n : part;\n const state = invocation.state;\n if (state !== 'result' && state !== 'error') continue;\n const toolCallId = invocation.toolCallId;\n const toolName = invocation.toolName ?? invocation.name;\n if (typeof toolCallId !== 'string' || typeof toolName !== 'string') continue;\n completed.push({\n assistantMessageId: message.id,\n messageCreatedAt: createdAt,\n toolCallId,\n toolName: toolName.slice(0, 256),\n input: boundedResult(invocation.args ?? {}),\n status: state === 'error' ? 'error' : 'success',\n value: state === 'error' ? boundedError(invocation.result ?? invocation.error) : boundedResult(invocation.result),\n });\n }\n return completed;\n}\n\nfunction currentCompletedToolMessage(\n messages: MastraDBMessage[],\n toolCallIds: ReadonlySet<string>,\n): MastraDBMessage | undefined {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index]!;\n if (completedToolResults(message).some(result => toolCallIds.has(result.toolCallId))) return message;\n }\n return undefined;\n}\n\nasync function phaseCacheKey(value: ActivePhaseSnapshotValue, linked: WorkItemRow[]): Promise<string> {\n const serialized = JSON.stringify({\n ...value,\n linked: linked.map(item => [item.id, item.revision, item.stages[0]]),\n });\n return Buffer.from(await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(serialized))).toString(\n 'hex',\n );\n}\n\nfunction escapeText(value: string): string {\n return value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');\n}\n\nfunction phaseFromSignal(signal: { metadata?: Record<string, unknown> } | undefined): PhaseSnapshotValue | undefined {\n return (signal?.metadata?.value as { phase?: PhaseSnapshotValue } | undefined)?.phase;\n}\n\nfunction latestPhase(args: ComputeStateSignalArgs): PhaseSnapshotValue | undefined {\n for (const signal of [...args.activeStateSignals].reverse()) {\n const phase = phaseFromSignal(signal);\n if (phase) return phase;\n }\n return phaseFromSignal(args.lastSnapshot);\n}\n\nasync function withRuleTimeout<T>(operation: Promise<T>): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n operation,\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error('FACTORY_RULE_TIMEOUT')), RULE_TIMEOUT_MS);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\nconst reportedUnavailableMemorySettings = new WeakSet<object>();\n\n/**\n * Marks this run's Factory memory settings as unavailable so memory falls back\n * to auto, and tells the thread once per request that saved choices were not\n * applied. The reserved request-context key keeps clients from spoofing it.\n */\nexport function reportMemorySettingsUnavailable(\n requestContext: NonNullable<ProcessInputArgs['requestContext']>,\n reason: string,\n): void {\n requestContext.set('mastra__factoryMemorySettings', { status: 'unavailable', reason });\n console.warn('[Factory Memory Settings] Failed to load settings for run', { error: reason });\n if (reportedUnavailableMemorySettings.has(requestContext)) return;\n reportedUnavailableMemorySettings.add(requestContext);\n const controller = requestContext.get('controller') as\n | Pick<AgentControllerRequestContext<MastraCodeState>, 'emitEvent'>\n | undefined;\n controller?.emitEvent?.({\n type: 'error',\n error: new Error(\n 'Memory settings could not be loaded for this run, so observational memory is using Auto models and default thresholds.',\n ),\n errorType: 'factory_memory_settings_unavailable',\n retryable: false,\n });\n}\n\nexport class FactoryPhaseStateProcessor implements Processor<'factory-phase'> {\n readonly id = STATE_ID;\n readonly stateId = STATE_ID;\n /** Request contexts whose caller row is already resolved for this request. */\n private readonly loadedMemorySettings = new WeakSet<object>();\n\n constructor(\n private readonly options: {\n configVersion: string;\n storage: WorkItemsStorage;\n boards: BoardRegistry;\n loadMemorySettings?: (args: {\n requestContext: ProcessInputStepArgs['requestContext'];\n binding: FactoryRunBindingRecord | null;\n }) => Promise<void>;\n /** The session's routed thinking default, used when the session has not picked a level. */\n defaultThinkingLevel?: (requestContext: ComputeStateSignalArgs['requestContext']) => Promise<ThinkingLevel>;\n transitionService?: Pick<FactoryTransitionService, 'transition'>;\n messageReader?: PersistedMessageReader;\n recordPullRequestProvenance?: (input: {\n binding: FactoryRunBindingRecord;\n item: WorkItemRow;\n assistantMessageId: string;\n toolCallId: string;\n toolName: string;\n toolInput: FactoryRuleJsonValue;\n toolResult: FactoryRuleJsonValue;\n status: 'success' | 'error';\n }) => Promise<void>;\n },\n ) {}\n\n /**\n * Memory settings are caller state, not run state. Factory invokes this while\n * resolving its configured processor list, before Agent resolves dynamic\n * Memory and enumerates Memory's processors. This guarantees both the Memory\n * options and its model callbacks see the authoritative row for this\n * invocation. Doing this in `processInputStep` would be too late: Memory's\n * input-step hook runs before configured processors.\n */\n async prepareMemorySettings(requestContext: ProcessInputArgs['requestContext']): Promise<void> {\n await this.loadCallerMemorySettings(requestContext, undefined, true);\n }\n\n async processInput(args: ProcessInputArgs): Promise<MessageList> {\n await this.loadCallerMemorySettings(args.requestContext);\n return args.messageList;\n }\n\n async processInputStep(args: ProcessInputStepArgs): Promise<MessageList | undefined> {\n const address = getFactorySessionCoordinates(args.requestContext);\n let binding: FactoryRunBindingRecord | null | undefined;\n try {\n binding = address ? await this.options.storage.findRunBindingBySession(address) : undefined;\n } catch {\n await this.loadCallerMemorySettings(args.requestContext, undefined);\n return;\n }\n // Resumed runs skip the input-processor phase, so re-check here: it is a\n // no-op once `processInput` already placed the row for this request. Passing\n // `undefined` (not `null`) keeps the recovery lookup inside the loader, so a\n // recovered session reaches its project row from this hook too.\n await this.loadCallerMemorySettings(args.requestContext, binding);\n if (!binding || binding.status !== 'active') return;\n const completedToolCallIds = completedStepToolCallIds(args.steps);\n const completedMessage = currentCompletedToolMessage(args.messages, completedToolCallIds);\n if (completedMessage) {\n await this.ingestMessages(binding, [completedMessage], completedToolCallIds);\n }\n }\n\n /**\n * Loads the caller's row once per invocation. The input hook always refreshes\n * it in case the controller reused a request context; later step hooks reuse\n * that value (`undefined` means it has not been loaded yet; `null` means an\n * empty row).\n *\n * The WeakSet covers loaders that do not set the context key themselves, so a\n * request is still loaded once. A failed load records an unavailable sentinel\n * (memory then runs both roles on auto with default thresholds) and is not\n * marked loaded so the next step can retry.\n */\n private async loadCallerMemorySettings(\n requestContext: ProcessInputStepArgs['requestContext'] | ProcessInputArgs['requestContext'],\n binding?: FactoryRunBindingRecord | null,\n force = false,\n ): Promise<void> {\n if (!requestContext || !this.options.loadMemorySettings) return;\n const currentSettings = requestContext.get('mastra__factoryMemorySettings') as\n | { status?: unknown }\n | null\n | undefined;\n if (force) this.loadedMemorySettings.delete(requestContext);\n if (!force && currentSettings !== undefined && currentSettings?.status !== 'unavailable') return;\n if (!force && this.loadedMemorySettings.has(requestContext)) return;\n try {\n let runBinding = binding ?? null;\n if (binding === undefined) {\n const address = getFactorySessionCoordinates(requestContext);\n runBinding = address\n ? await this.options.storage.findRunBindingBySession(address)\n : // Crash-recovered sessions come back with empty state, so the binding\n // table is the last source of the project whose row applies. Without\n // this the run would silently read the caller's personal row.\n await findSessionRunBinding(requestContext, this.options.storage);\n }\n await this.options.loadMemorySettings({ requestContext, binding: runBinding });\n this.loadedMemorySettings.add(requestContext);\n } catch (error) {\n reportMemorySettingsUnavailable(requestContext, error instanceof Error ? error.message : String(error));\n }\n }\n\n async computeStateSignal(args: ComputeStateSignalArgs): Promise<ComputeStateSignalResult> {\n const address = getFactorySessionCoordinates(args.requestContext);\n if (!address) return;\n const binding = await this.options.storage.findRunBindingBySession(address);\n const prior = latestPhase(args);\n const hasBase = Boolean(args.lastSnapshot) && args.contextWindow.hasSnapshot;\n\n if (!binding) return;\n if (binding.status !== 'active') {\n if (!hasBase || prior?.status !== 'active') return;\n return {\n id: STATE_ID,\n cacheKey: `factory:none:${prior.bindingId ?? 'revoked'}`,\n mode: 'snapshot',\n tagName: 'factory-phase',\n contents: '\\n',\n value: { phase: { status: 'none' } },\n attributes: { status: 'none' },\n metadata: { value: { phase: { status: 'none' } } },\n };\n }\n\n const item = await this.options.storage.get({ orgId: binding.orgId, id: binding.workItemId });\n const stage = ruleStage(this.options.boards, item);\n if (!item || !stage) return;\n const allItems = await this.options.storage.list({\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n });\n const linked = allItems\n .filter(candidate => candidate.parentWorkItemId === item.id || item.parentWorkItemId === candidate.id)\n .slice(0, MAX_LINKED_ITEMS);\n const board = boardForWorkItem(item);\n const baseValue: ActivePhaseSnapshotBase = {\n status: 'active',\n bindingId: binding.id,\n itemId: item.id,\n revision: item.revision,\n stage,\n role: binding.role,\n configVersion: this.options.configVersion,\n };\n const value: ActivePhaseSnapshotValue =\n board === 'review'\n ? {\n ...baseValue,\n board,\n ...reviewRuntimeFromRequestContext(\n args.requestContext,\n await this.options.defaultThinkingLevel?.(args.requestContext),\n ),\n }\n : { ...baseValue, board };\n const cacheKey = await phaseCacheKey(value, linked);\n if (hasBase && (args.tracking?.currentCacheKey ?? args.lastSnapshot?.metadata?.state?.cacheKey) === cacheKey)\n return;\n\n const linkedText = linked.length\n ? `\\nLinked items: ${linked.map(candidate => `${workItemSource(candidate.externalSource)} ${candidate.title}`).join('; ')}`\n : '';\n const phase = this.options.boards.get(board)?.phases[stage];\n const phaseLabel = phase?.name ?? stage;\n const exitText =\n phase?.kind === 'working' && phase.exitTool\n ? `This phase ends when ${escapeText(phase.exitTool.id)} succeeds. Then move the card with factory_transition_work_item to one of: ${phase.nextPhases.map(escapeText).join(', ')}.\\n`\n : '';\n const runtime =\n value.modelId && value.thinkingLevel ? { modelId: value.modelId, thinkingLevel: value.thinkingLevel } : null;\n const snapshotContents =\n `Factory ${board} phase: ${escapeText(phaseLabel)} (${escapeText(stage)})\\n` +\n `Work item: ${escapeText(item.title)} (${item.id})\\n` +\n `Role: ${escapeText(binding.role)}\\nRevision: ${item.revision}\\nConfig: ${escapeText(this.options.configVersion)}\\n` +\n (runtime\n ? `Runtime: model=${escapeText(runtime.modelId)}, reasoning-setting=${escapeText(runtime.thinkingLevel)}\\n`\n : '') +\n ((board === 'work' || board === 'review') && stage === 'intake'\n ? 'This card rests in Intake: its work is paused. Answer questions without moving it; when the user asks to resume, request the transition into the working stage first, then continue the work in this session.\\n'\n : '') +\n exitText +\n `Use factory_transition_work_item with expectedRevision ${item.revision} to request a phase change.${escapeText(linkedText)}`;\n const isDelta = hasBase && prior?.status === 'active';\n return {\n id: STATE_ID,\n cacheKey,\n mode: isDelta ? 'delta' : 'snapshot',\n tagName: 'factory-phase',\n contents: isDelta ? `Factory phase update:\\n${snapshotContents}` : snapshotContents,\n value: { phase: value },\n ...(isDelta ? { delta: { phase: value } } : {}),\n attributes: {\n status: 'active',\n board,\n stage,\n role: binding.role,\n revision: item.revision,\n ...(runtime ?? {}),\n },\n metadata: { value: { phase: value } },\n };\n }\n\n async reconcileAllBoundThreads(): Promise<void> {\n if (!this.options.messageReader) return;\n const bindings = await this.options.storage.listActiveRunBindings();\n for (const binding of bindings) await this.reconcileBinding(binding);\n }\n\n async reconcileBinding(binding: FactoryRunBindingRecord): Promise<void> {\n const reader = this.options.messageReader;\n if (!reader || binding.status !== 'active') return;\n // One keyed read up front: a binding whose item is gone or no longer in a\n // single rule stage would ingest nothing, so skip the cursor and message\n // reads entirely instead of paying them on every walk.\n const item = await this.options.storage.get({ orgId: binding.orgId, id: binding.workItemId });\n if (!itemInRuleStage(this.options.boards, item)) return;\n const cursor = await this.options.storage.getToolResultCursor(binding.orgId, binding.factoryProjectId, binding.id);\n let page = 0;\n while (true) {\n const result = await reader.listMessages({\n threadId: binding.threadId,\n resourceId: binding.resourceId,\n page,\n perPage: TRANSCRIPT_PAGE_SIZE,\n ...(cursor ? { filter: { dateRange: { start: cursor.lastMessageCreatedAt } } } : {}),\n orderBy: { field: 'createdAt', direction: 'ASC' },\n });\n await this.ingestMessages(binding, result.messages, undefined, item);\n const last = result.messages.at(-1);\n if (last) {\n await this.options.storage.advanceToolResultCursor({\n bindingId: binding.id,\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n lastMessageId: last.id,\n lastMessageCreatedAt: last.createdAt instanceof Date ? last.createdAt : new Date(last.createdAt),\n updatedAt: new Date(),\n });\n }\n if (!result.hasMore) break;\n page += 1;\n }\n }\n\n private async ingestMessages(\n binding: FactoryRunBindingRecord,\n messages: MastraDBMessage[],\n toolCallIds?: ReadonlySet<string>,\n preloadedItem?: WorkItemRow,\n ): Promise<void> {\n const item = preloadedItem ?? (await this.options.storage.get({ orgId: binding.orgId, id: binding.workItemId }));\n if (!itemInRuleStage(this.options.boards, item)) return;\n for (const message of messages) {\n for (const toolResult of completedToolResults(message)) {\n if (toolCallIds && !toolCallIds.has(toolResult.toolCallId)) continue;\n try {\n await this.options.recordPullRequestProvenance?.({\n binding,\n item,\n assistantMessageId: toolResult.assistantMessageId,\n toolCallId: toolResult.toolCallId,\n toolName: toolResult.toolName,\n toolInput: toolResult.input,\n toolResult: toolResult.value,\n status: toolResult.status,\n });\n } catch {\n // Provenance is supporting evidence and must not block authoritative rule ingress.\n }\n await this.ingestToolResult(binding, item, toolResult);\n }\n }\n }\n\n private async ingestToolResult(\n binding: FactoryRunBindingRecord,\n item: WorkItemRow,\n toolResult: CompletedToolResult,\n ): Promise<void> {\n const board = boardForWorkItem(item);\n const rule = resolveBoardToolRule(this.options.boards, board, toolResult.toolName);\n if (!rule) return;\n const ingressId = JSON.stringify([\n binding.id,\n binding.threadId,\n toolResult.assistantMessageId,\n toolResult.toolCallId,\n ]);\n const prior = await this.options.storage.getTransitionResultByIngress(\n binding.orgId,\n binding.factoryProjectId,\n ingressId,\n );\n if (prior) return;\n const context: FactoryToolResultRuleContext = {\n tenant: { orgId: binding.orgId, projectId: binding.factoryProjectId },\n actor: { type: 'agent', bindingId: binding.id, role: binding.role },\n ingress: { type: 'toolResult', id: ingressId },\n cause: `Completed ${toolResult.toolName}`,\n causalChain: [],\n configVersion: this.options.configVersion,\n item: {\n id: item.id,\n source: workItemSource(item.externalSource),\n sourceKey: workItemSourceKey(item),\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,\n itemRevision: item.revision,\n toolName: toolResult.toolName,\n threadId: binding.threadId,\n assistantMessageId: toolResult.assistantMessageId,\n toolCallId: toolResult.toolCallId,\n result: { status: toolResult.status, value: toolResult.value },\n };\n\n let decision: FactoryRuleDecision | void = undefined;\n let decisions: FactoryCommitDecision[] = [];\n let outcome: { status: 'accepted' | 'rejected'; code?: string; reason?: string } = { status: 'accepted' };\n try {\n decision = await withRuleTimeout(Promise.resolve(rule(Object.freeze(context))));\n if (decision?.type === 'reject') {\n outcome = { status: 'rejected', code: decision.code, reason: decision.reason };\n } else if (decision) {\n const validated = validateFactoryRuleDecisions([decision]);\n for (const entry of validated) assertFactoryDecisionTarget(entry, this.options.boards, board);\n decisions = validated;\n }\n } catch (error) {\n const timedOut = error instanceof Error && error.message === 'FACTORY_RULE_TIMEOUT';\n outcome = {\n status: 'rejected',\n code: timedOut ? 'timeout' : 'rule_error',\n reason: timedOut\n ? 'Factory rule evaluation timed out.'\n : error instanceof Error\n ? error.message.slice(0, 2_000)\n : 'Factory tool-result rule failed.',\n };\n }\n const committed = await this.options.storage.commitRuleEvaluation({\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n workItemId: item.id,\n ingress: { identity: ingressId, triggerType: 'tool.result' },\n configVersion: this.options.configVersion,\n expectedRevision: item.revision,\n actor: { ...context.actor },\n outcome,\n decisions: decisions.map(entry => ({ ...entry })),\n causalChain: [],\n now: new Date(),\n // The bound agent's own tool call carries the same consent as its governed moves.\n consentedBy: `agent:${binding.id}`,\n });\n if (committed.status !== 'committed' || !this.options.transitionService) return;\n for (const entry of decisions) {\n if (entry.type !== 'transition') continue;\n await this.options.transitionService.transition({\n orgId: binding.orgId,\n factoryProjectId: binding.factoryProjectId,\n workItemId: item.id,\n board: entry.board,\n stage: entry.stage,\n expectedRevision: item.revision,\n actor: { type: 'system', id: 'factory-tool-result-rule' },\n ingress: { type: 'rule', identity: `decision:${entry.idempotencyKey}` },\n cause: 'tool_result_rule',\n causalChain: [{ ingressId, decisionType: entry.type }],\n ...(isApprovedPlanResult(toolResult) ? { planApproved: true } : {}),\n });\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Conditions a board phase tests against a card, such as when it starts on its own or
|
|
4
|
+
* when its exit tool is approved without a person. The shape mirrors the editor's rule
|
|
5
|
+
* groups (`{field, operator, value}` leaves inside AND/OR groups), but Factory owns
|
|
6
|
+
* the types and evaluator; nothing is shared with `@mastra/editor` or `@mastra/server`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const RULE_OPERATORS: readonly ['equals', 'not_equals', 'contains', 'not_contains', 'in', 'not_in', 'exists', 'not_exists', 'greater_than', 'less_than', 'greater_than_or_equal', 'less_than_or_equal'];
|
|
9
|
+
export type RuleOperator = (typeof RULE_OPERATORS)[number];
|
|
10
|
+
export declare const MAX_RULE_GROUP_DEPTH = 3;
|
|
11
|
+
/** Facts a phase condition can test about a card (see `cardRuleFacts`). */
|
|
12
|
+
export declare const CARD_RULE_FIELDS: readonly ['item.labels', 'item.title', 'item.author', 'source.kind', 'source.integration'];
|
|
13
|
+
export type RuleValue = string | number | boolean | Array<string | number | boolean>;
|
|
14
|
+
export interface RuleCondition {
|
|
15
|
+
field: string;
|
|
16
|
+
operator: RuleOperator;
|
|
17
|
+
value?: RuleValue;
|
|
18
|
+
}
|
|
19
|
+
export interface RuleGroup {
|
|
20
|
+
operator: 'AND' | 'OR';
|
|
21
|
+
conditions: Array<RuleCondition | RuleGroup>;
|
|
22
|
+
}
|
|
23
|
+
export type RuleFacts = Readonly<Record<string, unknown>>;
|
|
24
|
+
/** Zod schema for a rule group whose leaves may only name `fields`. Depth is capped at {@link MAX_RULE_GROUP_DEPTH}. */
|
|
25
|
+
export declare function ruleGroupSchema(fields: readonly [string, ...string[]]): z.ZodType<RuleGroup>;
|
|
26
|
+
export declare const cardRuleGroupSchema: z.ZodType<RuleGroup, unknown, z.core.$ZodTypeInternals<RuleGroup, unknown>>;
|
|
27
|
+
/** True when `facts` satisfy `group`. A `null`/absent group matches everything (an unconditional phase). */
|
|
28
|
+
export declare function evaluateRuleGroup(group: RuleGroup | null | undefined, facts: RuleFacts): boolean;
|
|
29
|
+
//# sourceMappingURL=rule-group.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-group.d.ts","sourceRoot":"","sources":["../../src/rules/rule-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AACH,eAAO,MAAM,cAAc,YACzB,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,WAAW,EACX,uBAAuB,EACvB,oBAAoB,CACZ,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAItC,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,YAC3B,aAAa,EACb,YAAY,EACZ,aAAa,EACb,aAAa,EACb,oBAAoB,CACZ,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAErF,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,KAAK,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;CAC9C;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AA4C1D,wHAAwH;AACxH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAa5F;AAED,eAAO,MAAM,mBAAmB,6EAAoC,CAAC;AA2DrE,4GAA4G;AAC5G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAMhG"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// src/rules/rule-group.ts
|
|
3
|
+
/**
|
|
4
|
+
* Conditions a board phase tests against a card, such as when it starts on its own or
|
|
5
|
+
* when its exit tool is approved without a person. The shape mirrors the editor's rule
|
|
6
|
+
* groups (`{field, operator, value}` leaves inside AND/OR groups), but Factory owns
|
|
7
|
+
* the types and evaluator; nothing is shared with `@mastra/editor` or `@mastra/server`.
|
|
8
|
+
*/
|
|
9
|
+
const RULE_OPERATORS = [
|
|
10
|
+
"equals",
|
|
11
|
+
"not_equals",
|
|
12
|
+
"contains",
|
|
13
|
+
"not_contains",
|
|
14
|
+
"in",
|
|
15
|
+
"not_in",
|
|
16
|
+
"exists",
|
|
17
|
+
"not_exists",
|
|
18
|
+
"greater_than",
|
|
19
|
+
"less_than",
|
|
20
|
+
"greater_than_or_equal",
|
|
21
|
+
"less_than_or_equal"
|
|
22
|
+
];
|
|
23
|
+
const MAX_RULE_GROUP_DEPTH = 3;
|
|
24
|
+
const MAX_CONDITIONS_PER_GROUP = 20;
|
|
25
|
+
const MAX_STRING_VALUE_LENGTH = 500;
|
|
26
|
+
/** Facts a phase condition can test about a card (see `cardRuleFacts`). */
|
|
27
|
+
const CARD_RULE_FIELDS = [
|
|
28
|
+
"item.labels",
|
|
29
|
+
"item.title",
|
|
30
|
+
"item.author",
|
|
31
|
+
"source.kind",
|
|
32
|
+
"source.integration"
|
|
33
|
+
];
|
|
34
|
+
const scalarSchema = z.union([
|
|
35
|
+
z.string().max(MAX_STRING_VALUE_LENGTH),
|
|
36
|
+
z.number().finite(),
|
|
37
|
+
z.boolean()
|
|
38
|
+
]);
|
|
39
|
+
const valueSchema = z.union([scalarSchema, z.array(scalarSchema).max(100)]);
|
|
40
|
+
const VALUELESS = /* @__PURE__ */ new Set(["exists", "not_exists"]);
|
|
41
|
+
const LIST_VALUE = /* @__PURE__ */ new Set(["in", "not_in"]);
|
|
42
|
+
const ORDERED = /* @__PURE__ */ new Set([
|
|
43
|
+
"greater_than",
|
|
44
|
+
"less_than",
|
|
45
|
+
"greater_than_or_equal",
|
|
46
|
+
"less_than_or_equal"
|
|
47
|
+
]);
|
|
48
|
+
function conditionSchema(fields) {
|
|
49
|
+
return z.object({
|
|
50
|
+
field: z.enum(fields),
|
|
51
|
+
operator: z.enum(RULE_OPERATORS),
|
|
52
|
+
value: valueSchema.optional()
|
|
53
|
+
}).strict().superRefine((condition, ctx) => {
|
|
54
|
+
if (VALUELESS.has(condition.operator)) {
|
|
55
|
+
if (condition.value !== void 0) ctx.addIssue({
|
|
56
|
+
code: "custom",
|
|
57
|
+
path: ["value"],
|
|
58
|
+
message: `'${condition.operator}' takes no value.`
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (condition.value === void 0) {
|
|
63
|
+
ctx.addIssue({
|
|
64
|
+
code: "custom",
|
|
65
|
+
path: ["value"],
|
|
66
|
+
message: `'${condition.operator}' needs a value.`
|
|
67
|
+
});
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (LIST_VALUE.has(condition.operator) !== Array.isArray(condition.value)) ctx.addIssue({
|
|
71
|
+
code: "custom",
|
|
72
|
+
path: ["value"],
|
|
73
|
+
message: LIST_VALUE.has(condition.operator) ? `'${condition.operator}' needs a list value.` : `'${condition.operator}' needs a single value.`
|
|
74
|
+
});
|
|
75
|
+
if (ORDERED.has(condition.operator) && typeof condition.value !== "number") ctx.addIssue({
|
|
76
|
+
code: "custom",
|
|
77
|
+
path: ["value"],
|
|
78
|
+
message: `'${condition.operator}' needs a number.`
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/** Zod schema for a rule group whose leaves may only name `fields`. Depth is capped at {@link MAX_RULE_GROUP_DEPTH}. */
|
|
83
|
+
function ruleGroupSchema(fields) {
|
|
84
|
+
const leaf = conditionSchema(fields);
|
|
85
|
+
const groupAt = (depth) => {
|
|
86
|
+
const member = depth < 3 ? z.union([leaf, z.lazy(() => groupAt(depth + 1))]) : leaf;
|
|
87
|
+
return z.object({
|
|
88
|
+
operator: z.enum(["AND", "OR"]),
|
|
89
|
+
conditions: z.array(member).min(1).max(MAX_CONDITIONS_PER_GROUP)
|
|
90
|
+
}).strict();
|
|
91
|
+
};
|
|
92
|
+
return groupAt(1);
|
|
93
|
+
}
|
|
94
|
+
const cardRuleGroupSchema = ruleGroupSchema(CARD_RULE_FIELDS);
|
|
95
|
+
function isGroup(member) {
|
|
96
|
+
return "conditions" in member;
|
|
97
|
+
}
|
|
98
|
+
const normalize = (value) => typeof value === "string" ? value.trim().toLowerCase() : value;
|
|
99
|
+
const same = (left, right) => normalize(left) === normalize(right);
|
|
100
|
+
function contains(actual, expected) {
|
|
101
|
+
if (Array.isArray(actual)) return actual.some((entry) => same(entry, expected));
|
|
102
|
+
if (typeof actual === "string" && typeof expected === "string") return actual.toLowerCase().includes(expected.toLowerCase());
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
function compare(actual, expected, test) {
|
|
106
|
+
return typeof actual === "number" && typeof expected === "number" && test(actual, expected);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Evaluate one condition. Strings compare case-insensitively (labels and
|
|
110
|
+
* repository slugs are case-insensitive on every provider Factory reads). A
|
|
111
|
+
* missing fact fails every operator except `not_exists`, `not_equals`,
|
|
112
|
+
* `not_contains` and `not_in`.
|
|
113
|
+
*/
|
|
114
|
+
function evaluateCondition(condition, facts) {
|
|
115
|
+
const actual = facts[condition.field];
|
|
116
|
+
const present = actual !== void 0 && actual !== null;
|
|
117
|
+
const expected = condition.value;
|
|
118
|
+
switch (condition.operator) {
|
|
119
|
+
case "exists": return present;
|
|
120
|
+
case "not_exists": return !present;
|
|
121
|
+
case "equals": return present && same(actual, expected);
|
|
122
|
+
case "not_equals": return !present || !same(actual, expected);
|
|
123
|
+
case "contains": return present && contains(actual, expected);
|
|
124
|
+
case "not_contains": return !present || !contains(actual, expected);
|
|
125
|
+
case "in": return present && Array.isArray(expected) && expected.some((candidate) => same(actual, candidate));
|
|
126
|
+
case "not_in": return !present || !Array.isArray(expected) || !expected.some((candidate) => same(actual, candidate));
|
|
127
|
+
case "greater_than": return compare(actual, expected, (left, right) => left > right);
|
|
128
|
+
case "less_than": return compare(actual, expected, (left, right) => left < right);
|
|
129
|
+
case "greater_than_or_equal": return compare(actual, expected, (left, right) => left >= right);
|
|
130
|
+
case "less_than_or_equal": return compare(actual, expected, (left, right) => left <= right);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** True when `facts` satisfy `group`. A `null`/absent group matches everything (an unconditional phase). */
|
|
134
|
+
function evaluateRuleGroup(group, facts) {
|
|
135
|
+
if (!group) return true;
|
|
136
|
+
const results = group.conditions.map((member) => isGroup(member) ? evaluateRuleGroup(member, facts) : evaluateCondition(member, facts));
|
|
137
|
+
return group.operator === "AND" ? results.every(Boolean) : results.some(Boolean);
|
|
138
|
+
}
|
|
139
|
+
export { CARD_RULE_FIELDS, MAX_RULE_GROUP_DEPTH, RULE_OPERATORS, cardRuleGroupSchema, evaluateRuleGroup, ruleGroupSchema };
|
|
140
|
+
|
|
141
|
+
//# sourceMappingURL=rule-group.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-group.js","names":[],"sources":["../../src/rules/rule-group.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Conditions a board phase tests against a card, such as when it starts on its own or\n * when its exit tool is approved without a person. The shape mirrors the editor's rule\n * groups (`{field, operator, value}` leaves inside AND/OR groups), but Factory owns\n * the types and evaluator; nothing is shared with `@mastra/editor` or `@mastra/server`.\n */\nexport const RULE_OPERATORS = [\n 'equals',\n 'not_equals',\n 'contains',\n 'not_contains',\n 'in',\n 'not_in',\n 'exists',\n 'not_exists',\n 'greater_than',\n 'less_than',\n 'greater_than_or_equal',\n 'less_than_or_equal',\n] as const;\nexport type RuleOperator = (typeof RULE_OPERATORS)[number];\n\nexport const MAX_RULE_GROUP_DEPTH = 3;\nconst MAX_CONDITIONS_PER_GROUP = 20;\nconst MAX_STRING_VALUE_LENGTH = 500;\n\n/** Facts a phase condition can test about a card (see `cardRuleFacts`). */\nexport const CARD_RULE_FIELDS = [\n 'item.labels',\n 'item.title',\n 'item.author',\n 'source.kind',\n 'source.integration',\n] as const;\n\nexport type RuleValue = string | number | boolean | Array<string | number | boolean>;\n\nexport interface RuleCondition {\n field: string;\n operator: RuleOperator;\n value?: RuleValue;\n}\n\nexport interface RuleGroup {\n operator: 'AND' | 'OR';\n conditions: Array<RuleCondition | RuleGroup>;\n}\n\nexport type RuleFacts = Readonly<Record<string, unknown>>;\n\nconst scalarSchema = z.union([z.string().max(MAX_STRING_VALUE_LENGTH), z.number().finite(), z.boolean()]);\nconst valueSchema = z.union([scalarSchema, z.array(scalarSchema).max(100)]);\n\nconst VALUELESS: ReadonlySet<RuleOperator> = new Set(['exists', 'not_exists']);\nconst LIST_VALUE: ReadonlySet<RuleOperator> = new Set(['in', 'not_in']);\nconst ORDERED: ReadonlySet<RuleOperator> = new Set([\n 'greater_than',\n 'less_than',\n 'greater_than_or_equal',\n 'less_than_or_equal',\n]);\n\nfunction conditionSchema(fields: readonly [string, ...string[]]) {\n return z\n .object({ field: z.enum(fields), operator: z.enum(RULE_OPERATORS), value: valueSchema.optional() })\n .strict()\n .superRefine((condition, ctx) => {\n if (VALUELESS.has(condition.operator)) {\n if (condition.value !== undefined) {\n ctx.addIssue({ code: 'custom', path: ['value'], message: `'${condition.operator}' takes no value.` });\n }\n return;\n }\n if (condition.value === undefined) {\n ctx.addIssue({ code: 'custom', path: ['value'], message: `'${condition.operator}' needs a value.` });\n return;\n }\n if (LIST_VALUE.has(condition.operator) !== Array.isArray(condition.value)) {\n ctx.addIssue({\n code: 'custom',\n path: ['value'],\n message: LIST_VALUE.has(condition.operator)\n ? `'${condition.operator}' needs a list value.`\n : `'${condition.operator}' needs a single value.`,\n });\n }\n if (ORDERED.has(condition.operator) && typeof condition.value !== 'number') {\n ctx.addIssue({ code: 'custom', path: ['value'], message: `'${condition.operator}' needs a number.` });\n }\n });\n}\n\n/** Zod schema for a rule group whose leaves may only name `fields`. Depth is capped at {@link MAX_RULE_GROUP_DEPTH}. */\nexport function ruleGroupSchema(fields: readonly [string, ...string[]]): z.ZodType<RuleGroup> {\n const leaf = conditionSchema(fields);\n const groupAt = (depth: number): z.ZodType<RuleGroup> => {\n const member: z.ZodType<RuleCondition | RuleGroup> =\n depth < MAX_RULE_GROUP_DEPTH ? z.union([leaf, z.lazy(() => groupAt(depth + 1))]) : leaf;\n return z\n .object({\n operator: z.enum(['AND', 'OR']),\n conditions: z.array(member).min(1).max(MAX_CONDITIONS_PER_GROUP),\n })\n .strict() as z.ZodType<RuleGroup>;\n };\n return groupAt(1);\n}\n\nexport const cardRuleGroupSchema = ruleGroupSchema(CARD_RULE_FIELDS);\n\nfunction isGroup(member: RuleCondition | RuleGroup): member is RuleGroup {\n return 'conditions' in member;\n}\n\nconst normalize = (value: unknown) => (typeof value === 'string' ? value.trim().toLowerCase() : value);\nconst same = (left: unknown, right: unknown) => normalize(left) === normalize(right);\n\nfunction contains(actual: unknown, expected: unknown): boolean {\n if (Array.isArray(actual)) return actual.some(entry => same(entry, expected));\n if (typeof actual === 'string' && typeof expected === 'string') {\n return actual.toLowerCase().includes(expected.toLowerCase());\n }\n return false;\n}\n\nfunction compare(actual: unknown, expected: unknown, test: (left: number, right: number) => boolean): boolean {\n return typeof actual === 'number' && typeof expected === 'number' && test(actual, expected);\n}\n\n/**\n * Evaluate one condition. Strings compare case-insensitively (labels and\n * repository slugs are case-insensitive on every provider Factory reads). A\n * missing fact fails every operator except `not_exists`, `not_equals`,\n * `not_contains` and `not_in`.\n */\nfunction evaluateCondition(condition: RuleCondition, facts: RuleFacts): boolean {\n const actual = facts[condition.field];\n const present = actual !== undefined && actual !== null;\n const expected = condition.value;\n switch (condition.operator) {\n case 'exists':\n return present;\n case 'not_exists':\n return !present;\n case 'equals':\n return present && same(actual, expected);\n case 'not_equals':\n return !present || !same(actual, expected);\n case 'contains':\n return present && contains(actual, expected);\n case 'not_contains':\n return !present || !contains(actual, expected);\n case 'in':\n return present && Array.isArray(expected) && expected.some(candidate => same(actual, candidate));\n case 'not_in':\n return !present || !Array.isArray(expected) || !expected.some(candidate => same(actual, candidate));\n case 'greater_than':\n return compare(actual, expected, (left, right) => left > right);\n case 'less_than':\n return compare(actual, expected, (left, right) => left < right);\n case 'greater_than_or_equal':\n return compare(actual, expected, (left, right) => left >= right);\n case 'less_than_or_equal':\n return compare(actual, expected, (left, right) => left <= right);\n }\n}\n\n/** True when `facts` satisfy `group`. A `null`/absent group matches everything (an unconditional phase). */\nexport function evaluateRuleGroup(group: RuleGroup | null | undefined, facts: RuleFacts): boolean {\n if (!group) return true;\n const results = group.conditions.map(member =>\n isGroup(member) ? evaluateRuleGroup(member, facts) : evaluateCondition(member, facts),\n );\n return group.operator === 'AND' ? results.every(Boolean) : results.some(Boolean);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start-coordinator.d.ts","sourceRoot":"","sources":["../../src/rules/start-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAM9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AACvG,OAAO,KAAK,EAAwB,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAClH,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACnG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExE,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kGAAkG;IAClG,UAAU,EAAE,mBAAmB,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,mBAAmB,CAAC;KAC5B,CAAC;IACF,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"start-coordinator.d.ts","sourceRoot":"","sources":["../../src/rules/start-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAM9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AACvG,OAAO,KAAK,EAAwB,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAClH,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACnG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExE,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kGAAkG;IAClG,UAAU,EAAE,mBAAmB,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,mBAAmB,CAAC;KAC5B,CAAC;IACF,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM;IAAtC,YAAqB,SAAS,EAAE,MAAM,EAKrC;CACF;AAqBD,qBAAa,uBAAwB,SAAQ,KAAK;IAE9C,QAAQ,CAAC,IAAI,EAAE,qBAAqB,GAAG,sBAAsB,GAAG,qBAAqB;IAErF,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE;IAH/B,YACW,IAAI,EAAE,qBAAqB,GAAG,sBAAsB,GAAG,qBAAqB,EACrF,OAAO,EAAE,MAAM,EACN,UAAU,GAAE,MAAM,EAAO,EAInC;CACF;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,uBAAuB,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IAE1E,YAAY,MAAM,EAAE,OAAO,CAAC,uBAAuB,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,EAI3E;CACF;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAClE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,KAAK,iBAAiB,GAAG,eAAe,CAAC,eAAe,CAAC,CAAC;AA+B1D,qBAAa,uBAAuB;;IAalC,YACE,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,gBAAgB,EACzB,iBAAiB,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,YAAY,CAAC,EAChE,aAAa,CAAC,EACV,0BAA0B,GAC1B,CAAC,CACC,OAAO,EAAE,mBAAmB,KACzB,0BAA0B,GAAG,SAAS,GAAG,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAAC,EAClG,MAAM,CAAC,EAAE,aAAa,EACtB,YAAY,CAAC,EAAE;QAAE,QAAQ,EAAE,sBAAsB,CAAC;QAAC,aAAa,EAAE,oBAAoB,CAAA;KAAE,EASzF;IAEK,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA8M/E;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-cleanup.d.ts","sourceRoot":"","sources":["../../src/rules/terminal-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAEvG,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,IAAI,CACb,gBAAgB,EACd,KAAK,GACL,iBAAiB,GACjB,8BAA8B,GAC9B,uCAAuC,GACvC,yBAAyB,CAC5B,CAAC;IACF,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACzE;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,
|
|
1
|
+
{"version":3,"file":"terminal-cleanup.d.ts","sourceRoot":"","sources":["../../src/rules/terminal-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAEvG,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,IAAI,CACb,gBAAgB,EACd,KAAK,GACL,iBAAiB,GACjB,8BAA8B,GAC9B,uCAAuC,GACvC,yBAAyB,CAC5B,CAAC;IACF,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACzE;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,UACzD,wBAAwB,KAAG,OAAO,CAAC,IAAI,CAAC,CA8E7D"}
|
package/dist/rules/tools.d.ts
CHANGED
|
@@ -11,5 +11,5 @@ export declare function createFactoryTransitionTools(options: {
|
|
|
11
11
|
sessions?: FactorySessionSourceLookup;
|
|
12
12
|
boards?: BoardRegistry;
|
|
13
13
|
}): Promise<IntegrationTools>;
|
|
14
|
-
export declare const REVIEW_VERDICTS: readonly [
|
|
14
|
+
export declare const REVIEW_VERDICTS: readonly ['approve', 'request changes'];
|
|
15
15
|
//# 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,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC3F,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,CAqF5B;AAED,eAAO,MAAM,eAAe,
|
|
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;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC3F,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,CAqF5B;AAED,eAAO,MAAM,eAAe,YAAI,SAAS,EAAE,iBAAiB,CAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transition-service.d.ts","sourceRoot":"","sources":["../../src/rules/transition-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"transition-service.d.ts","sourceRoot":"","sources":["../../src/rules/transition-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { assertFactoryDecisionTarget, validateFactoryRuleDecision, validateFacto
|
|
|
3
3
|
import { createBoardRegistry } from "../boards/registry.js";
|
|
4
4
|
import "../boards/index.js";
|
|
5
5
|
import { isAgentActor } from "../storage/domains/work-items/base.js";
|
|
6
|
+
import { autoApprovedExitTool } from "../boards/phase-automation.js";
|
|
6
7
|
import { boardTransitionPolicyResultSchema, immutablePolicySnapshot } from "../boards/transition-policy.js";
|
|
7
8
|
import { resolveFactoryStageRules } from "./resolve.js";
|
|
8
9
|
// src/rules/transition-service.ts
|
|
@@ -73,6 +74,7 @@ function startsRun(decision) {
|
|
|
73
74
|
}
|
|
74
75
|
function runAlreadyUnderway(request, decision) {
|
|
75
76
|
if (request.cause === "run_start") return true;
|
|
77
|
+
if (decision.type === "invokeSkill" && decision.startsAfterOwnMove === true) return false;
|
|
76
78
|
return request.actor.type === "agent" && request.actor.role === decision.role;
|
|
77
79
|
}
|
|
78
80
|
function stageTransitionMessage(fromStage, toStage) {
|
|
@@ -220,7 +222,7 @@ var FactoryTransitionService = class {
|
|
|
220
222
|
if (!Object.prototype.hasOwnProperty.call(board.phases, request.stage) || !board.allowsTransition(fromStage, request.stage)) {
|
|
221
223
|
const nextStages = [...new Set((board.transitions[fromStage] ?? []).map((transition) => transition.to))];
|
|
222
224
|
const nextStagesReason = nextStages.length > 0 ? `Next stages declared from ${fromStage}: ${nextStages.join(", ")}.` : `No next stage is declared from ${fromStage}.`;
|
|
223
|
-
return this.#commitRejection(request, transitionId, "invalid_transition", `The ${board.
|
|
225
|
+
return this.#commitRejection(request, transitionId, "invalid_transition", `The ${board.name} board does not allow moving from ${fromStage} to ${request.stage}. ${nextStagesReason}`);
|
|
224
226
|
}
|
|
225
227
|
const humanMove = request.actor.type === "human" && fromStage !== request.stage && request.cause !== "run_start";
|
|
226
228
|
const entersWorking = board.isWorking(request.stage);
|
|
@@ -258,10 +260,10 @@ var FactoryTransitionService = class {
|
|
|
258
260
|
let evaluation;
|
|
259
261
|
try {
|
|
260
262
|
evaluation = await withRuleTimeout((async () => {
|
|
261
|
-
const plansAutoApproved = this.#autoApprovePlans ? await this.#autoApprovePlans({
|
|
263
|
+
const plansAutoApproved = autoApprovedExitTool(this.#boards, item) === "submit_plan" || (this.#autoApprovePlans ? await this.#autoApprovePlans({
|
|
262
264
|
orgId: request.orgId,
|
|
263
265
|
factoryProjectId: request.factoryProjectId
|
|
264
|
-
}) : false;
|
|
266
|
+
}) : false);
|
|
265
267
|
const policy = boardTransitionPolicyResultSchema.parse(await board.transitionPolicy?.(immutablePolicySnapshot({
|
|
266
268
|
...contextBase,
|
|
267
269
|
item: {
|