@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.
Files changed (135) hide show
  1. package/README.md +93 -10
  2. package/dist/boards/define-board.d.ts +36 -2
  3. package/dist/boards/define-board.d.ts.map +1 -1
  4. package/dist/boards/define-board.js +51 -1
  5. package/dist/boards/define-board.js.map +1 -1
  6. package/dist/boards/index.d.ts +3 -1
  7. package/dist/boards/index.d.ts.map +1 -1
  8. package/dist/boards/index.js +2 -1
  9. package/dist/boards/index.js.map +1 -1
  10. package/dist/boards/review.d.ts.map +1 -1
  11. package/dist/boards/review.js +5 -0
  12. package/dist/boards/review.js.map +1 -1
  13. package/dist/boards/semantics.d.ts +28 -0
  14. package/dist/boards/semantics.d.ts.map +1 -0
  15. package/dist/boards/semantics.js +41 -0
  16. package/dist/boards/semantics.js.map +1 -0
  17. package/dist/boards/work-tool-rules.d.ts +8 -0
  18. package/dist/boards/work-tool-rules.d.ts.map +1 -0
  19. package/dist/boards/work-tool-rules.js +20 -0
  20. package/dist/boards/work-tool-rules.js.map +1 -0
  21. package/dist/boards/work.d.ts.map +1 -1
  22. package/dist/boards/work.js +14 -1
  23. package/dist/boards/work.js.map +1 -1
  24. package/dist/factory.d.ts +5 -6
  25. package/dist/factory.d.ts.map +1 -1
  26. package/dist/factory.js +19 -11
  27. package/dist/factory.js.map +1 -1
  28. package/dist/integrations/base.d.ts +7 -4
  29. package/dist/integrations/base.d.ts.map +1 -1
  30. package/dist/integrations/github/issue-reconciler.d.ts.map +1 -1
  31. package/dist/integrations/github/issue-reconciler.js +4 -3
  32. package/dist/integrations/github/issue-reconciler.js.map +1 -1
  33. package/dist/integrations/github/rules.d.ts +3 -2
  34. package/dist/integrations/github/rules.d.ts.map +1 -1
  35. package/dist/integrations/github/rules.js +11 -10
  36. package/dist/integrations/github/rules.js.map +1 -1
  37. package/dist/integrations/issue-reconciler.d.ts +2 -0
  38. package/dist/integrations/issue-reconciler.d.ts.map +1 -1
  39. package/dist/integrations/issue-reconciler.js +1 -3
  40. package/dist/integrations/issue-reconciler.js.map +1 -1
  41. package/dist/integrations/linear/issue-reconciler.d.ts.map +1 -1
  42. package/dist/integrations/linear/issue-reconciler.js +8 -4
  43. package/dist/integrations/linear/issue-reconciler.js.map +1 -1
  44. package/dist/integrations/linear/rules.d.ts +1 -2
  45. package/dist/integrations/linear/rules.d.ts.map +1 -1
  46. package/dist/integrations/linear/rules.js +5 -5
  47. package/dist/integrations/linear/rules.js.map +1 -1
  48. package/dist/integrations/platform/api-client.d.ts.map +1 -1
  49. package/dist/integrations/platform/api-client.js +25 -4
  50. package/dist/integrations/platform/api-client.js.map +1 -1
  51. package/dist/integrations/platform/linear/integration.js +1 -1
  52. package/dist/integrations/platform/linear/integration.js.map +1 -1
  53. package/dist/integrations/slack/emoji-shortcodes.generated.d.ts +8 -0
  54. package/dist/integrations/slack/emoji-shortcodes.generated.d.ts.map +1 -0
  55. package/dist/integrations/slack/emoji-shortcodes.generated.js +1985 -0
  56. package/dist/integrations/slack/emoji-shortcodes.generated.js.map +1 -0
  57. package/dist/integrations/slack/emoji.d.ts +3 -0
  58. package/dist/integrations/slack/emoji.d.ts.map +1 -0
  59. package/dist/integrations/slack/emoji.js +12 -0
  60. package/dist/integrations/slack/emoji.js.map +1 -0
  61. package/dist/integrations/slack/integration.js +1 -1
  62. package/dist/integrations/slack/integration.js.map +1 -1
  63. package/dist/integrations/slack/slack.d.ts.map +1 -1
  64. package/dist/integrations/slack/slack.js +16 -2
  65. package/dist/integrations/slack/slack.js.map +1 -1
  66. package/dist/routes/supervisor.d.ts +2 -0
  67. package/dist/routes/supervisor.d.ts.map +1 -1
  68. package/dist/routes/supervisor.js +2 -2
  69. package/dist/routes/supervisor.js.map +1 -1
  70. package/dist/routes/surface.d.ts +4 -4
  71. package/dist/routes/surface.d.ts.map +1 -1
  72. package/dist/routes/surface.js +14 -9
  73. package/dist/routes/surface.js.map +1 -1
  74. package/dist/routes/work-items.d.ts +1 -1
  75. package/dist/routes/work-items.d.ts.map +1 -1
  76. package/dist/routes/work-items.js +17 -15
  77. package/dist/routes/work-items.js.map +1 -1
  78. package/dist/rules/dispatcher.d.ts +3 -0
  79. package/dist/rules/dispatcher.d.ts.map +1 -1
  80. package/dist/rules/dispatcher.js +37 -6
  81. package/dist/rules/dispatcher.js.map +1 -1
  82. package/dist/rules/index.d.ts +4 -5
  83. package/dist/rules/index.d.ts.map +1 -1
  84. package/dist/rules/index.js +3 -4
  85. package/dist/rules/processor.d.ts +3 -3
  86. package/dist/rules/processor.d.ts.map +1 -1
  87. package/dist/rules/processor.js +10 -12
  88. package/dist/rules/processor.js.map +1 -1
  89. package/dist/rules/resolve.d.ts +1 -3
  90. package/dist/rules/resolve.d.ts.map +1 -1
  91. package/dist/rules/resolve.js +1 -4
  92. package/dist/rules/resolve.js.map +1 -1
  93. package/dist/rules/start-coordinator.d.ts.map +1 -1
  94. package/dist/rules/start-coordinator.js +3 -1
  95. package/dist/rules/start-coordinator.js.map +1 -1
  96. package/dist/rules/tools.d.ts.map +1 -1
  97. package/dist/rules/tools.js +3 -4
  98. package/dist/rules/tools.js.map +1 -1
  99. package/dist/rules/transition-service.d.ts +7 -7
  100. package/dist/rules/transition-service.d.ts.map +1 -1
  101. package/dist/rules/transition-service.js +20 -25
  102. package/dist/rules/transition-service.js.map +1 -1
  103. package/dist/rules/types.d.ts +1 -11
  104. package/dist/rules/types.d.ts.map +1 -1
  105. package/dist/rules/types.js.map +1 -1
  106. package/dist/rules/validation.d.ts +7 -2
  107. package/dist/rules/validation.d.ts.map +1 -1
  108. package/dist/rules/validation.js +9 -15
  109. package/dist/rules/validation.js.map +1 -1
  110. package/dist/storage/domains/work-items/base.d.ts +9 -3
  111. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  112. package/dist/storage/domains/work-items/base.js +13 -17
  113. package/dist/storage/domains/work-items/base.js.map +1 -1
  114. package/dist/supervisor/health-worker.d.ts +2 -0
  115. package/dist/supervisor/health-worker.d.ts.map +1 -1
  116. package/dist/supervisor/health-worker.js +3 -1
  117. package/dist/supervisor/health-worker.js.map +1 -1
  118. package/dist/supervisor/health.d.ts +10 -12
  119. package/dist/supervisor/health.d.ts.map +1 -1
  120. package/dist/supervisor/health.js +11 -40
  121. package/dist/supervisor/health.js.map +1 -1
  122. package/dist/supervisor/instructions.d.ts +1 -1
  123. package/dist/supervisor/instructions.d.ts.map +1 -1
  124. package/dist/supervisor/instructions.js +10 -8
  125. package/dist/supervisor/instructions.js.map +1 -1
  126. package/dist/supervisor/read-tools.d.ts +2 -0
  127. package/dist/supervisor/read-tools.d.ts.map +1 -1
  128. package/dist/supervisor/read-tools.js +2 -2
  129. package/dist/supervisor/read-tools.js.map +1 -1
  130. package/factory-skills/configure-factory-rules/SKILL.md +18 -10
  131. package/package.json +7 -7
  132. package/dist/rules/defaults.d.ts +0 -9
  133. package/dist/rules/defaults.d.ts.map +0 -1
  134. package/dist/rules/defaults.js +0 -50
  135. 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 definition-owned board handlers, integration event rules, and global tool-result rules
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`, `defaultFactoryRules`, and the installed `GithubIntegration`, `PlatformGithubIntegration`, `LinearIntegration`, or `PlatformLinearIntegration` constructors and their `rules` options.
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, use `defaultFactoryRules({ version, overrides: { tools } })` and pass the result to `MastraFactory`. For GitHub or Linear rules, configure the installed integration constructor directly.
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`. The global rules tree contains only `version` and `tools.<toolName>.onResult`.
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. Working/resting phase semantics, role routing, terminal cleanup, consent, and kickoff behavior still contain built-in naming assumptions; custom policies do not generalize them. Do not advertise a custom `shipped` phase as terminal or invent built-in replacement APIs.
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
- ## Apply supported overrides
63
+ ## Configure board phase semantics
64
64
 
65
- Tool-result overrides replace the exact handler leaf. Integration overrides replace one event handler. Neither composes with the built-in handler; siblings remain unchanged. Board handlers belong to their definitions, not this override mechanism.
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
- Before replacing a built-in leaf:
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
- 1. Find and read the built-in handler: GitHub handlers live in `src/integrations/github/default-rules.ts`, Linear handlers in `src/integrations/linear/default-rules.ts`, and tool defaults in `src/rules/defaults.ts` within the Factory package. Inspect Work and Review defaults in `src/boards/work.ts` and `src/boards/review.ts`, and custom handlers in their installed definitions.
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 `version`. Change it whenever rule behavior changes. The version identifies persisted evaluations and audit records; it must not be used as event identity or added to ingress deduplication keys.
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.12",
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/code-sdk": "1.7.0-alpha.9",
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/workspace": "0.0.2",
76
- "@internal/lint": "0.0.130"
75
+ "@internal/types-builder": "0.0.105",
76
+ "@internal/workspace": "0.0.2"
77
77
  },
78
78
  "engines": {
79
79
  "node": ">=22.19.0"
@@ -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"}
@@ -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"}