@mastra/factory 0.13.0-alpha.12 → 0.13.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -10
- package/dist/boards/define-board.d.ts +36 -2
- package/dist/boards/define-board.d.ts.map +1 -1
- package/dist/boards/define-board.js +51 -1
- package/dist/boards/define-board.js.map +1 -1
- package/dist/boards/index.d.ts +3 -1
- package/dist/boards/index.d.ts.map +1 -1
- package/dist/boards/index.js +2 -1
- package/dist/boards/index.js.map +1 -1
- package/dist/boards/review.d.ts.map +1 -1
- package/dist/boards/review.js +5 -0
- package/dist/boards/review.js.map +1 -1
- package/dist/boards/semantics.d.ts +28 -0
- package/dist/boards/semantics.d.ts.map +1 -0
- package/dist/boards/semantics.js +41 -0
- package/dist/boards/semantics.js.map +1 -0
- package/dist/boards/work-tool-rules.d.ts +8 -0
- package/dist/boards/work-tool-rules.d.ts.map +1 -0
- package/dist/boards/work-tool-rules.js +20 -0
- package/dist/boards/work-tool-rules.js.map +1 -0
- package/dist/boards/work.d.ts.map +1 -1
- package/dist/boards/work.js +14 -1
- package/dist/boards/work.js.map +1 -1
- package/dist/factory.d.ts +5 -6
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +19 -11
- package/dist/factory.js.map +1 -1
- package/dist/integrations/base.d.ts +7 -4
- package/dist/integrations/base.d.ts.map +1 -1
- package/dist/integrations/github/issue-reconciler.d.ts.map +1 -1
- package/dist/integrations/github/issue-reconciler.js +4 -3
- package/dist/integrations/github/issue-reconciler.js.map +1 -1
- package/dist/integrations/github/rules.d.ts +3 -2
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +11 -10
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/issue-reconciler.d.ts +2 -0
- package/dist/integrations/issue-reconciler.d.ts.map +1 -1
- package/dist/integrations/issue-reconciler.js +1 -3
- package/dist/integrations/issue-reconciler.js.map +1 -1
- package/dist/integrations/linear/issue-reconciler.d.ts.map +1 -1
- package/dist/integrations/linear/issue-reconciler.js +8 -4
- package/dist/integrations/linear/issue-reconciler.js.map +1 -1
- package/dist/integrations/linear/rules.d.ts +1 -2
- package/dist/integrations/linear/rules.d.ts.map +1 -1
- package/dist/integrations/linear/rules.js +5 -5
- package/dist/integrations/linear/rules.js.map +1 -1
- package/dist/integrations/platform/api-client.d.ts.map +1 -1
- package/dist/integrations/platform/api-client.js +25 -4
- package/dist/integrations/platform/api-client.js.map +1 -1
- package/dist/integrations/platform/linear/integration.js +1 -1
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/integrations/slack/emoji-shortcodes.generated.d.ts +8 -0
- package/dist/integrations/slack/emoji-shortcodes.generated.d.ts.map +1 -0
- package/dist/integrations/slack/emoji-shortcodes.generated.js +1985 -0
- package/dist/integrations/slack/emoji-shortcodes.generated.js.map +1 -0
- package/dist/integrations/slack/emoji.d.ts +3 -0
- package/dist/integrations/slack/emoji.d.ts.map +1 -0
- package/dist/integrations/slack/emoji.js +12 -0
- package/dist/integrations/slack/emoji.js.map +1 -0
- package/dist/integrations/slack/integration.js +1 -1
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +16 -2
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/routes/supervisor.d.ts +2 -0
- package/dist/routes/supervisor.d.ts.map +1 -1
- package/dist/routes/supervisor.js +2 -2
- package/dist/routes/supervisor.js.map +1 -1
- package/dist/routes/surface.d.ts +4 -4
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +14 -9
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/work-items.d.ts +1 -1
- package/dist/routes/work-items.d.ts.map +1 -1
- package/dist/routes/work-items.js +17 -15
- package/dist/routes/work-items.js.map +1 -1
- package/dist/rules/dispatcher.d.ts +3 -0
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +37 -6
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/index.d.ts +4 -5
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +3 -4
- package/dist/rules/processor.d.ts +3 -3
- package/dist/rules/processor.d.ts.map +1 -1
- package/dist/rules/processor.js +10 -12
- package/dist/rules/processor.js.map +1 -1
- package/dist/rules/resolve.d.ts +1 -3
- package/dist/rules/resolve.d.ts.map +1 -1
- package/dist/rules/resolve.js +1 -4
- package/dist/rules/resolve.js.map +1 -1
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +3 -1
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/rules/tools.d.ts.map +1 -1
- package/dist/rules/tools.js +3 -4
- package/dist/rules/tools.js.map +1 -1
- package/dist/rules/transition-service.d.ts +7 -7
- package/dist/rules/transition-service.d.ts.map +1 -1
- package/dist/rules/transition-service.js +20 -25
- package/dist/rules/transition-service.js.map +1 -1
- package/dist/rules/types.d.ts +1 -11
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.d.ts +7 -2
- package/dist/rules/validation.d.ts.map +1 -1
- package/dist/rules/validation.js +9 -15
- package/dist/rules/validation.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +9 -3
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +13 -17
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/supervisor/health-worker.d.ts +2 -0
- package/dist/supervisor/health-worker.d.ts.map +1 -1
- package/dist/supervisor/health-worker.js +3 -1
- package/dist/supervisor/health-worker.js.map +1 -1
- package/dist/supervisor/health.d.ts +10 -12
- package/dist/supervisor/health.d.ts.map +1 -1
- package/dist/supervisor/health.js +11 -40
- package/dist/supervisor/health.js.map +1 -1
- package/dist/supervisor/instructions.d.ts +1 -1
- package/dist/supervisor/instructions.d.ts.map +1 -1
- package/dist/supervisor/instructions.js +10 -8
- package/dist/supervisor/instructions.js.map +1 -1
- package/dist/supervisor/read-tools.d.ts +2 -0
- package/dist/supervisor/read-tools.d.ts.map +1 -1
- package/dist/supervisor/read-tools.js +2 -2
- package/dist/supervisor/read-tools.js.map +1 -1
- package/factory-skills/configure-factory-rules/SKILL.md +18 -10
- package/package.json +7 -7
- package/dist/rules/defaults.d.ts +0 -9
- package/dist/rules/defaults.d.ts.map +0 -1
- package/dist/rules/defaults.js +0 -50
- package/dist/rules/defaults.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-tools.js","names":[],"sources":["../../src/supervisor/read-tools.ts"],"sourcesContent":["/**\n * Supervisor read surface. Every tool is bounded (hard row caps, truncated\n * text) and answers with ids a person can click on the board, so the model\n * can explain a card's state without ever touching the database itself.\n */\n\nimport type { MastraDBMessage } from '@mastra/core/agent/message-list';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport type { IntegrationTools } from '../integrations/base.js';\nimport { factoryDispatchFailureMetadata } from '../rules/dispatch-errors.js';\nimport { FACTORY_RULE_STAGES, factoryRuleStage } from '../rules/types.js';\nimport type { FactoryRuleStage } from '../rules/types.js';\nimport type { AuditStorage } from '../storage/domains/audit/base.js';\nimport type { WorkItemCommentsStorage } from '../storage/domains/comments/base.js';\nimport type {\n FactoryDeferredDecisionRecord,\n WorkItemRow,\n WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\nimport type { FactoryHealthReport, FactoryHealthThresholds } from './health.js';\nimport { runFactoryHealthCheck } from './health.js';\n\nexport interface SupervisorScope {\n orgId: string;\n factoryProjectId: string;\n}\n\nexport interface SupervisorMessageReader {\n listMessages(input: {\n threadId: string;\n resourceId?: string;\n page: number;\n perPage: number;\n orderBy: { field: 'createdAt'; direction: 'ASC' | 'DESC' };\n }): Promise<{ messages: MastraDBMessage[]; hasMore: boolean }>;\n}\n\nexport interface SupervisorReadDependencies {\n scope: SupervisorScope;\n workItems: WorkItemsStorage;\n comments: WorkItemCommentsStorage;\n audit: AuditStorage;\n messageReader?: SupervisorMessageReader;\n healthThresholds?: FactoryHealthThresholds;\n now?: () => Date;\n}\n\nconst MAX_TEXT = 600;\nconst MAX_ERROR = 400;\nconst MAX_LIST = 50;\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\nfunction iso(value: Date | string | null | undefined): string | null {\n if (!value) return null;\n const date = value instanceof Date ? value : new Date(value);\n return Number.isFinite(date.getTime()) ? date.toISOString() : null;\n}\n\nfunction itemNumber(item: WorkItemRow): number | null {\n const number = item.metadata?.number ?? item.metadata?.githubIssueNumber ?? item.metadata?.githubPullRequestNumber;\n return typeof number === 'number' ? number : null;\n}\n\nfunction itemLabels(item: WorkItemRow): string[] {\n const labels = item.metadata?.labels;\n return Array.isArray(labels) ? labels.filter((label): label is string => typeof label === 'string') : [];\n}\n\nfunction summarizeItem(item: WorkItemRow) {\n return {\n id: item.id,\n number: itemNumber(item),\n title: item.title,\n stage: factoryRuleStage(item.stages) ?? item.stages.join('+'),\n source: item.externalSource ? `${item.externalSource.integrationId}:${item.externalSource.type}` : 'manual',\n url: typeof item.metadata?.url === 'string' ? item.metadata.url : null,\n triageType: item.triageType,\n acceptedAt: iso(item.acceptedAt),\n autonomyArmedAt: iso(item.autonomyArmedAt),\n parentWorkItemId: item.parentWorkItemId,\n revision: item.revision,\n updatedAt: iso(item.updatedAt),\n };\n}\n\nfunction summarizeDecision(decision: FactoryDeferredDecisionRecord) {\n const type = typeof decision.decision.type === 'string' ? decision.decision.type : 'decision';\n const role = typeof decision.decision.role === 'string' ? decision.decision.role : null;\n const skill = typeof decision.decision.skillName === 'string' ? decision.decision.skillName : null;\n return {\n id: decision.id,\n workItemId: decision.workItemId,\n type,\n role,\n skill,\n status: decision.status,\n attempts: decision.attempts,\n availableAt: iso(decision.availableAt),\n leaseOwner: decision.leaseOwner,\n leaseExpiresAt: iso(decision.leaseExpiresAt),\n failureCode: decision.failureCode,\n failureLabel: decision.failureCode ? factoryDispatchFailureMetadata(decision.failureCode).label : null,\n canRetry: decision.status === 'failed' ? factoryDispatchFailureMetadata(decision.failureCode).canRetry : false,\n lastError: decision.lastError ? truncate(decision.lastError, MAX_ERROR) : null,\n approvedBy: decision.approvedBy,\n createdAt: iso(decision.createdAt),\n updatedAt: iso(decision.updatedAt),\n completedAt: iso(decision.completedAt),\n };\n}\n\nfunction messageParts(content: unknown): unknown[] {\n if (Array.isArray(content)) return content;\n if (content && typeof content === 'object') {\n const parts = (content as { parts?: unknown }).parts;\n if (Array.isArray(parts)) return parts;\n }\n return [];\n}\n\nfunction messageText(message: MastraDBMessage): string {\n const content: unknown = message.content;\n const parts = messageParts(content);\n const text: string[] = [];\n for (const part of parts) {\n if (part && typeof part === 'object' && (part as { type?: unknown }).type === 'text') {\n const value = (part as { text?: unknown }).text;\n if (typeof value === 'string') text.push(value);\n }\n }\n if (text.length === 0 && typeof content === 'string') text.push(content);\n return text.join('\\n');\n}\n\nfunction messageToolCalls(message: MastraDBMessage): Array<{ tool: string; state: string | null }> {\n const parts = messageParts(message.content);\n const calls: Array<{ tool: string; state: string | null }> = [];\n for (const rawPart of parts) {\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 : typeof part.type === 'string' && part.type.startsWith('tool-')\n ? part\n : undefined;\n if (!invocation) continue;\n const name = invocation.toolName ?? invocation.name ?? (typeof part.type === 'string' ? part.type.slice(5) : null);\n if (typeof name !== 'string') continue;\n calls.push({ tool: name, state: typeof invocation.state === 'string' ? invocation.state : null });\n }\n return calls;\n}\n\nasync function findItem(\n deps: SupervisorReadDependencies,\n ref: { id?: string; number?: number },\n): Promise<WorkItemRow | null> {\n if (ref.id) return deps.workItems.getForProject(deps.scope.orgId, deps.scope.factoryProjectId, ref.id);\n if (ref.number === undefined) return null;\n const items = await deps.workItems.list(deps.scope);\n const matches = items.filter(item => itemNumber(item) === ref.number);\n // Issue and PR numbers share a space on GitHub; prefer the Work-board card.\n return matches.find(item => item.externalSource?.type !== 'pull-request') ?? matches[0] ?? null;\n}\n\nconst itemRefSchema = z\n .object({\n id: z.string().uuid().optional().describe('Work item id.'),\n number: z.number().int().positive().optional().describe('Card number as shown on the board, e.g. 22874.'),\n })\n .refine(ref => ref.id !== undefined || ref.number !== undefined, { message: 'Provide an id or a number.' });\n\nexport function createFactorySupervisorReadTools(deps: SupervisorReadDependencies): IntegrationTools {\n const now = deps.now ?? (() => new Date());\n const scope = deps.scope;\n\n return {\n factory_overview: createTool({\n id: 'factory_overview',\n description:\n 'Counts per pipeline stage, decisions by status, active seats, open proposals and held cards for this Factory. Start here for \"what needs me\" questions.',\n inputSchema: z.object({}).strict(),\n execute: async () => {\n const [items, decisions, bindings, pendingStarts] = await Promise.all([\n deps.workItems.list(scope),\n deps.workItems.listDeferredDecisions(scope.orgId, scope.factoryProjectId),\n deps.workItems.listRunBindings(scope.orgId, scope.factoryProjectId),\n deps.workItems.listPendingStarts(scope.orgId, scope.factoryProjectId),\n ]);\n const stages = Object.fromEntries(FACTORY_RULE_STAGES.map(stage => [stage, 0])) as Record<\n FactoryRuleStage,\n number\n >;\n let held = 0;\n for (const item of items) {\n const stage = factoryRuleStage(item.stages);\n if (stage) stages[stage] += 1;\n if (stage === 'triage' && item.triageType && item.triageType !== 'bug' && !item.acceptedAt) held += 1;\n }\n const decisionsByStatus: Record<string, number> = {};\n for (const decision of decisions) {\n decisionsByStatus[decision.status] = (decisionsByStatus[decision.status] ?? 0) + 1;\n }\n const activeSeats = bindings.filter(binding => binding.status === 'active');\n const seatsByRole: Record<string, number> = {};\n for (const seat of activeSeats) seatsByRole[seat.role] = (seatsByRole[seat.role] ?? 0) + 1;\n return {\n checkedAt: now().toISOString(),\n workItems: { total: items.length, byStage: stages, heldForDecision: held },\n decisions: decisionsByStatus,\n openProposals: decisions\n .filter(d => d.status === 'proposed')\n .map(summarizeDecision)\n .slice(0, MAX_LIST),\n failedDecisions: decisions\n .filter(d => d.status === 'failed')\n .map(summarizeDecision)\n .slice(0, MAX_LIST),\n activeSeats: { total: activeSeats.length, byRole: seatsByRole },\n pendingStarts: pendingStarts.filter(start => start.status !== 'sent').length,\n };\n },\n }),\n\n factory_health_check: createTool({\n id: 'factory_health_check',\n description:\n 'Deterministic list of things wrong with this Factory right now (failed or stuck decisions, stalled starts, orphaned or missing seats, proposals and held cards waiting on a person, label drift). Each finding carries evidence and the standard repair. Explain these; do not invent findings that are not listed.',\n inputSchema: z.object({}).strict(),\n execute: async (): Promise<FactoryHealthReport> =>\n runFactoryHealthCheck(deps.workItems, scope, { now: now(), thresholds: deps.healthThresholds }),\n }),\n\n factory_inspect_work_item: createTool({\n id: 'factory_inspect_work_item',\n description:\n 'Everything the Factory knows about one card: row, stage history, seats (run bindings), decisions with errors, recent audit events, recent feed comments, linked parent/children and last observed labels. Use for \"why is #N in this state\".',\n inputSchema: itemRefSchema,\n execute: async ref => {\n const item = await findItem(deps, ref);\n if (!item) throw new Error(`No work item matches ${ref.id ?? `#${ref.number}`} in this Factory.`);\n const [decisions, bindings, audit, feed, all] = await Promise.all([\n deps.workItems.listDeferredDecisions(scope.orgId, scope.factoryProjectId),\n deps.workItems.listRunBindings(scope.orgId, scope.factoryProjectId, item.id),\n deps.audit.list({ orgId: scope.orgId, factoryProjectId: scope.factoryProjectId, limit: 200 }),\n deps.comments.listRecent({ ...scope, workItemId: item.id, limit: 10 }),\n deps.workItems.list(scope),\n ]);\n const parent = item.parentWorkItemId\n ? all.find(candidate => candidate.id === item.parentWorkItemId)\n : undefined;\n const children = all.filter(candidate => candidate.parentWorkItemId === item.id);\n return {\n item: summarizeItem(item),\n labels: itemLabels(item),\n stageHistory: item.stageHistory.map(entry => ({\n stage: entry.stage,\n enteredAt: entry.enteredAt,\n exitedAt: entry.exitedAt ?? null,\n by: entry.by,\n })),\n sessions: Object.entries(item.sessions).map(([role, ref]) => ({\n role,\n sessionId: ref.sessionId,\n threadId: ref.threadId,\n branch: ref.branch,\n startedBy: ref.startedBy,\n })),\n seats: bindings.map(binding => ({\n id: binding.id,\n role: binding.role,\n status: binding.status,\n sessionId: binding.sessionId,\n threadId: binding.threadId,\n createdAt: iso(binding.createdAt),\n revokedAt: iso(binding.revokedAt),\n })),\n decisions: decisions\n .filter(decision => decision.workItemId === item.id)\n .map(summarizeDecision)\n .slice(-MAX_LIST),\n audit: audit.events\n .filter(event => event.targets.some(target => target.type === 'work_item' && target.id === item.id))\n .slice(0, 25)\n .map(event => ({\n id: event.id,\n action: event.action,\n actorId: event.actorId,\n actorType: event.actorType,\n occurredAt: iso(event.occurredAt),\n metadata: event.metadata,\n })),\n feed: feed.map(comment => ({\n id: comment.id,\n kind: comment.kind,\n author: comment.author,\n occurredAt: iso(comment.occurredAt),\n body: truncate(comment.body, MAX_TEXT),\n })),\n parent: parent ? summarizeItem(parent) : null,\n children: children.map(summarizeItem),\n };\n },\n }),\n\n factory_list_attention: createTool({\n id: 'factory_list_attention',\n description:\n 'Failed decisions grouped by failure code and error text, so a batch of cards that broke the same way reads as one incident. Also lists proposals waiting on a person and terminal cards that still hold seats.',\n inputSchema: z.object({ limit: z.number().int().min(1).max(MAX_LIST).default(25) }).strict(),\n execute: async ({ limit }) => {\n const [decisions, items] = await Promise.all([\n deps.workItems.listDeferredDecisions(scope.orgId, scope.factoryProjectId),\n deps.workItems.list(scope),\n ]);\n const itemsById = new Map(items.map(item => [item.id, item]));\n const groups = new Map<\n string,\n { failureCode: string; error: string; decisions: FactoryDeferredDecisionRecord[] }\n >();\n for (const decision of decisions) {\n if (decision.status !== 'failed') continue;\n const error = truncate(decision.lastError ?? '', 160);\n const key = `${decision.failureCode ?? 'unknown'}|${error}`;\n const group = groups.get(key) ?? { failureCode: decision.failureCode ?? 'unknown', error, decisions: [] };\n group.decisions.push(decision);\n groups.set(key, group);\n }\n const incidents = [...groups.values()]\n .sort((a, b) => b.decisions.length - a.decisions.length)\n .slice(0, limit)\n .map(group => ({\n failureCode: group.failureCode,\n failureLabel: factoryDispatchFailureMetadata(group.decisions[0]!.failureCode).label,\n error: group.error,\n count: group.decisions.length,\n firstFailedAt: iso(\n new Date(\n group.decisions.reduce(\n (earliest, decision) => Math.min(earliest, decision.updatedAt.getTime()),\n Infinity,\n ),\n ),\n ),\n lastFailedAt: iso(\n new Date(\n group.decisions.reduce((latest, decision) => Math.max(latest, decision.updatedAt.getTime()), -Infinity),\n ),\n ),\n decisions: group.decisions.slice(0, limit).map(decision => {\n const item = decision.workItemId ? itemsById.get(decision.workItemId) : undefined;\n return {\n id: decision.id,\n workItemId: decision.workItemId,\n number: item ? itemNumber(item) : null,\n title: item?.title ?? null,\n attempts: decision.attempts,\n };\n }),\n }));\n return {\n incidents,\n proposals: decisions\n .filter(d => d.status === 'proposed')\n .slice(0, limit)\n .map(summarizeDecision),\n };\n },\n }),\n\n factory_read_session: createTool({\n id: 'factory_read_session',\n description:\n \"The most recent turns of a card's shared agent thread: who spoke, when, the text (truncated) and which tools were called. Use to see what a worker actually did. Give a work item (id or number) or a threadId.\",\n inputSchema: z\n .object({\n id: z.string().uuid().optional(),\n number: z.number().int().positive().optional(),\n threadId: z.string().min(1).optional(),\n limit: z.number().int().min(1).max(40).default(20),\n })\n .strict()\n .refine(ref => ref.id !== undefined || ref.number !== undefined || ref.threadId !== undefined, {\n message: 'Provide a work item id, a number, or a threadId.',\n }),\n execute: async ({ limit, ...ref }) => {\n if (!deps.messageReader) throw new Error('Session transcripts are not available on this deployment.');\n let threadId = ref.threadId;\n let resourceId: string | undefined;\n if (!threadId) {\n const item = await findItem(deps, ref);\n if (!item) throw new Error(`No work item matches ${ref.id ?? `#${ref.number}`} in this Factory.`);\n const session = Object.values(item.sessions)[0];\n if (!session) return { threadId: null, item: summarizeItem(item), turns: [] };\n threadId = session.threadId;\n resourceId = session.sessionId;\n } else {\n // A thread the caller named must still belong to a card in this Factory.\n const bindings = await deps.workItems.listRunBindings(scope.orgId, scope.factoryProjectId);\n const binding = bindings.find(candidate => candidate.threadId === threadId);\n if (!binding) throw new Error(`Thread ${threadId} is not bound to a card in this Factory.`);\n resourceId = binding.resourceId;\n }\n const page = await deps.messageReader.listMessages({\n threadId,\n ...(resourceId ? { resourceId } : {}),\n page: 0,\n perPage: limit,\n orderBy: { field: 'createdAt', direction: 'DESC' },\n });\n const turns = [...page.messages].reverse().map(message => ({\n id: message.id,\n role: message.role,\n createdAt: iso(message.createdAt),\n text: truncate(messageText(message), MAX_TEXT),\n tools: messageToolCalls(message),\n }));\n return { threadId, hasOlder: page.hasMore, turns };\n },\n }),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"read-tools.js","names":[],"sources":["../../src/supervisor/read-tools.ts"],"sourcesContent":["/**\n * Supervisor read surface. Every tool is bounded (hard row caps, truncated\n * text) and answers with ids a person can click on the board, so the model\n * can explain a card's state without ever touching the database itself.\n */\n\nimport type { MastraDBMessage } from '@mastra/core/agent/message-list';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { IntegrationTools } from '../integrations/base.js';\nimport { factoryDispatchFailureMetadata } from '../rules/dispatch-errors.js';\nimport { FACTORY_RULE_STAGES, factoryRuleStage } from '../rules/types.js';\nimport type { FactoryRuleStage } from '../rules/types.js';\nimport type { AuditStorage } from '../storage/domains/audit/base.js';\nimport type { WorkItemCommentsStorage } from '../storage/domains/comments/base.js';\nimport type {\n FactoryDeferredDecisionRecord,\n WorkItemRow,\n WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\nimport type { FactoryHealthReport, FactoryHealthThresholds } from './health.js';\nimport { runFactoryHealthCheck } from './health.js';\n\nexport interface SupervisorScope {\n orgId: string;\n factoryProjectId: string;\n}\n\nexport interface SupervisorMessageReader {\n listMessages(input: {\n threadId: string;\n resourceId?: string;\n page: number;\n perPage: number;\n orderBy: { field: 'createdAt'; direction: 'ASC' | 'DESC' };\n }): Promise<{ messages: MastraDBMessage[]; hasMore: boolean }>;\n}\n\nexport interface SupervisorReadDependencies {\n scope: SupervisorScope;\n workItems: WorkItemsStorage;\n boards: BoardRegistry;\n comments: WorkItemCommentsStorage;\n audit: AuditStorage;\n messageReader?: SupervisorMessageReader;\n healthThresholds?: FactoryHealthThresholds;\n now?: () => Date;\n}\n\nconst MAX_TEXT = 600;\nconst MAX_ERROR = 400;\nconst MAX_LIST = 50;\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\nfunction iso(value: Date | string | null | undefined): string | null {\n if (!value) return null;\n const date = value instanceof Date ? value : new Date(value);\n return Number.isFinite(date.getTime()) ? date.toISOString() : null;\n}\n\nfunction itemNumber(item: WorkItemRow): number | null {\n const number = item.metadata?.number ?? item.metadata?.githubIssueNumber ?? item.metadata?.githubPullRequestNumber;\n return typeof number === 'number' ? number : null;\n}\n\nfunction itemLabels(item: WorkItemRow): string[] {\n const labels = item.metadata?.labels;\n return Array.isArray(labels) ? labels.filter((label): label is string => typeof label === 'string') : [];\n}\n\nfunction summarizeItem(item: WorkItemRow) {\n return {\n id: item.id,\n number: itemNumber(item),\n title: item.title,\n stage: factoryRuleStage(item.stages) ?? item.stages.join('+'),\n source: item.externalSource ? `${item.externalSource.integrationId}:${item.externalSource.type}` : 'manual',\n url: typeof item.metadata?.url === 'string' ? item.metadata.url : null,\n triageType: item.triageType,\n acceptedAt: iso(item.acceptedAt),\n autonomyArmedAt: iso(item.autonomyArmedAt),\n parentWorkItemId: item.parentWorkItemId,\n revision: item.revision,\n updatedAt: iso(item.updatedAt),\n };\n}\n\nfunction summarizeDecision(decision: FactoryDeferredDecisionRecord) {\n const type = typeof decision.decision.type === 'string' ? decision.decision.type : 'decision';\n const role = typeof decision.decision.role === 'string' ? decision.decision.role : null;\n const skill = typeof decision.decision.skillName === 'string' ? decision.decision.skillName : null;\n return {\n id: decision.id,\n workItemId: decision.workItemId,\n type,\n role,\n skill,\n status: decision.status,\n attempts: decision.attempts,\n availableAt: iso(decision.availableAt),\n leaseOwner: decision.leaseOwner,\n leaseExpiresAt: iso(decision.leaseExpiresAt),\n failureCode: decision.failureCode,\n failureLabel: decision.failureCode ? factoryDispatchFailureMetadata(decision.failureCode).label : null,\n canRetry: decision.status === 'failed' ? factoryDispatchFailureMetadata(decision.failureCode).canRetry : false,\n lastError: decision.lastError ? truncate(decision.lastError, MAX_ERROR) : null,\n approvedBy: decision.approvedBy,\n createdAt: iso(decision.createdAt),\n updatedAt: iso(decision.updatedAt),\n completedAt: iso(decision.completedAt),\n };\n}\n\nfunction messageParts(content: unknown): unknown[] {\n if (Array.isArray(content)) return content;\n if (content && typeof content === 'object') {\n const parts = (content as { parts?: unknown }).parts;\n if (Array.isArray(parts)) return parts;\n }\n return [];\n}\n\nfunction messageText(message: MastraDBMessage): string {\n const content: unknown = message.content;\n const parts = messageParts(content);\n const text: string[] = [];\n for (const part of parts) {\n if (part && typeof part === 'object' && (part as { type?: unknown }).type === 'text') {\n const value = (part as { text?: unknown }).text;\n if (typeof value === 'string') text.push(value);\n }\n }\n if (text.length === 0 && typeof content === 'string') text.push(content);\n return text.join('\\n');\n}\n\nfunction messageToolCalls(message: MastraDBMessage): Array<{ tool: string; state: string | null }> {\n const parts = messageParts(message.content);\n const calls: Array<{ tool: string; state: string | null }> = [];\n for (const rawPart of parts) {\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 : typeof part.type === 'string' && part.type.startsWith('tool-')\n ? part\n : undefined;\n if (!invocation) continue;\n const name = invocation.toolName ?? invocation.name ?? (typeof part.type === 'string' ? part.type.slice(5) : null);\n if (typeof name !== 'string') continue;\n calls.push({ tool: name, state: typeof invocation.state === 'string' ? invocation.state : null });\n }\n return calls;\n}\n\nasync function findItem(\n deps: SupervisorReadDependencies,\n ref: { id?: string; number?: number },\n): Promise<WorkItemRow | null> {\n if (ref.id) return deps.workItems.getForProject(deps.scope.orgId, deps.scope.factoryProjectId, ref.id);\n if (ref.number === undefined) return null;\n const items = await deps.workItems.list(deps.scope);\n const matches = items.filter(item => itemNumber(item) === ref.number);\n // Issue and PR numbers share a space on GitHub; prefer the Work-board card.\n return matches.find(item => item.externalSource?.type !== 'pull-request') ?? matches[0] ?? null;\n}\n\nconst itemRefSchema = z\n .object({\n id: z.string().uuid().optional().describe('Work item id.'),\n number: z.number().int().positive().optional().describe('Card number as shown on the board, e.g. 22874.'),\n })\n .refine(ref => ref.id !== undefined || ref.number !== undefined, { message: 'Provide an id or a number.' });\n\nexport function createFactorySupervisorReadTools(deps: SupervisorReadDependencies): IntegrationTools {\n const now = deps.now ?? (() => new Date());\n const scope = deps.scope;\n\n return {\n factory_overview: createTool({\n id: 'factory_overview',\n description:\n 'Counts per pipeline stage, decisions by status, active seats, open proposals and held cards for this Factory. Start here for \"what needs me\" questions.',\n inputSchema: z.object({}).strict(),\n execute: async () => {\n const [items, decisions, bindings, pendingStarts] = await Promise.all([\n deps.workItems.list(scope),\n deps.workItems.listDeferredDecisions(scope.orgId, scope.factoryProjectId),\n deps.workItems.listRunBindings(scope.orgId, scope.factoryProjectId),\n deps.workItems.listPendingStarts(scope.orgId, scope.factoryProjectId),\n ]);\n const stages = Object.fromEntries(FACTORY_RULE_STAGES.map(stage => [stage, 0])) as Record<\n FactoryRuleStage,\n number\n >;\n let held = 0;\n for (const item of items) {\n const stage = factoryRuleStage(item.stages);\n if (stage) stages[stage] += 1;\n if (stage === 'triage' && item.triageType && item.triageType !== 'bug' && !item.acceptedAt) held += 1;\n }\n const decisionsByStatus: Record<string, number> = {};\n for (const decision of decisions) {\n decisionsByStatus[decision.status] = (decisionsByStatus[decision.status] ?? 0) + 1;\n }\n const activeSeats = bindings.filter(binding => binding.status === 'active');\n const seatsByRole: Record<string, number> = {};\n for (const seat of activeSeats) seatsByRole[seat.role] = (seatsByRole[seat.role] ?? 0) + 1;\n return {\n checkedAt: now().toISOString(),\n workItems: { total: items.length, byStage: stages, heldForDecision: held },\n decisions: decisionsByStatus,\n openProposals: decisions\n .filter(d => d.status === 'proposed')\n .map(summarizeDecision)\n .slice(0, MAX_LIST),\n failedDecisions: decisions\n .filter(d => d.status === 'failed')\n .map(summarizeDecision)\n .slice(0, MAX_LIST),\n activeSeats: { total: activeSeats.length, byRole: seatsByRole },\n pendingStarts: pendingStarts.filter(start => start.status !== 'sent').length,\n };\n },\n }),\n\n factory_health_check: createTool({\n id: 'factory_health_check',\n description:\n 'Deterministic list of things wrong with this Factory right now (stuck decisions, stalled starts, orphaned or missing seats, held cards waiting on a person, label drift). Each finding carries evidence and the standard repair. Explain these; do not invent findings that are not listed.',\n inputSchema: z.object({}).strict(),\n execute: async (): Promise<FactoryHealthReport> =>\n runFactoryHealthCheck(deps.workItems, deps.boards, scope, { now: now(), thresholds: deps.healthThresholds }),\n }),\n\n factory_inspect_work_item: createTool({\n id: 'factory_inspect_work_item',\n description:\n 'Everything the Factory knows about one card: row, stage history, seats (run bindings), decisions with errors, recent audit events, recent feed comments, linked parent/children and last observed labels. Use for \"why is #N in this state\".',\n inputSchema: itemRefSchema,\n execute: async ref => {\n const item = await findItem(deps, ref);\n if (!item) throw new Error(`No work item matches ${ref.id ?? `#${ref.number}`} in this Factory.`);\n const [decisions, bindings, audit, feed, all] = await Promise.all([\n deps.workItems.listDeferredDecisions(scope.orgId, scope.factoryProjectId),\n deps.workItems.listRunBindings(scope.orgId, scope.factoryProjectId, item.id),\n deps.audit.list({ orgId: scope.orgId, factoryProjectId: scope.factoryProjectId, limit: 200 }),\n deps.comments.listRecent({ ...scope, workItemId: item.id, limit: 10 }),\n deps.workItems.list(scope),\n ]);\n const parent = item.parentWorkItemId\n ? all.find(candidate => candidate.id === item.parentWorkItemId)\n : undefined;\n const children = all.filter(candidate => candidate.parentWorkItemId === item.id);\n return {\n item: summarizeItem(item),\n labels: itemLabels(item),\n stageHistory: item.stageHistory.map(entry => ({\n stage: entry.stage,\n enteredAt: entry.enteredAt,\n exitedAt: entry.exitedAt ?? null,\n by: entry.by,\n })),\n sessions: Object.entries(item.sessions).map(([role, ref]) => ({\n role,\n sessionId: ref.sessionId,\n threadId: ref.threadId,\n branch: ref.branch,\n startedBy: ref.startedBy,\n })),\n seats: bindings.map(binding => ({\n id: binding.id,\n role: binding.role,\n status: binding.status,\n sessionId: binding.sessionId,\n threadId: binding.threadId,\n createdAt: iso(binding.createdAt),\n revokedAt: iso(binding.revokedAt),\n })),\n decisions: decisions\n .filter(decision => decision.workItemId === item.id)\n .map(summarizeDecision)\n .slice(-MAX_LIST),\n audit: audit.events\n .filter(event => event.targets.some(target => target.type === 'work_item' && target.id === item.id))\n .slice(0, 25)\n .map(event => ({\n id: event.id,\n action: event.action,\n actorId: event.actorId,\n actorType: event.actorType,\n occurredAt: iso(event.occurredAt),\n metadata: event.metadata,\n })),\n feed: feed.map(comment => ({\n id: comment.id,\n kind: comment.kind,\n author: comment.author,\n occurredAt: iso(comment.occurredAt),\n body: truncate(comment.body, MAX_TEXT),\n })),\n parent: parent ? summarizeItem(parent) : null,\n children: children.map(summarizeItem),\n };\n },\n }),\n\n factory_list_attention: createTool({\n id: 'factory_list_attention',\n description:\n 'Failed decisions grouped by failure code and error text, so a batch of cards that broke the same way reads as one incident. Also lists proposals waiting on a person and terminal cards that still hold seats.',\n inputSchema: z.object({ limit: z.number().int().min(1).max(MAX_LIST).default(25) }).strict(),\n execute: async ({ limit }) => {\n const [decisions, items] = await Promise.all([\n deps.workItems.listDeferredDecisions(scope.orgId, scope.factoryProjectId),\n deps.workItems.list(scope),\n ]);\n const itemsById = new Map(items.map(item => [item.id, item]));\n const groups = new Map<\n string,\n { failureCode: string; error: string; decisions: FactoryDeferredDecisionRecord[] }\n >();\n for (const decision of decisions) {\n if (decision.status !== 'failed') continue;\n const error = truncate(decision.lastError ?? '', 160);\n const key = `${decision.failureCode ?? 'unknown'}|${error}`;\n const group = groups.get(key) ?? { failureCode: decision.failureCode ?? 'unknown', error, decisions: [] };\n group.decisions.push(decision);\n groups.set(key, group);\n }\n const incidents = [...groups.values()]\n .sort((a, b) => b.decisions.length - a.decisions.length)\n .slice(0, limit)\n .map(group => ({\n failureCode: group.failureCode,\n failureLabel: factoryDispatchFailureMetadata(group.decisions[0]!.failureCode).label,\n error: group.error,\n count: group.decisions.length,\n firstFailedAt: iso(\n new Date(\n group.decisions.reduce(\n (earliest, decision) => Math.min(earliest, decision.updatedAt.getTime()),\n Infinity,\n ),\n ),\n ),\n lastFailedAt: iso(\n new Date(\n group.decisions.reduce((latest, decision) => Math.max(latest, decision.updatedAt.getTime()), -Infinity),\n ),\n ),\n decisions: group.decisions.slice(0, limit).map(decision => {\n const item = decision.workItemId ? itemsById.get(decision.workItemId) : undefined;\n return {\n id: decision.id,\n workItemId: decision.workItemId,\n number: item ? itemNumber(item) : null,\n title: item?.title ?? null,\n attempts: decision.attempts,\n };\n }),\n }));\n return {\n incidents,\n proposals: decisions\n .filter(d => d.status === 'proposed')\n .slice(0, limit)\n .map(summarizeDecision),\n };\n },\n }),\n\n factory_read_session: createTool({\n id: 'factory_read_session',\n description:\n \"The most recent turns of a card's shared agent thread: who spoke, when, the text (truncated) and which tools were called. Use to see what a worker actually did. Give a work item (id or number) or a threadId.\",\n inputSchema: z\n .object({\n id: z.string().uuid().optional(),\n number: z.number().int().positive().optional(),\n threadId: z.string().min(1).optional(),\n limit: z.number().int().min(1).max(40).default(20),\n })\n .strict()\n .refine(ref => ref.id !== undefined || ref.number !== undefined || ref.threadId !== undefined, {\n message: 'Provide a work item id, a number, or a threadId.',\n }),\n execute: async ({ limit, ...ref }) => {\n if (!deps.messageReader) throw new Error('Session transcripts are not available on this deployment.');\n let threadId = ref.threadId;\n let resourceId: string | undefined;\n if (!threadId) {\n const item = await findItem(deps, ref);\n if (!item) throw new Error(`No work item matches ${ref.id ?? `#${ref.number}`} in this Factory.`);\n const session = Object.values(item.sessions)[0];\n if (!session) return { threadId: null, item: summarizeItem(item), turns: [] };\n threadId = session.threadId;\n resourceId = session.sessionId;\n } else {\n // A thread the caller named must still belong to a card in this Factory.\n const bindings = await deps.workItems.listRunBindings(scope.orgId, scope.factoryProjectId);\n const binding = bindings.find(candidate => candidate.threadId === threadId);\n if (!binding) throw new Error(`Thread ${threadId} is not bound to a card in this Factory.`);\n resourceId = binding.resourceId;\n }\n const page = await deps.messageReader.listMessages({\n threadId,\n ...(resourceId ? { resourceId } : {}),\n page: 0,\n perPage: limit,\n orderBy: { field: 'createdAt', direction: 'DESC' },\n });\n const turns = [...page.messages].reverse().map(message => ({\n id: message.id,\n role: message.role,\n createdAt: iso(message.createdAt),\n text: truncate(messageText(message), MAX_TEXT),\n tools: messageToolCalls(message),\n }));\n return { threadId, hasOlder: page.hasMore, turns };\n },\n }),\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: configure-factory-rules
|
|
3
|
-
description: Configure
|
|
3
|
+
description: Configure board-owned lifecycle, policy, phase-semantics, and tool-result rules, plus integration event rules
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Configure Factory Rules
|
|
@@ -9,10 +9,10 @@ Help the user change Factory policy in the typed deployment configuration. Facto
|
|
|
9
9
|
|
|
10
10
|
## Find the configuration
|
|
11
11
|
|
|
12
|
-
1. Search for `new MastraFactory`, its `boards` and `includeDefaultBoards` options, `defineBoard`, `
|
|
12
|
+
1. Search for `new MastraFactory`, its `boards` and `includeDefaultBoards` options, `defineBoard`, `configVersion`, and the installed `GithubIntegration`, `PlatformGithubIntegration`, `LinearIntegration`, or `PlatformLinearIntegration` constructors and their `rules` options.
|
|
13
13
|
2. Read the existing rule configuration and its tests before editing.
|
|
14
14
|
3. Import rule helpers and types from the same local Factory module used by the deployment.
|
|
15
|
-
4. For custom-board handlers, edit the installed `defineBoard()` definition. For tool rules,
|
|
15
|
+
4. For custom-board handlers or phase semantics (`kind`, `role`), edit the installed `defineBoard()` definition. For tool-result rules, add `tools: { <toolName>: { onResult } }` to the installed `defineBoard()` definition of the board whose seat produces the result. For GitHub or Linear rules, configure the installed integration constructor directly.
|
|
16
16
|
|
|
17
17
|
Do not guess a file path. Factory deployments can assemble `MastraFactory` from different entry points.
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@ Do not guess a file path. Factory deployments can assemble `MastraFactory` from
|
|
|
20
20
|
|
|
21
21
|
Installed board definitions exclusively own lifecycle handlers: use `phases.<phase>.onEnter.<source>` and `phases.<phase>.onExit.<source>` in `defineBoard()`. Sources are `issue`, `pullRequest`, `linearIssue`, and `manual`. Work and Review install automatically with preferred defaults. Custom boards are installed through `boards`; `includeDefaultBoards: false` supports custom-only installations.
|
|
22
22
|
|
|
23
|
-
Remove former global `rules.work` and `rules.review` configuration. Built-in customization is deferred: do not invent a board override API, derive replacements, or use reserved IDs `work` and `review`.
|
|
23
|
+
Remove former global `rules.work` and `rules.review` configuration. Built-in customization is deferred: do not invent a board override API, derive replacements, or use reserved IDs `work` and `review`. There is no global rules tree; `new MastraFactory({ rules })` throws. Set `configVersion` on `MastraFactory` for the audit label. Tool-result rules resolve only from the item's installed board: Work declares `submit_plan`, Review declares none, and custom boards inherit nothing.
|
|
24
24
|
|
|
25
25
|
Work automatic intake requires both `linked_item_materialized` and `autoStartCandidate: true`. Do not remove these guards to reproduce the web deployment's former unconditional intake override. Noncandidate and manual arrivals stay unstarted merely from entering Intake; explicit issue triage and human-approval safeguards remain. Linear Intake and Review retain their existing defaults and guards.
|
|
26
26
|
|
|
@@ -58,15 +58,23 @@ The policy receives a deeply readonly snapshot with ISO-string dates. Return `un
|
|
|
58
58
|
|
|
59
59
|
Policies must be side-effect-free and share the lifecycle timeout budget. Initial entry, reentry, and same-stage requests evaluate policy; completed replay does not. Concurrent attempts may evaluate more than once, and timing out does not cancel work started by a callback. Do not access storage or integrations from a policy.
|
|
60
60
|
|
|
61
|
-
Policy allowance cannot bypass topology, board ownership, ingress authorization, external-author safety, revision checks, replay, or decision validation.
|
|
61
|
+
Policy allowance cannot bypass topology, board ownership, ingress authorization, external-author safety, revision checks, replay, or decision validation. Phase meaning is declared on the phase (`kind`), not in the policy. Do not invent built-in replacement APIs.
|
|
62
62
|
|
|
63
|
-
##
|
|
63
|
+
## Configure board phase semantics
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Every phase in `defineBoard()` requires `kind: 'resting' | 'working' | 'terminal'`; working phases also require `role`. Read `src/boards/define-board.ts` for validation and the derived helpers (`phaseKind`, `isWorking`, `isTerminal`, `roleForPhase`, `phaseForRole`) and `src/boards/semantics.ts` for how runtime resolves an item's board and phase. Work and Review declarations live in `src/boards/work.ts` and `src/boards/review.ts`.
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
Runtime reads the installed board's declarations for consent arming, the external-author guard, kickoff seating, run-start lanes, terminal cleanup, sweeps, and supervisor findings; nothing name-matches phases, and custom boards inherit nothing from Work. `initialPhase` must be resting. Unknown board or phase fails closed: consent is requested, nothing is cleaned up, no seat is started or revoked.
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
To make a custom phase terminal or seat an agent in it, change its `kind`/`role` in the definition. Do not add phase-name checks to the transition service, dispatcher, sweeps, or supervisor. Decision and tool-input validation still accept only built-in board IDs and phase names, so custom-board handlers cannot emit `transition` decisions into custom phases yet.
|
|
70
|
+
|
|
71
|
+
## Change a built-in handler
|
|
72
|
+
|
|
73
|
+
Integration overrides (`rules[event]` on the GitHub/Linear constructor) replace one event handler; they do not compose with the built-in handler, and siblings remain unchanged. There is no override mechanism for board-owned handlers, including Work's `submit_plan` tool-result rule: change the installed definition itself (`src/boards/work.ts`, handler in `src/boards/work-tool-rules.ts`) or install a custom board that declares its own `tools`.
|
|
74
|
+
|
|
75
|
+
Before changing a built-in handler:
|
|
76
|
+
|
|
77
|
+
1. Find and read it: GitHub handlers live in `src/integrations/github/default-rules.ts`, Linear handlers in `src/integrations/linear/default-rules.ts`, Work's tool-result handler in `src/boards/work-tool-rules.ts`, and Work and Review lifecycle/policy defaults in `src/boards/work.ts` and `src/boards/review.ts`. Custom handlers live in their installed definitions.
|
|
70
78
|
2. Decide whether the replacement must preserve part of that behavior explicitly.
|
|
71
79
|
3. Use only fields exposed by the typed context. Do not reach into Factory storage or raw webhook payloads.
|
|
72
80
|
4. Return `undefined` to allow the ingress with no decision, or return a typed rejection or bounded structured decision.
|
|
@@ -74,7 +82,7 @@ Before replacing a built-in leaf:
|
|
|
74
82
|
|
|
75
83
|
## Version changes
|
|
76
84
|
|
|
77
|
-
Set an explicit, deployment-owned `
|
|
85
|
+
Set an explicit, deployment-owned `configVersion` on `MastraFactory`. Change it whenever rule behavior changes. It labels persisted evaluations and audit records (stored in the `rule_set_version` column); it must not be used as event identity or added to ingress deduplication keys.
|
|
78
86
|
|
|
79
87
|
## Safety rules
|
|
80
88
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/factory",
|
|
3
|
-
"version": "0.13.0-alpha.
|
|
3
|
+
"version": "0.13.0-alpha.13",
|
|
4
4
|
"description": "Mastra Software Factory module: the server core behind the Mastra Software Factory — storage domains, integrations, and surfaces for agent-powered software delivery",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -57,10 +57,10 @@
|
|
|
57
57
|
"hono": "^4.12.8",
|
|
58
58
|
"zod": "^4.3.6",
|
|
59
59
|
"@mastra/auth-workos": "1.6.5",
|
|
60
|
+
"@mastra/code-sdk": "1.7.0-alpha.10",
|
|
61
|
+
"@mastra/slack": "1.6.3",
|
|
60
62
|
"@mastra/auth-studio": "1.3.5",
|
|
61
|
-
"@mastra/
|
|
62
|
-
"@mastra/core": "1.65.0-alpha.8",
|
|
63
|
-
"@mastra/slack": "1.6.3"
|
|
63
|
+
"@mastra/core": "1.65.0-alpha.9"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@types/node": "22.20.1",
|
|
@@ -69,11 +69,11 @@
|
|
|
69
69
|
"typescript": "^6.0.3",
|
|
70
70
|
"typescript-eslint": "^8.57.0",
|
|
71
71
|
"vitest": "4.1.10",
|
|
72
|
+
"@internal/lint": "0.0.130",
|
|
72
73
|
"@mastra/libsql": "1.22.4-alpha.0",
|
|
73
|
-
"@internal/types-builder": "0.0.105",
|
|
74
74
|
"@mastra/pg": "1.23.0-alpha.3",
|
|
75
|
-
"@internal/
|
|
76
|
-
"@internal/
|
|
75
|
+
"@internal/types-builder": "0.0.105",
|
|
76
|
+
"@internal/workspace": "0.0.2"
|
|
77
77
|
},
|
|
78
78
|
"engines": {
|
|
79
79
|
"node": ">=22.19.0"
|
package/dist/rules/defaults.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { FactoryRules, FactoryRulesOverrides } from './types.js';
|
|
2
|
-
export declare const DEFAULT_FACTORY_RULE_VERSION = "factory-default-v1";
|
|
3
|
-
export declare function mergeFactoryRuleOverrides(base: FactoryRulesOverrides, overrides?: FactoryRulesOverrides): Omit<FactoryRules, 'version'>;
|
|
4
|
-
export declare function defaultFactoryRules(input: {
|
|
5
|
-
version: string;
|
|
6
|
-
overrides?: FactoryRulesOverrides;
|
|
7
|
-
}): FactoryRules;
|
|
8
|
-
export declare function builtInFactoryRules(): FactoryRules;
|
|
9
|
-
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/rules/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,qBAAqB,EAGtB,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,4BAA4B,uBAAuB,CAAC;AAmDjE,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,qBAAqB,EAC3B,SAAS,GAAE,qBAA0B,GACpC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAI/B;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,qBAAqB,CAAA;CAAE,GAAG,YAAY,CAW/G;AAED,wBAAgB,mBAAmB,IAAI,YAAY,CAElD"}
|
package/dist/rules/defaults.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { FactoryRuleValidationError, assertFactoryRules } from "./validation.js";
|
|
2
|
-
//#region src/rules/defaults.ts
|
|
3
|
-
const DEFAULT_FACTORY_RULE_VERSION = "factory-default-v1";
|
|
4
|
-
function resultContent(value) {
|
|
5
|
-
if (typeof value === "string") return value;
|
|
6
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
7
|
-
const content = value.content;
|
|
8
|
-
return typeof content === "string" ? content : void 0;
|
|
9
|
-
}
|
|
10
|
-
function advanceApprovedPlan(context) {
|
|
11
|
-
if (context.result.status !== "success" || context.board !== "work" || context.item.stages.length !== 1 || context.item.stages[0] !== "planning" || context.actor.type !== "agent" || context.actor.role !== "plan" || !resultContent(context.result.value)?.startsWith("Plan approved.")) return;
|
|
12
|
-
return {
|
|
13
|
-
type: "transition",
|
|
14
|
-
idempotencyKey: `${context.ingress.id}:approved-plan`,
|
|
15
|
-
board: "work",
|
|
16
|
-
stage: "execute"
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
const BUILT_IN_DEFAULTS = { tools: { submit_plan: { onResult: advanceApprovedPlan } } };
|
|
20
|
-
function mergeToolRules(base, overrides) {
|
|
21
|
-
const result = {};
|
|
22
|
-
for (const name of /* @__PURE__ */ new Set([...Object.keys(base ?? {}), ...Object.keys(overrides ?? {})])) {
|
|
23
|
-
const baseLeaf = base?.[name];
|
|
24
|
-
const overrideLeaf = overrides?.[name];
|
|
25
|
-
result[name] = {
|
|
26
|
-
...baseLeaf && "onResult" in baseLeaf ? { onResult: baseLeaf.onResult } : {},
|
|
27
|
-
...overrideLeaf && "onResult" in overrideLeaf ? { onResult: overrideLeaf.onResult } : {}
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
return result;
|
|
31
|
-
}
|
|
32
|
-
function mergeFactoryRuleOverrides(base, overrides = {}) {
|
|
33
|
-
return { tools: mergeToolRules(base.tools, overrides.tools) };
|
|
34
|
-
}
|
|
35
|
-
function defaultFactoryRules(input) {
|
|
36
|
-
if (typeof input?.version !== "string" || input.version.trim().length === 0) throw new FactoryRuleValidationError("Factory rule version is required.");
|
|
37
|
-
const rules = {
|
|
38
|
-
version: input.version.trim(),
|
|
39
|
-
...mergeFactoryRuleOverrides(BUILT_IN_DEFAULTS, input.overrides)
|
|
40
|
-
};
|
|
41
|
-
assertFactoryRules(rules);
|
|
42
|
-
return rules;
|
|
43
|
-
}
|
|
44
|
-
function builtInFactoryRules() {
|
|
45
|
-
return defaultFactoryRules({ version: DEFAULT_FACTORY_RULE_VERSION });
|
|
46
|
-
}
|
|
47
|
-
//#endregion
|
|
48
|
-
export { DEFAULT_FACTORY_RULE_VERSION, builtInFactoryRules, defaultFactoryRules, mergeFactoryRuleOverrides };
|
|
49
|
-
|
|
50
|
-
//# sourceMappingURL=defaults.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","names":[],"sources":["../../src/rules/defaults.ts"],"sourcesContent":["import type {\n FactoryRules,\n FactoryRulesOverrides,\n FactoryToolResultRuleContext,\n FactoryToolRuleLeaf,\n} from './types.js';\nimport { assertFactoryRules, FactoryRuleValidationError } from './validation.js';\n\nexport const DEFAULT_FACTORY_RULE_VERSION = 'factory-default-v1';\n\nfunction resultContent(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (!value || typeof value !== 'object' || Array.isArray(value)) return;\n const content = (value as { content?: unknown }).content;\n return typeof content === 'string' ? content : undefined;\n}\n\n// Interactive-session path only: factory-plan never calls submit_plan — it\n// advances planning → execute via factory_transition_work_item directly.\nfunction advanceApprovedPlan(context: FactoryToolResultRuleContext) {\n if (\n context.result.status !== 'success' ||\n context.board !== 'work' ||\n context.item.stages.length !== 1 ||\n context.item.stages[0] !== 'planning' ||\n context.actor.type !== 'agent' ||\n context.actor.role !== 'plan' ||\n !resultContent(context.result.value)?.startsWith('Plan approved.')\n ) {\n return;\n }\n return {\n type: 'transition',\n idempotencyKey: `${context.ingress.id}:approved-plan`,\n board: 'work',\n stage: 'execute',\n } as const;\n}\n\nconst BUILT_IN_DEFAULTS: FactoryRulesOverrides = {\n tools: { submit_plan: { onResult: advanceApprovedPlan } },\n};\n\nfunction mergeToolRules(\n base: Record<string, FactoryToolRuleLeaf> | undefined,\n overrides: Record<string, FactoryToolRuleLeaf> | undefined,\n): Record<string, FactoryToolRuleLeaf> {\n const result: Record<string, FactoryToolRuleLeaf> = {};\n for (const name of new Set([...Object.keys(base ?? {}), ...Object.keys(overrides ?? {})])) {\n const baseLeaf = base?.[name];\n const overrideLeaf = overrides?.[name];\n result[name] = {\n ...(baseLeaf && 'onResult' in baseLeaf ? { onResult: baseLeaf.onResult } : {}),\n ...(overrideLeaf && 'onResult' in overrideLeaf ? { onResult: overrideLeaf.onResult } : {}),\n };\n }\n return result;\n}\n\nexport function mergeFactoryRuleOverrides(\n base: FactoryRulesOverrides,\n overrides: FactoryRulesOverrides = {},\n): Omit<FactoryRules, 'version'> {\n return {\n tools: mergeToolRules(base.tools, overrides.tools),\n };\n}\n\nexport function defaultFactoryRules(input: { version: string; overrides?: FactoryRulesOverrides }): FactoryRules {\n if (typeof input?.version !== 'string' || input.version.trim().length === 0) {\n throw new FactoryRuleValidationError('Factory rule version is required.');\n }\n\n const rules: FactoryRules = {\n version: input.version.trim(),\n ...mergeFactoryRuleOverrides(BUILT_IN_DEFAULTS, input.overrides),\n };\n assertFactoryRules(rules);\n return rules;\n}\n\nexport function builtInFactoryRules(): FactoryRules {\n return defaultFactoryRules({ version: DEFAULT_FACTORY_RULE_VERSION });\n}\n"],"mappings":";;AAQA,MAAa,+BAA+B;AAE5C,SAAS,cAAc,OAAoC;CACzD,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;CACjE,MAAM,UAAW,MAAgC;CACjD,OAAO,OAAO,YAAY,WAAW,UAAU,KAAA;AACjD;AAIA,SAAS,oBAAoB,SAAuC;CAClE,IACE,QAAQ,OAAO,WAAW,aAC1B,QAAQ,UAAU,UAClB,QAAQ,KAAK,OAAO,WAAW,KAC/B,QAAQ,KAAK,OAAO,OAAO,cAC3B,QAAQ,MAAM,SAAS,WACvB,QAAQ,MAAM,SAAS,UACvB,CAAC,cAAc,QAAQ,OAAO,KAAK,CAAC,EAAE,WAAW,gBAAgB,GAEjE;CAEF,OAAO;EACL,MAAM;EACN,gBAAgB,GAAG,QAAQ,QAAQ,GAAG;EACtC,OAAO;EACP,OAAO;CACT;AACF;AAEA,MAAM,oBAA2C,EAC/C,OAAO,EAAE,aAAa,EAAE,UAAU,oBAAoB,EAAE,EAC1D;AAEA,SAAS,eACP,MACA,WACqC;CACrC,MAAM,SAA8C,CAAC;CACrD,KAAK,MAAM,wBAAQ,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,QAAQ,CAAC,CAAC,GAAG,GAAG,OAAO,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG;EACzF,MAAM,WAAW,OAAO;EACxB,MAAM,eAAe,YAAY;EACjC,OAAO,QAAQ;GACb,GAAI,YAAY,cAAc,WAAW,EAAE,UAAU,SAAS,SAAS,IAAI,CAAC;GAC5E,GAAI,gBAAgB,cAAc,eAAe,EAAE,UAAU,aAAa,SAAS,IAAI,CAAC;EAC1F;CACF;CACA,OAAO;AACT;AAEA,SAAgB,0BACd,MACA,YAAmC,CAAC,GACL;CAC/B,OAAO,EACL,OAAO,eAAe,KAAK,OAAO,UAAU,KAAK,EACnD;AACF;AAEA,SAAgB,oBAAoB,OAA6E;CAC/G,IAAI,OAAO,OAAO,YAAY,YAAY,MAAM,QAAQ,KAAK,CAAC,CAAC,WAAW,GACxE,MAAM,IAAI,2BAA2B,mCAAmC;CAG1E,MAAM,QAAsB;EAC1B,SAAS,MAAM,QAAQ,KAAK;EAC5B,GAAG,0BAA0B,mBAAmB,MAAM,SAAS;CACjE;CACA,mBAAmB,KAAK;CACxB,OAAO;AACT;AAEA,SAAgB,sBAAoC;CAClD,OAAO,oBAAoB,EAAE,SAAS,6BAA6B,CAAC;AACtE"}
|