@mastra/factory 0.13.0-alpha.9 → 0.13.0

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 (232) hide show
  1. package/README.md +232 -10
  2. package/dist/auth.d.ts +2 -0
  3. package/dist/auth.d.ts.map +1 -1
  4. package/dist/auth.js +29 -4
  5. package/dist/auth.js.map +1 -1
  6. package/dist/boards/define-board.d.ts +36 -2
  7. package/dist/boards/define-board.d.ts.map +1 -1
  8. package/dist/boards/define-board.js +58 -1
  9. package/dist/boards/define-board.js.map +1 -1
  10. package/dist/boards/index.d.ts +4 -2
  11. package/dist/boards/index.d.ts.map +1 -1
  12. package/dist/boards/index.js +2 -1
  13. package/dist/boards/index.js.map +1 -1
  14. package/dist/boards/relocate.d.ts +17 -0
  15. package/dist/boards/relocate.d.ts.map +1 -0
  16. package/dist/boards/relocate.js +53 -0
  17. package/dist/boards/relocate.js.map +1 -0
  18. package/dist/boards/review.d.ts +1 -1
  19. package/dist/boards/review.d.ts.map +1 -1
  20. package/dist/boards/review.js +17 -4
  21. package/dist/boards/review.js.map +1 -1
  22. package/dist/boards/semantics.d.ts +28 -0
  23. package/dist/boards/semantics.d.ts.map +1 -0
  24. package/dist/boards/semantics.js +41 -0
  25. package/dist/boards/semantics.js.map +1 -0
  26. package/dist/boards/work-tool-rules.d.ts +8 -0
  27. package/dist/boards/work-tool-rules.d.ts.map +1 -0
  28. package/dist/boards/work-tool-rules.js +20 -0
  29. package/dist/boards/work-tool-rules.js.map +1 -0
  30. package/dist/boards/work.d.ts +1 -1
  31. package/dist/boards/work.d.ts.map +1 -1
  32. package/dist/boards/work.js +13 -0
  33. package/dist/boards/work.js.map +1 -1
  34. package/dist/capabilities/intake.d.ts +2 -0
  35. package/dist/capabilities/intake.d.ts.map +1 -1
  36. package/dist/factory.d.ts +5 -6
  37. package/dist/factory.d.ts.map +1 -1
  38. package/dist/factory.js +41 -12
  39. package/dist/factory.js.map +1 -1
  40. package/dist/integrations/base.d.ts +7 -4
  41. package/dist/integrations/base.d.ts.map +1 -1
  42. package/dist/integrations/github/default-rules.d.ts +2 -2
  43. package/dist/integrations/github/default-rules.d.ts.map +1 -1
  44. package/dist/integrations/github/default-rules.js +2 -2
  45. package/dist/integrations/github/default-rules.js.map +1 -1
  46. package/dist/integrations/github/issue-reconciler.d.ts.map +1 -1
  47. package/dist/integrations/github/issue-reconciler.js +4 -3
  48. package/dist/integrations/github/issue-reconciler.js.map +1 -1
  49. package/dist/integrations/github/rules.d.ts +6 -2
  50. package/dist/integrations/github/rules.d.ts.map +1 -1
  51. package/dist/integrations/github/rules.js +96 -15
  52. package/dist/integrations/github/rules.js.map +1 -1
  53. package/dist/integrations/github/sandbox.d.ts +6 -3
  54. package/dist/integrations/github/sandbox.d.ts.map +1 -1
  55. package/dist/integrations/github/sandbox.js +21 -2
  56. package/dist/integrations/github/sandbox.js.map +1 -1
  57. package/dist/integrations/issue-reconciler.d.ts +2 -0
  58. package/dist/integrations/issue-reconciler.d.ts.map +1 -1
  59. package/dist/integrations/issue-reconciler.js +1 -3
  60. package/dist/integrations/issue-reconciler.js.map +1 -1
  61. package/dist/integrations/linear/agent-tools.d.ts.map +1 -1
  62. package/dist/integrations/linear/agent-tools.js.map +1 -1
  63. package/dist/integrations/linear/default-rules.d.ts +2 -2
  64. package/dist/integrations/linear/default-rules.d.ts.map +1 -1
  65. package/dist/integrations/linear/default-rules.js +2 -2
  66. package/dist/integrations/linear/default-rules.js.map +1 -1
  67. package/dist/integrations/linear/integration.js +1 -0
  68. package/dist/integrations/linear/integration.js.map +1 -1
  69. package/dist/integrations/linear/issue-reconciler.d.ts.map +1 -1
  70. package/dist/integrations/linear/issue-reconciler.js +9 -4
  71. package/dist/integrations/linear/issue-reconciler.js.map +1 -1
  72. package/dist/integrations/linear/reconciliation-config.d.ts.map +1 -1
  73. package/dist/integrations/linear/reconciliation-config.js.map +1 -1
  74. package/dist/integrations/linear/routes.d.ts.map +1 -1
  75. package/dist/integrations/linear/routes.js +19 -26
  76. package/dist/integrations/linear/routes.js.map +1 -1
  77. package/dist/integrations/linear/rules.d.ts +7 -2
  78. package/dist/integrations/linear/rules.d.ts.map +1 -1
  79. package/dist/integrations/linear/rules.js +20 -8
  80. package/dist/integrations/linear/rules.js.map +1 -1
  81. package/dist/integrations/platform/api-client.d.ts.map +1 -1
  82. package/dist/integrations/platform/api-client.js +25 -4
  83. package/dist/integrations/platform/api-client.js.map +1 -1
  84. package/dist/integrations/platform/github/integration.d.ts +1 -0
  85. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  86. package/dist/integrations/platform/github/integration.js +5 -0
  87. package/dist/integrations/platform/github/integration.js.map +1 -1
  88. package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
  89. package/dist/integrations/platform/linear/integration.js +5 -2
  90. package/dist/integrations/platform/linear/integration.js.map +1 -1
  91. package/dist/integrations/slack/emoji-shortcodes.generated.d.ts +8 -0
  92. package/dist/integrations/slack/emoji-shortcodes.generated.d.ts.map +1 -0
  93. package/dist/integrations/slack/emoji-shortcodes.generated.js +1985 -0
  94. package/dist/integrations/slack/emoji-shortcodes.generated.js.map +1 -0
  95. package/dist/integrations/slack/emoji.d.ts +3 -0
  96. package/dist/integrations/slack/emoji.d.ts.map +1 -0
  97. package/dist/integrations/slack/emoji.js +12 -0
  98. package/dist/integrations/slack/emoji.js.map +1 -0
  99. package/dist/integrations/slack/integration.js +1 -1
  100. package/dist/integrations/slack/integration.js.map +1 -1
  101. package/dist/integrations/slack/slack.d.ts.map +1 -1
  102. package/dist/integrations/slack/slack.js +16 -2
  103. package/dist/integrations/slack/slack.js.map +1 -1
  104. package/dist/routes/attention-activity.d.ts +2 -3
  105. package/dist/routes/attention-activity.d.ts.map +1 -1
  106. package/dist/routes/attention-activity.js +12 -3
  107. package/dist/routes/attention-activity.js.map +1 -1
  108. package/dist/routes/attention-parked.d.ts +22 -0
  109. package/dist/routes/attention-parked.d.ts.map +1 -0
  110. package/dist/routes/attention-parked.js +136 -0
  111. package/dist/routes/attention-parked.js.map +1 -0
  112. package/dist/routes/attention-providers.js +8 -8
  113. package/dist/routes/attention-providers.js.map +1 -1
  114. package/dist/routes/attention.d.ts +2 -0
  115. package/dist/routes/attention.d.ts.map +1 -1
  116. package/dist/routes/attention.js +47 -118
  117. package/dist/routes/attention.js.map +1 -1
  118. package/dist/routes/contracts.d.ts +627 -0
  119. package/dist/routes/contracts.d.ts.map +1 -0
  120. package/dist/routes/contracts.js +468 -0
  121. package/dist/routes/contracts.js.map +1 -0
  122. package/dist/routes/intake.d.ts +18 -0
  123. package/dist/routes/intake.d.ts.map +1 -1
  124. package/dist/routes/intake.js +265 -15
  125. package/dist/routes/intake.js.map +1 -1
  126. package/dist/routes/projects.d.ts.map +1 -1
  127. package/dist/routes/projects.js +26 -76
  128. package/dist/routes/projects.js.map +1 -1
  129. package/dist/routes/supervisor.d.ts +2 -0
  130. package/dist/routes/supervisor.d.ts.map +1 -1
  131. package/dist/routes/supervisor.js +7 -6
  132. package/dist/routes/supervisor.js.map +1 -1
  133. package/dist/routes/surface.d.ts +7 -4
  134. package/dist/routes/surface.d.ts.map +1 -1
  135. package/dist/routes/surface.js +17 -11
  136. package/dist/routes/surface.js.map +1 -1
  137. package/dist/routes/telemetry.d.ts +13 -0
  138. package/dist/routes/telemetry.d.ts.map +1 -0
  139. package/dist/routes/telemetry.js +60 -0
  140. package/dist/routes/telemetry.js.map +1 -0
  141. package/dist/routes/work-items.d.ts +3 -3
  142. package/dist/routes/work-items.d.ts.map +1 -1
  143. package/dist/routes/work-items.js +134 -250
  144. package/dist/routes/work-items.js.map +1 -1
  145. package/dist/rules/dispatch-errors.d.ts +2 -2
  146. package/dist/rules/dispatch-errors.d.ts.map +1 -1
  147. package/dist/rules/dispatch-errors.js +10 -6
  148. package/dist/rules/dispatch-errors.js.map +1 -1
  149. package/dist/rules/dispatcher.d.ts +9 -2
  150. package/dist/rules/dispatcher.d.ts.map +1 -1
  151. package/dist/rules/dispatcher.js +76 -23
  152. package/dist/rules/dispatcher.js.map +1 -1
  153. package/dist/rules/index.d.ts +4 -5
  154. package/dist/rules/index.d.ts.map +1 -1
  155. package/dist/rules/index.js +3 -4
  156. package/dist/rules/processor.d.ts +3 -3
  157. package/dist/rules/processor.d.ts.map +1 -1
  158. package/dist/rules/processor.js +24 -31
  159. package/dist/rules/processor.js.map +1 -1
  160. package/dist/rules/resolve.d.ts +1 -3
  161. package/dist/rules/resolve.d.ts.map +1 -1
  162. package/dist/rules/resolve.js +1 -4
  163. package/dist/rules/resolve.js.map +1 -1
  164. package/dist/rules/start-coordinator.d.ts.map +1 -1
  165. package/dist/rules/start-coordinator.js +3 -1
  166. package/dist/rules/start-coordinator.js.map +1 -1
  167. package/dist/rules/tools.d.ts.map +1 -1
  168. package/dist/rules/tools.js +20 -10
  169. package/dist/rules/tools.js.map +1 -1
  170. package/dist/rules/transition-service.d.ts +7 -7
  171. package/dist/rules/transition-service.d.ts.map +1 -1
  172. package/dist/rules/transition-service.js +21 -25
  173. package/dist/rules/transition-service.js.map +1 -1
  174. package/dist/rules/types.d.ts +16 -11
  175. package/dist/rules/types.d.ts.map +1 -1
  176. package/dist/rules/types.js.map +1 -1
  177. package/dist/rules/validation.d.ts +12 -2
  178. package/dist/rules/validation.d.ts.map +1 -1
  179. package/dist/rules/validation.js +29 -20
  180. package/dist/rules/validation.js.map +1 -1
  181. package/dist/session/live-sessions.d.ts +33 -3
  182. package/dist/session/live-sessions.d.ts.map +1 -1
  183. package/dist/session/live-sessions.js +67 -5
  184. package/dist/session/live-sessions.js.map +1 -1
  185. package/dist/storage/domains/intake/base.d.ts +54 -1
  186. package/dist/storage/domains/intake/base.d.ts.map +1 -1
  187. package/dist/storage/domains/intake/base.js +136 -4
  188. package/dist/storage/domains/intake/base.js.map +1 -1
  189. package/dist/storage/domains/work-items/base.d.ts +22 -7
  190. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  191. package/dist/storage/domains/work-items/base.js +41 -26
  192. package/dist/storage/domains/work-items/base.js.map +1 -1
  193. package/dist/supervisor/health-worker.d.ts +2 -0
  194. package/dist/supervisor/health-worker.d.ts.map +1 -1
  195. package/dist/supervisor/health-worker.js +3 -1
  196. package/dist/supervisor/health-worker.js.map +1 -1
  197. package/dist/supervisor/health.d.ts +12 -14
  198. package/dist/supervisor/health.d.ts.map +1 -1
  199. package/dist/supervisor/health.js +24 -52
  200. package/dist/supervisor/health.js.map +1 -1
  201. package/dist/supervisor/instructions.d.ts +1 -1
  202. package/dist/supervisor/instructions.d.ts.map +1 -1
  203. package/dist/supervisor/instructions.js +10 -8
  204. package/dist/supervisor/instructions.js.map +1 -1
  205. package/dist/supervisor/read-tools.d.ts +2 -0
  206. package/dist/supervisor/read-tools.d.ts.map +1 -1
  207. package/dist/supervisor/read-tools.js +2 -2
  208. package/dist/supervisor/read-tools.js.map +1 -1
  209. package/dist/supervisor/write-tools.d.ts.map +1 -1
  210. package/dist/supervisor/write-tools.js +6 -4
  211. package/dist/supervisor/write-tools.js.map +1 -1
  212. package/dist/telemetry-types.d.ts +7 -0
  213. package/dist/telemetry-types.d.ts.map +1 -0
  214. package/dist/telemetry-types.js +24 -0
  215. package/dist/telemetry-types.js.map +1 -0
  216. package/dist/telemetry.d.ts +9 -0
  217. package/dist/telemetry.d.ts.map +1 -0
  218. package/dist/telemetry.js +47 -0
  219. package/dist/telemetry.js.map +1 -0
  220. package/dist/work-item-branch.d.ts +2 -0
  221. package/dist/work-item-branch.d.ts.map +1 -1
  222. package/dist/work-item-branch.js +6 -1
  223. package/dist/work-item-branch.js.map +1 -1
  224. package/dist/workspace.d.ts.map +1 -1
  225. package/dist/workspace.js +3 -1
  226. package/dist/workspace.js.map +1 -1
  227. package/factory-skills/configure-factory-rules/SKILL.md +30 -10
  228. package/package.json +12 -10
  229. package/dist/rules/defaults.d.ts +0 -9
  230. package/dist/rules/defaults.d.ts.map +0 -1
  231. package/dist/rules/defaults.js +0 -50
  232. 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 +1 @@
1
- {"version":3,"file":"write-tools.d.ts","sourceRoot":"","sources":["../../src/supervisor/write-tools.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,UAAU,2BAA2B;IACnC,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,yBAAyB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACpG,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,2BAA2B,GAAG,gBAAgB,CA4LrG"}
1
+ {"version":3,"file":"write-tools.d.ts","sourceRoot":"","sources":["../../src/supervisor/write-tools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,UAAU,2BAA2B;IACnC,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,yBAAyB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACpG,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,2BAA2B,GAAG,gBAAgB,CA+LrG"}
@@ -1,4 +1,6 @@
1
- import { FACTORY_RULE_STAGES, factoryRuleStage } from "../rules/types.js";
1
+ import { BOARD_IDENTIFIER_RE } from "../rules/validation.js";
2
+ import { boardForWorkItem } from "../boards/semantics.js";
3
+ import "../boards/index.js";
2
4
  import { createTool } from "@mastra/core/tools";
3
5
  import { z } from "zod";
4
6
  //#region src/supervisor/write-tools.ts
@@ -84,7 +86,7 @@ function createFactorySupervisorWriteTools(deps) {
84
86
  description: "Move or accept one Factory work item after the person confirms the destination stage.",
85
87
  inputSchema: z.object({
86
88
  workItemId: z.string().min(1),
87
- stage: z.enum(FACTORY_RULE_STAGES)
89
+ stage: z.string().max(128).regex(BOARD_IDENTIFIER_RE)
88
90
  }),
89
91
  requireApproval: true,
90
92
  execute: async ({ workItemId, stage }) => {
@@ -93,13 +95,13 @@ function createFactorySupervisorWriteTools(deps) {
93
95
  id: workItemId
94
96
  });
95
97
  if (!item || item.factoryProjectId !== deps.scope.factoryProjectId) throw new Error("Work item not found.");
96
- const from = factoryRuleStage(item.stages);
98
+ const from = item.stages.length === 1 ? item.stages[0] : void 0;
97
99
  if (!from) throw new Error("The work item does not have one valid Factory stage.");
98
100
  const result = await deps.transitionService.transition({
99
101
  orgId: deps.scope.orgId,
100
102
  factoryProjectId: deps.scope.factoryProjectId,
101
103
  workItemId,
102
- board: item.externalSource?.type === "pull-request" ? "review" : "work",
104
+ board: boardForWorkItem(item),
103
105
  stage,
104
106
  expectedRevision: item.revision,
105
107
  actor: {
@@ -1 +1 @@
1
- {"version":3,"file":"write-tools.js","names":[],"sources":["../../src/supervisor/write-tools.ts"],"sourcesContent":["import { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport type { IntegrationTools } from '../integrations/base.js';\nimport type { FactoryTransitionService } from '../rules/transition-service.js';\nimport { FACTORY_RULE_STAGES, factoryRuleStage } from '../rules/types.js';\nimport type { AuditStorage } from '../storage/domains/audit/base.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { SupervisorScope } from './read-tools.js';\n\ninterface SupervisorWriteDependencies {\n scope: SupervisorScope;\n userId: string;\n workItems: WorkItemsStorage;\n audit: AuditStorage;\n transitionService: FactoryTransitionService;\n reconcileAcceptanceLabels?: (input: { orgId: string; factoryProjectId: string; item: WorkItemRow }) => Promise<void>;\n signalSession?: (input: { sessionId: string; message: string; userId: string }) => Promise<unknown>;\n now?: () => Date;\n}\n\nexport function createFactorySupervisorWriteTools(deps: SupervisorWriteDependencies): IntegrationTools {\n const now = deps.now ?? (() => new Date());\n const audit = async (action: string, target: { type: string; id: string }, metadata: Record<string, unknown> = {}) =>\n deps.audit.record({\n orgId: deps.scope.orgId,\n actorId: deps.userId,\n actorType: 'human',\n action,\n targets: [target],\n factoryProjectId: deps.scope.factoryProjectId,\n metadata: { ...metadata, cause: 'supervisor' },\n occurredAt: now(),\n });\n\n return {\n factory_retry_decision: createTool({\n id: 'factory_retry_decision',\n description: 'Retry one failed Factory decision after the person confirms the repair.',\n inputSchema: z.object({ decisionId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ decisionId }) => {\n const decision = await deps.workItems.retryDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision) throw new Error('The decision is not failed, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.run.retry',\n { type: 'rule_decision', id: decisionId },\n { workItemId: decision.workItemId },\n );\n return { decisionId, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_dismiss_decision: createTool({\n id: 'factory_dismiss_decision',\n description: 'Dismiss one parked Factory proposal after the person confirms it is no longer wanted.',\n inputSchema: z.object({ decisionId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ decisionId }) => {\n const decision = await deps.workItems.dismissDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision)\n throw new Error('The decision is not proposed, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.run.dismissed',\n { type: 'rule_decision', id: decisionId },\n { workItemId: decision.workItemId },\n );\n return { decisionId, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_resolve_proposal: createTool({\n id: 'factory_resolve_proposal',\n description: 'Approve or dismiss one proposed Factory decision after the person confirms the choice.',\n inputSchema: z.object({ decisionId: z.string().min(1), resolution: z.enum(['approve', 'dismiss']) }),\n requireApproval: true,\n execute: async ({ decisionId, resolution }) => {\n const decision =\n resolution === 'approve'\n ? await deps.workItems.approveDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n deps.userId,\n )\n : await deps.workItems.dismissDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision) throw new Error('The proposal is no longer open or belongs to another factory.');\n await audit(\n resolution === 'approve' ? 'factory.run.approved' : 'factory.run.dismissed',\n {\n type: 'rule_decision',\n id: decisionId,\n },\n { workItemId: decision.workItemId },\n );\n return { decisionId, resolution, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_transition_work_item: createTool({\n id: 'factory_transition_work_item',\n description: 'Move or accept one Factory work item after the person confirms the destination stage.',\n inputSchema: z.object({ workItemId: z.string().min(1), stage: z.enum(FACTORY_RULE_STAGES) }),\n requireApproval: true,\n execute: async ({ workItemId, stage }) => {\n const item = await deps.workItems.get({ orgId: deps.scope.orgId, id: workItemId });\n if (!item || item.factoryProjectId !== deps.scope.factoryProjectId) throw new Error('Work item not found.');\n const from = factoryRuleStage(item.stages);\n if (!from) throw new Error('The work item does not have one valid Factory stage.');\n const result = await deps.transitionService.transition({\n orgId: deps.scope.orgId,\n factoryProjectId: deps.scope.factoryProjectId,\n workItemId,\n board: item.externalSource?.type === 'pull-request' ? 'review' : 'work',\n stage,\n expectedRevision: item.revision,\n actor: { type: 'human', id: deps.userId },\n ingress: { type: 'human', identity: `supervisor:${deps.userId}:${workItemId}:${item.revision}:${stage}` },\n cause: 'supervisor',\n });\n await audit(\n result.status === 'accepted' ? 'factory.work_item.stage_moved' : 'factory.work_item.transition_rejected',\n { type: 'work_item', id: workItemId },\n result.status === 'accepted'\n ? { from, to: result.stage, revision: result.revision, transitionId: result.transitionId }\n : { from, to: stage, code: result.code, reason: result.reason, transitionId: result.transitionId },\n );\n if (result.status !== 'accepted') {\n throw new Error(`The transition was rejected (${result.code}): ${result.reason}`);\n }\n return result;\n },\n }),\n factory_reconcile_labels: createTool({\n id: 'factory_reconcile_labels',\n description: 'Reconcile stale acceptance labels for one accepted work item after the person confirms the repair.',\n inputSchema: z.object({ workItemId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ workItemId }) => {\n if (!deps.reconcileAcceptanceLabels) throw new Error('Acceptance-label reconciliation is unavailable.');\n const item = await deps.workItems.get({ orgId: deps.scope.orgId, id: workItemId });\n if (!item || item.factoryProjectId !== deps.scope.factoryProjectId) throw new Error('Work item not found.');\n if (!item.acceptedAt) throw new Error('The work item has not been accepted.');\n await deps.reconcileAcceptanceLabels({ ...deps.scope, item });\n await audit('factory.work_item.labels_reconciled', { type: 'work_item', id: workItemId });\n return { workItemId, reconciled: true };\n },\n }),\n factory_revoke_binding: createTool({\n id: 'factory_revoke_binding',\n description: 'Revoke an orphaned or stale run binding after a health finding and person confirmation.',\n inputSchema: z.object({ bindingId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ bindingId }) => {\n const binding = await deps.workItems.revokeRunBinding({\n orgId: deps.scope.orgId,\n factoryProjectId: deps.scope.factoryProjectId,\n bindingId,\n revokedAt: now(),\n });\n if (!binding) throw new Error('The binding is not active, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.intake.binding_updated',\n { type: 'run_binding', id: bindingId },\n {\n workItemId: binding.workItemId,\n role: binding.role,\n status: 'revoked',\n },\n );\n return { bindingId, status: binding.status, workItemId: binding.workItemId, role: binding.role };\n },\n }),\n factory_signal_session: createTool({\n id: 'factory_signal_session',\n description: 'Send bounded guidance to a worker session after the person confirms the exact message.',\n inputSchema: z.object({ sessionId: z.string().min(1), message: z.string().trim().min(1).max(2000) }),\n requireApproval: true,\n execute: async ({ sessionId, message }) => {\n if (!deps.signalSession) throw new Error('Worker session signaling is unavailable.');\n const bindings = await deps.workItems.listRunBindings(deps.scope.orgId, deps.scope.factoryProjectId);\n const binding = bindings.find(row => row.sessionId === sessionId);\n if (!binding) throw new Error('The session does not belong to this factory.');\n await deps.signalSession({ sessionId, message, userId: deps.userId });\n await audit(\n 'factory.agent.signaled',\n { type: 'factory_session', id: sessionId },\n {\n workItemId: binding.workItemId,\n role: binding.role,\n },\n );\n return { sessionId, delivered: true, workItemId: binding.workItemId, role: binding.role };\n },\n }),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"write-tools.js","names":[],"sources":["../../src/supervisor/write-tools.ts"],"sourcesContent":["import { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { IntegrationTools } from '../integrations/base.js';\nimport type { FactoryTransitionService } from '../rules/transition-service.js';\nimport { BOARD_IDENTIFIER_RE, MAX_BOARD_IDENTIFIER_LENGTH } from '../rules/validation.js';\nimport type { AuditStorage } from '../storage/domains/audit/base.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { SupervisorScope } from './read-tools.js';\n\ninterface SupervisorWriteDependencies {\n scope: SupervisorScope;\n userId: string;\n workItems: WorkItemsStorage;\n audit: AuditStorage;\n transitionService: FactoryTransitionService;\n reconcileAcceptanceLabels?: (input: { orgId: string; factoryProjectId: string; item: WorkItemRow }) => Promise<void>;\n signalSession?: (input: { sessionId: string; message: string; userId: string }) => Promise<unknown>;\n now?: () => Date;\n}\n\nexport function createFactorySupervisorWriteTools(deps: SupervisorWriteDependencies): IntegrationTools {\n const now = deps.now ?? (() => new Date());\n const audit = async (action: string, target: { type: string; id: string }, metadata: Record<string, unknown> = {}) =>\n deps.audit.record({\n orgId: deps.scope.orgId,\n actorId: deps.userId,\n actorType: 'human',\n action,\n targets: [target],\n factoryProjectId: deps.scope.factoryProjectId,\n metadata: { ...metadata, cause: 'supervisor' },\n occurredAt: now(),\n });\n\n return {\n factory_retry_decision: createTool({\n id: 'factory_retry_decision',\n description: 'Retry one failed Factory decision after the person confirms the repair.',\n inputSchema: z.object({ decisionId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ decisionId }) => {\n const decision = await deps.workItems.retryDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision) throw new Error('The decision is not failed, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.run.retry',\n { type: 'rule_decision', id: decisionId },\n { workItemId: decision.workItemId },\n );\n return { decisionId, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_dismiss_decision: createTool({\n id: 'factory_dismiss_decision',\n description: 'Dismiss one parked Factory proposal after the person confirms it is no longer wanted.',\n inputSchema: z.object({ decisionId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ decisionId }) => {\n const decision = await deps.workItems.dismissDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision)\n throw new Error('The decision is not proposed, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.run.dismissed',\n { type: 'rule_decision', id: decisionId },\n { workItemId: decision.workItemId },\n );\n return { decisionId, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_resolve_proposal: createTool({\n id: 'factory_resolve_proposal',\n description: 'Approve or dismiss one proposed Factory decision after the person confirms the choice.',\n inputSchema: z.object({ decisionId: z.string().min(1), resolution: z.enum(['approve', 'dismiss']) }),\n requireApproval: true,\n execute: async ({ decisionId, resolution }) => {\n const decision =\n resolution === 'approve'\n ? await deps.workItems.approveDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n deps.userId,\n )\n : await deps.workItems.dismissDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision) throw new Error('The proposal is no longer open or belongs to another factory.');\n await audit(\n resolution === 'approve' ? 'factory.run.approved' : 'factory.run.dismissed',\n {\n type: 'rule_decision',\n id: decisionId,\n },\n { workItemId: decision.workItemId },\n );\n return { decisionId, resolution, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_transition_work_item: createTool({\n id: 'factory_transition_work_item',\n description: 'Move or accept one Factory work item after the person confirms the destination stage.',\n inputSchema: z.object({\n workItemId: z.string().min(1),\n stage: z.string().max(MAX_BOARD_IDENTIFIER_LENGTH).regex(BOARD_IDENTIFIER_RE),\n }),\n requireApproval: true,\n execute: async ({ workItemId, stage }) => {\n const item = await deps.workItems.get({ orgId: deps.scope.orgId, id: workItemId });\n if (!item || item.factoryProjectId !== deps.scope.factoryProjectId) throw new Error('Work item not found.');\n const from = item.stages.length === 1 ? item.stages[0] : undefined;\n if (!from) throw new Error('The work item does not have one valid Factory stage.');\n const result = await deps.transitionService.transition({\n orgId: deps.scope.orgId,\n factoryProjectId: deps.scope.factoryProjectId,\n workItemId,\n board: boardForWorkItem(item),\n stage,\n expectedRevision: item.revision,\n actor: { type: 'human', id: deps.userId },\n ingress: { type: 'human', identity: `supervisor:${deps.userId}:${workItemId}:${item.revision}:${stage}` },\n cause: 'supervisor',\n });\n await audit(\n result.status === 'accepted' ? 'factory.work_item.stage_moved' : 'factory.work_item.transition_rejected',\n { type: 'work_item', id: workItemId },\n result.status === 'accepted'\n ? { from, to: result.stage, revision: result.revision, transitionId: result.transitionId }\n : { from, to: stage, code: result.code, reason: result.reason, transitionId: result.transitionId },\n );\n if (result.status !== 'accepted') {\n throw new Error(`The transition was rejected (${result.code}): ${result.reason}`);\n }\n return result;\n },\n }),\n factory_reconcile_labels: createTool({\n id: 'factory_reconcile_labels',\n description: 'Reconcile stale acceptance labels for one accepted work item after the person confirms the repair.',\n inputSchema: z.object({ workItemId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ workItemId }) => {\n if (!deps.reconcileAcceptanceLabels) throw new Error('Acceptance-label reconciliation is unavailable.');\n const item = await deps.workItems.get({ orgId: deps.scope.orgId, id: workItemId });\n if (!item || item.factoryProjectId !== deps.scope.factoryProjectId) throw new Error('Work item not found.');\n if (!item.acceptedAt) throw new Error('The work item has not been accepted.');\n await deps.reconcileAcceptanceLabels({ ...deps.scope, item });\n await audit('factory.work_item.labels_reconciled', { type: 'work_item', id: workItemId });\n return { workItemId, reconciled: true };\n },\n }),\n factory_revoke_binding: createTool({\n id: 'factory_revoke_binding',\n description: 'Revoke an orphaned or stale run binding after a health finding and person confirmation.',\n inputSchema: z.object({ bindingId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ bindingId }) => {\n const binding = await deps.workItems.revokeRunBinding({\n orgId: deps.scope.orgId,\n factoryProjectId: deps.scope.factoryProjectId,\n bindingId,\n revokedAt: now(),\n });\n if (!binding) throw new Error('The binding is not active, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.intake.binding_updated',\n { type: 'run_binding', id: bindingId },\n {\n workItemId: binding.workItemId,\n role: binding.role,\n status: 'revoked',\n },\n );\n return { bindingId, status: binding.status, workItemId: binding.workItemId, role: binding.role };\n },\n }),\n factory_signal_session: createTool({\n id: 'factory_signal_session',\n description: 'Send bounded guidance to a worker session after the person confirms the exact message.',\n inputSchema: z.object({ sessionId: z.string().min(1), message: z.string().trim().min(1).max(2000) }),\n requireApproval: true,\n execute: async ({ sessionId, message }) => {\n if (!deps.signalSession) throw new Error('Worker session signaling is unavailable.');\n const bindings = await deps.workItems.listRunBindings(deps.scope.orgId, deps.scope.factoryProjectId);\n const binding = bindings.find(row => row.sessionId === sessionId);\n if (!binding) throw new Error('The session does not belong to this factory.');\n await deps.signalSession({ sessionId, message, userId: deps.userId });\n await audit(\n 'factory.agent.signaled',\n { type: 'factory_session', id: sessionId },\n {\n workItemId: binding.workItemId,\n role: binding.role,\n },\n );\n return { sessionId, delivered: true, workItemId: binding.workItemId, role: binding.role };\n },\n }),\n };\n}\n"],"mappings":";;;;;;AAsBA,SAAgB,kCAAkC,MAAqD;CACrG,MAAM,MAAM,KAAK,8BAAc,IAAI,KAAK;CACxC,MAAM,QAAQ,OAAO,QAAgB,QAAsC,WAAoC,CAAC,MAC9G,KAAK,MAAM,OAAO;EAChB,OAAO,KAAK,MAAM;EAClB,SAAS,KAAK;EACd,WAAW;EACX;EACA,SAAS,CAAC,MAAM;EAChB,kBAAkB,KAAK,MAAM;EAC7B,UAAU;GAAE,GAAG;GAAU,OAAO;EAAa;EAC7C,YAAY,IAAI;CAClB,CAAC;CAEH,OAAO;EACL,wBAAwB,WAAW;GACjC,IAAI;GACJ,aAAa;GACb,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;GACvD,iBAAiB;GACjB,SAAS,OAAO,EAAE,iBAAiB;IACjC,MAAM,WAAW,MAAM,KAAK,UAAU,sBACpC,KAAK,MAAM,OACX,KAAK,MAAM,kBACX,YACA,IAAI,CACN;IACA,IAAI,CAAC,UAAU,MAAM,IAAI,MAAM,8EAA8E;IAC7G,MAAM,MACJ,qBACA;KAAE,MAAM;KAAiB,IAAI;IAAW,GACxC,EAAE,YAAY,SAAS,WAAW,CACpC;IACA,OAAO;KAAE;KAAY,QAAQ,SAAS;KAAQ,YAAY,SAAS;IAAW;GAChF;EACF,CAAC;EACD,0BAA0B,WAAW;GACnC,IAAI;GACJ,aAAa;GACb,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;GACvD,iBAAiB;GACjB,SAAS,OAAO,EAAE,iBAAiB;IACjC,MAAM,WAAW,MAAM,KAAK,UAAU,wBACpC,KAAK,MAAM,OACX,KAAK,MAAM,kBACX,YACA,IAAI,CACN;IACA,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,gFAAgF;IAClG,MAAM,MACJ,yBACA;KAAE,MAAM;KAAiB,IAAI;IAAW,GACxC,EAAE,YAAY,SAAS,WAAW,CACpC;IACA,OAAO;KAAE;KAAY,QAAQ,SAAS;KAAQ,YAAY,SAAS;IAAW;GAChF;EACF,CAAC;EACD,0BAA0B,WAAW;GACnC,IAAI;GACJ,aAAa;GACb,aAAa,EAAE,OAAO;IAAE,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;IAAG,YAAY,EAAE,KAAK,CAAC,WAAW,SAAS,CAAC;GAAE,CAAC;GACnG,iBAAiB;GACjB,SAAS,OAAO,EAAE,YAAY,iBAAiB;IAC7C,MAAM,WACJ,eAAe,YACX,MAAM,KAAK,UAAU,wBACnB,KAAK,MAAM,OACX,KAAK,MAAM,kBACX,YACA,IAAI,GACJ,KAAK,MACP,IACA,MAAM,KAAK,UAAU,wBACnB,KAAK,MAAM,OACX,KAAK,MAAM,kBACX,YACA,IAAI,CACN;IACN,IAAI,CAAC,UAAU,MAAM,IAAI,MAAM,+DAA+D;IAC9F,MAAM,MACJ,eAAe,YAAY,yBAAyB,yBACpD;KACE,MAAM;KACN,IAAI;IACN,GACA,EAAE,YAAY,SAAS,WAAW,CACpC;IACA,OAAO;KAAE;KAAY;KAAY,QAAQ,SAAS;KAAQ,YAAY,SAAS;IAAW;GAC5F;EACF,CAAC;EACD,8BAA8B,WAAW;GACvC,IAAI;GACJ,aAAa;GACb,aAAa,EAAE,OAAO;IACpB,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC,CAAC,IAAA,GAA+B,CAAC,CAAC,MAAM,mBAAmB;GAC9E,CAAC;GACD,iBAAiB;GACjB,SAAS,OAAO,EAAE,YAAY,YAAY;IACxC,MAAM,OAAO,MAAM,KAAK,UAAU,IAAI;KAAE,OAAO,KAAK,MAAM;KAAO,IAAI;IAAW,CAAC;IACjF,IAAI,CAAC,QAAQ,KAAK,qBAAqB,KAAK,MAAM,kBAAkB,MAAM,IAAI,MAAM,sBAAsB;IAC1G,MAAM,OAAO,KAAK,OAAO,WAAW,IAAI,KAAK,OAAO,KAAK,KAAA;IACzD,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,sDAAsD;IACjF,MAAM,SAAS,MAAM,KAAK,kBAAkB,WAAW;KACrD,OAAO,KAAK,MAAM;KAClB,kBAAkB,KAAK,MAAM;KAC7B;KACA,OAAO,iBAAiB,IAAI;KAC5B;KACA,kBAAkB,KAAK;KACvB,OAAO;MAAE,MAAM;MAAS,IAAI,KAAK;KAAO;KACxC,SAAS;MAAE,MAAM;MAAS,UAAU,cAAc,KAAK,OAAO,GAAG,WAAW,GAAG,KAAK,SAAS,GAAG;KAAQ;KACxG,OAAO;IACT,CAAC;IACD,MAAM,MACJ,OAAO,WAAW,aAAa,kCAAkC,yCACjE;KAAE,MAAM;KAAa,IAAI;IAAW,GACpC,OAAO,WAAW,aACd;KAAE;KAAM,IAAI,OAAO;KAAO,UAAU,OAAO;KAAU,cAAc,OAAO;IAAa,IACvF;KAAE;KAAM,IAAI;KAAO,MAAM,OAAO;KAAM,QAAQ,OAAO;KAAQ,cAAc,OAAO;IAAa,CACrG;IACA,IAAI,OAAO,WAAW,YACpB,MAAM,IAAI,MAAM,gCAAgC,OAAO,KAAK,KAAK,OAAO,QAAQ;IAElF,OAAO;GACT;EACF,CAAC;EACD,0BAA0B,WAAW;GACnC,IAAI;GACJ,aAAa;GACb,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;GACvD,iBAAiB;GACjB,SAAS,OAAO,EAAE,iBAAiB;IACjC,IAAI,CAAC,KAAK,2BAA2B,MAAM,IAAI,MAAM,iDAAiD;IACtG,MAAM,OAAO,MAAM,KAAK,UAAU,IAAI;KAAE,OAAO,KAAK,MAAM;KAAO,IAAI;IAAW,CAAC;IACjF,IAAI,CAAC,QAAQ,KAAK,qBAAqB,KAAK,MAAM,kBAAkB,MAAM,IAAI,MAAM,sBAAsB;IAC1G,IAAI,CAAC,KAAK,YAAY,MAAM,IAAI,MAAM,sCAAsC;IAC5E,MAAM,KAAK,0BAA0B;KAAE,GAAG,KAAK;KAAO;IAAK,CAAC;IAC5D,MAAM,MAAM,uCAAuC;KAAE,MAAM;KAAa,IAAI;IAAW,CAAC;IACxF,OAAO;KAAE;KAAY,YAAY;IAAK;GACxC;EACF,CAAC;EACD,wBAAwB,WAAW;GACjC,IAAI;GACJ,aAAa;GACb,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;GACtD,iBAAiB;GACjB,SAAS,OAAO,EAAE,gBAAgB;IAChC,MAAM,UAAU,MAAM,KAAK,UAAU,iBAAiB;KACpD,OAAO,KAAK,MAAM;KAClB,kBAAkB,KAAK,MAAM;KAC7B;KACA,WAAW,IAAI;IACjB,CAAC;IACD,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,6EAA6E;IAC3G,MAAM,MACJ,kCACA;KAAE,MAAM;KAAe,IAAI;IAAU,GACrC;KACE,YAAY,QAAQ;KACpB,MAAM,QAAQ;KACd,QAAQ;IACV,CACF;IACA,OAAO;KAAE;KAAW,QAAQ,QAAQ;KAAQ,YAAY,QAAQ;KAAY,MAAM,QAAQ;IAAK;GACjG;EACF,CAAC;EACD,wBAAwB,WAAW;GACjC,IAAI;GACJ,aAAa;GACb,aAAa,EAAE,OAAO;IAAE,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;IAAG,SAAS,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAI;GAAE,CAAC;GACnG,iBAAiB;GACjB,SAAS,OAAO,EAAE,WAAW,cAAc;IACzC,IAAI,CAAC,KAAK,eAAe,MAAM,IAAI,MAAM,0CAA0C;IAEnF,MAAM,WAAU,MADO,KAAK,UAAU,gBAAgB,KAAK,MAAM,OAAO,KAAK,MAAM,gBAAgB,EAAA,CAC1E,MAAK,QAAO,IAAI,cAAc,SAAS;IAChE,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,8CAA8C;IAC5E,MAAM,KAAK,cAAc;KAAE;KAAW;KAAS,QAAQ,KAAK;IAAO,CAAC;IACpE,MAAM,MACJ,0BACA;KAAE,MAAM;KAAmB,IAAI;IAAU,GACzC;KACE,YAAY,QAAQ;KACpB,MAAM,QAAQ;IAChB,CACF;IACA,OAAO;KAAE;KAAW,WAAW;KAAM,YAAY,QAAQ;KAAY,MAAM,QAAQ;IAAK;GAC1F;EACF,CAAC;CACH;AACF"}
@@ -0,0 +1,7 @@
1
+ /** Browser-safe vocabulary: never send URLs, route parameters, or input contents. */
2
+ export declare const FACTORY_WEB_PAGES: readonly ["onboarding", "work", "review", "overview", "attention", "activity", "rules", "audit", "knowledge", "settings", "slack_connection", "workspace", "thread", "supervisor", "new_session", "new_factory"];
3
+ export interface FactoryWebActivity {
4
+ activity: 'page_view' | 'interaction';
5
+ page: (typeof FACTORY_WEB_PAGES)[number];
6
+ }
7
+ //# sourceMappingURL=telemetry-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-types.d.ts","sourceRoot":"","sources":["../src/telemetry-types.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,kNAiBpB,CAAC;AAEX,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,WAAW,GAAG,aAAa,CAAC;IACtC,IAAI,EAAE,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;CAC1C"}
@@ -0,0 +1,24 @@
1
+ //#region src/telemetry-types.ts
2
+ /** Browser-safe vocabulary: never send URLs, route parameters, or input contents. */
3
+ const FACTORY_WEB_PAGES = [
4
+ "onboarding",
5
+ "work",
6
+ "review",
7
+ "overview",
8
+ "attention",
9
+ "activity",
10
+ "rules",
11
+ "audit",
12
+ "knowledge",
13
+ "settings",
14
+ "slack_connection",
15
+ "workspace",
16
+ "thread",
17
+ "supervisor",
18
+ "new_session",
19
+ "new_factory"
20
+ ];
21
+ //#endregion
22
+ export { FACTORY_WEB_PAGES };
23
+
24
+ //# sourceMappingURL=telemetry-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-types.js","names":[],"sources":["../src/telemetry-types.ts"],"sourcesContent":["/** Browser-safe vocabulary: never send URLs, route parameters, or input contents. */\nexport const FACTORY_WEB_PAGES = [\n 'onboarding',\n 'work',\n 'review',\n 'overview',\n 'attention',\n 'activity',\n 'rules',\n 'audit',\n 'knowledge',\n 'settings',\n 'slack_connection',\n 'workspace',\n 'thread',\n 'supervisor',\n 'new_session',\n 'new_factory',\n] as const;\n\nexport interface FactoryWebActivity {\n activity: 'page_view' | 'interaction';\n page: (typeof FACTORY_WEB_PAGES)[number];\n}\n"],"mappings":";;AACA,MAAa,oBAAoB;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
@@ -0,0 +1,9 @@
1
+ import type { FactoryWebActivity } from './telemetry-types.js';
2
+ /** Start with the default platform auth provider; custom identity authorities are separate work. */
3
+ export declare function isFactoryTelemetryEnabled(providerName: string | undefined): boolean;
4
+ /** Identity is resolved by the server. This never aliases existing CLI or platform profiles. */
5
+ export declare function captureFactoryWebActivity(activity: FactoryWebActivity, actor: {
6
+ userId: string;
7
+ orgId?: string;
8
+ }): void;
9
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAI/D,oGAAoG;AACpG,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAKnF;AAMD,gGAAgG;AAChG,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,kBAAkB,EAC5B,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC,IAAI,CA6BN"}
@@ -0,0 +1,47 @@
1
+ import { PostHog } from "posthog-node";
2
+ //#region src/telemetry.ts
3
+ let client;
4
+ /** Start with the default platform auth provider; custom identity authorities are separate work. */
5
+ function isFactoryTelemetryEnabled(providerName) {
6
+ return providerName === "mastra-studio" && ![
7
+ "1",
8
+ "true",
9
+ "yes"
10
+ ].includes(process.env.MASTRA_TELEMETRY_DISABLED?.trim().toLowerCase() ?? "");
11
+ }
12
+ function env(name) {
13
+ return process.env[name]?.trim() || void 0;
14
+ }
15
+ /** Identity is resolved by the server. This never aliases existing CLI or platform profiles. */
16
+ function captureFactoryWebActivity(activity, actor) {
17
+ if (!isFactoryTelemetryEnabled("mastra-studio")) return;
18
+ try {
19
+ const deploymentId = env("MASTRA_DEPLOYMENT_ID");
20
+ client ??= new PostHog("phc_SBLpZVAB6jmHOct9CABq3PF0Yn5FU3G2FgT4xUr2XrT", {
21
+ host: "https://us.posthog.com",
22
+ flushAt: 1,
23
+ flushInterval: 0,
24
+ maxQueueSize: 100,
25
+ disableGeoip: true
26
+ });
27
+ client.capture({
28
+ distinctId: `factory:platform:${actor.userId}`,
29
+ event: "factory_web_activity",
30
+ properties: {
31
+ schema_version: 1,
32
+ activity: activity.activity,
33
+ page: activity.page,
34
+ platform_user_id: actor.userId,
35
+ platform_org_id: actor.orgId,
36
+ platform_hosted: Boolean(deploymentId),
37
+ platform_project_id: env("MASTRA_PROJECT_ID"),
38
+ deployment_id: deploymentId,
39
+ platform_region: env("MASTRA_PLATFORM_REGION")
40
+ }
41
+ });
42
+ } catch {}
43
+ }
44
+ //#endregion
45
+ export { captureFactoryWebActivity, isFactoryTelemetryEnabled };
46
+
47
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","names":[],"sources":["../src/telemetry.ts"],"sourcesContent":["import { PostHog } from 'posthog-node';\n\nimport type { FactoryWebActivity } from './telemetry-types.js';\n\nlet client: PostHog | undefined;\n\n/** Start with the default platform auth provider; custom identity authorities are separate work. */\nexport function isFactoryTelemetryEnabled(providerName: string | undefined): boolean {\n return (\n providerName === 'mastra-studio' &&\n !['1', 'true', 'yes'].includes(process.env.MASTRA_TELEMETRY_DISABLED?.trim().toLowerCase() ?? '')\n );\n}\n\nfunction env(name: string): string | undefined {\n return process.env[name]?.trim() || undefined;\n}\n\n/** Identity is resolved by the server. This never aliases existing CLI or platform profiles. */\nexport function captureFactoryWebActivity(\n activity: FactoryWebActivity,\n actor: { userId: string; orgId?: string },\n): void {\n if (!isFactoryTelemetryEnabled('mastra-studio')) return;\n try {\n const deploymentId = env('MASTRA_DEPLOYMENT_ID');\n client ??= new PostHog('phc_SBLpZVAB6jmHOct9CABq3PF0Yn5FU3G2FgT4xUr2XrT', {\n host: 'https://us.posthog.com',\n flushAt: 1,\n flushInterval: 0,\n maxQueueSize: 100,\n disableGeoip: true,\n });\n client.capture({\n distinctId: `factory:platform:${actor.userId}`,\n event: 'factory_web_activity',\n properties: {\n schema_version: 1,\n activity: activity.activity,\n page: activity.page,\n platform_user_id: actor.userId,\n platform_org_id: actor.orgId,\n platform_hosted: Boolean(deploymentId),\n platform_project_id: env('MASTRA_PROJECT_ID'),\n deployment_id: deploymentId,\n platform_region: env('MASTRA_PLATFORM_REGION'),\n },\n });\n } catch {\n // Analytics is best effort and must never interrupt Factory usage.\n }\n}\n"],"mappings":";;AAIA,IAAI;;AAGJ,SAAgB,0BAA0B,cAA2C;CACnF,OACE,iBAAiB,mBACjB,CAAC;EAAC;EAAK;EAAQ;CAAK,CAAC,CAAC,SAAS,QAAQ,IAAI,2BAA2B,KAAK,CAAC,CAAC,YAAY,KAAK,EAAE;AAEpG;AAEA,SAAS,IAAI,MAAkC;CAC7C,OAAO,QAAQ,IAAI,KAAK,EAAE,KAAK,KAAK,KAAA;AACtC;;AAGA,SAAgB,0BACd,UACA,OACM;CACN,IAAI,CAAC,0BAA0B,eAAe,GAAG;CACjD,IAAI;EACF,MAAM,eAAe,IAAI,sBAAsB;EAC/C,WAAW,IAAI,QAAQ,mDAAmD;GACxE,MAAM;GACN,SAAS;GACT,eAAe;GACf,cAAc;GACd,cAAc;EAChB,CAAC;EACD,OAAO,QAAQ;GACb,YAAY,oBAAoB,MAAM;GACtC,OAAO;GACP,YAAY;IACV,gBAAgB;IAChB,UAAU,SAAS;IACnB,MAAM,SAAS;IACf,kBAAkB,MAAM;IACxB,iBAAiB,MAAM;IACvB,iBAAiB,QAAQ,YAAY;IACrC,qBAAqB,IAAI,mBAAmB;IAC5C,eAAe;IACf,iBAAiB,IAAI,wBAAwB;GAC/C;EACF,CAAC;CACH,QAAQ,CAER;AACF"}
@@ -26,4 +26,6 @@ export declare function workItemThreadTitle(item: Pick<WorkItemBranchInput, 'sou
26
26
  * lost their identifier fall back to the id-derived branch.
27
27
  */
28
28
  export declare function workItemBranch(item: WorkItemBranchInput): string;
29
+ /** The pull request a `factory/pr-<number>` branch was named after, the inverse of {@link workItemBranch}. */
30
+ export declare function pullRequestNumberFromBranch(branch: string): number | undefined;
29
31
  //# sourceMappingURL=work-item-branch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"work-item-branch.d.ts","sourceRoot":"","sources":["../src/work-item-branch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAEnF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,GAAG,QAAQ,CAAC;AAE7G,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,oBAAoB,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,sBAAsB,GAAG,IAAI,GAAG,SAAS,GAAG,oBAAoB,CAOpH;AAOD,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS,CAKzG;AAED,yHAAyH;AACzH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACzE,MAAM,CAIR;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAWhE"}
1
+ {"version":3,"file":"work-item-branch.d.ts","sourceRoot":"","sources":["../src/work-item-branch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAEnF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,GAAG,QAAQ,CAAC;AAE7G,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,oBAAoB,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,sBAAsB,GAAG,IAAI,GAAG,SAAS,GAAG,oBAAoB,CAOpH;AAOD,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS,CAKzG;AAED,yHAAyH;AACzH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACzE,MAAM,CAIR;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAWhE;AAED,8GAA8G;AAC9G,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG9E"}
@@ -39,7 +39,12 @@ function workItemBranch(item) {
39
39
  }
40
40
  return `factory/item-${item.id}`;
41
41
  }
42
+ /** The pull request a `factory/pr-<number>` branch was named after, the inverse of {@link workItemBranch}. */
43
+ function pullRequestNumberFromBranch(branch) {
44
+ const match = /^factory\/pr-([1-9]\d*)$/.exec(branch);
45
+ return match ? Number(match[1]) : void 0;
46
+ }
42
47
  //#endregion
43
- export { workItemBranch, workItemBranchSource, workItemNumber, workItemThreadTitle };
48
+ export { pullRequestNumberFromBranch, workItemBranch, workItemBranchSource, workItemNumber, workItemThreadTitle };
44
49
 
45
50
  //# sourceMappingURL=work-item-branch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"work-item-branch.js","names":[],"sources":["../src/work-item-branch.ts"],"sourcesContent":["import type { ExternalWorkItemSource } from './storage/domains/work-items/base.js';\n\n/**\n * Where a card came from, in the vocabulary branch naming reads. Server rows\n * map their `externalSource` into this with {@link workItemBranchSource}; the\n * board's own `WorkItem['source']` is already this union.\n */\nexport type WorkItemBranchSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'slack-thread' | 'manual';\n\nexport interface WorkItemBranchInput {\n id: string;\n source: WorkItemBranchSource;\n metadata?: Record<string, unknown> | null;\n}\n\n/** Map a stored item's provenance onto the source vocabulary branch naming reads. */\nexport function workItemBranchSource(externalSource: ExternalWorkItemSource | null | undefined): WorkItemBranchSource {\n if (!externalSource) return 'manual';\n if (externalSource.integrationId === 'linear') return 'linear-issue';\n // Only GitHub and Linear carry provider identities; anything else (a Slack\n // thread, say) is a plain work item rather than a mislabeled GitHub issue.\n if (externalSource.integrationId !== 'github') return 'manual';\n return externalSource.type === 'pull-request' ? 'github-pr' : 'github-issue';\n}\n\nfunction branchNumber(metadata: Record<string, unknown>, key: string): number | undefined {\n const value = metadata[key] ?? metadata.number;\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : undefined;\n}\n\n/** The provider number a GitHub card carries — the `#12` its runs and thread titles name it by. */\nexport function workItemNumber(item: Pick<WorkItemBranchInput, 'source' | 'metadata'>): number | undefined {\n const metadata = item.metadata ?? {};\n if (item.source === 'github-issue') return branchNumber(metadata, 'githubIssueNumber');\n if (item.source === 'github-pr') return branchNumber(metadata, 'githubPullRequestNumber');\n return;\n}\n\n/** How a card names its thread: a Linear title already opens with its identifier, a GitHub card gets its number here. */\nexport function workItemThreadTitle(\n item: Pick<WorkItemBranchInput, 'source' | 'metadata'> & { title: string },\n): string {\n const number = workItemNumber(item);\n if (number === undefined) return item.title;\n return `${item.source === 'github-pr' ? 'PR' : 'Issue'} #${number}: ${item.title}`;\n}\n\n/**\n * The git branch an item's runs and sessions share, one grammar for both sides\n * of the wire: the dispatcher names autonomous run branches with it and the\n * board opens card sessions on it, so both converge on one checkout per item.\n * Cards without a provider identity (manual, Slack) and cards whose metadata\n * lost their identifier fall back to the id-derived branch.\n */\nexport function workItemBranch(item: WorkItemBranchInput): string {\n const metadata = item.metadata ?? {};\n const githubNumber = workItemNumber(item);\n if (githubNumber !== undefined) {\n return item.source === 'github-issue' ? `factory/issue-${githubNumber}` : `factory/pr-${githubNumber}`;\n }\n if (item.source === 'linear-issue' && typeof metadata.identifier === 'string') {\n const identifier = metadata.identifier.trim();\n if (identifier) return `factory/linear-${identifier.toLowerCase()}`;\n }\n return `factory/item-${item.id}`;\n}\n"],"mappings":";;AAgBA,SAAgB,qBAAqB,gBAAiF;CACpH,IAAI,CAAC,gBAAgB,OAAO;CAC5B,IAAI,eAAe,kBAAkB,UAAU,OAAO;CAGtD,IAAI,eAAe,kBAAkB,UAAU,OAAO;CACtD,OAAO,eAAe,SAAS,iBAAiB,cAAc;AAChE;AAEA,SAAS,aAAa,UAAmC,KAAiC;CACxF,MAAM,QAAQ,SAAS,QAAQ,SAAS;CACxC,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ,IAAI,QAAQ,KAAA;AACrF;;AAGA,SAAgB,eAAe,MAA4E;CACzG,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,IAAI,KAAK,WAAW,gBAAgB,OAAO,aAAa,UAAU,mBAAmB;CACrF,IAAI,KAAK,WAAW,aAAa,OAAO,aAAa,UAAU,yBAAyB;AAE1F;;AAGA,SAAgB,oBACd,MACQ;CACR,MAAM,SAAS,eAAe,IAAI;CAClC,IAAI,WAAW,KAAA,GAAW,OAAO,KAAK;CACtC,OAAO,GAAG,KAAK,WAAW,cAAc,OAAO,QAAQ,IAAI,OAAO,IAAI,KAAK;AAC7E;;;;;;;;AASA,SAAgB,eAAe,MAAmC;CAChE,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,MAAM,eAAe,eAAe,IAAI;CACxC,IAAI,iBAAiB,KAAA,GACnB,OAAO,KAAK,WAAW,iBAAiB,iBAAiB,iBAAiB,cAAc;CAE1F,IAAI,KAAK,WAAW,kBAAkB,OAAO,SAAS,eAAe,UAAU;EAC7E,MAAM,aAAa,SAAS,WAAW,KAAK;EAC5C,IAAI,YAAY,OAAO,kBAAkB,WAAW,YAAY;CAClE;CACA,OAAO,gBAAgB,KAAK;AAC9B"}
1
+ {"version":3,"file":"work-item-branch.js","names":[],"sources":["../src/work-item-branch.ts"],"sourcesContent":["import type { ExternalWorkItemSource } from './storage/domains/work-items/base.js';\n\n/**\n * Where a card came from, in the vocabulary branch naming reads. Server rows\n * map their `externalSource` into this with {@link workItemBranchSource}; the\n * board's own `WorkItem['source']` is already this union.\n */\nexport type WorkItemBranchSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'slack-thread' | 'manual';\n\nexport interface WorkItemBranchInput {\n id: string;\n source: WorkItemBranchSource;\n metadata?: Record<string, unknown> | null;\n}\n\n/** Map a stored item's provenance onto the source vocabulary branch naming reads. */\nexport function workItemBranchSource(externalSource: ExternalWorkItemSource | null | undefined): WorkItemBranchSource {\n if (!externalSource) return 'manual';\n if (externalSource.integrationId === 'linear') return 'linear-issue';\n // Only GitHub and Linear carry provider identities; anything else (a Slack\n // thread, say) is a plain work item rather than a mislabeled GitHub issue.\n if (externalSource.integrationId !== 'github') return 'manual';\n return externalSource.type === 'pull-request' ? 'github-pr' : 'github-issue';\n}\n\nfunction branchNumber(metadata: Record<string, unknown>, key: string): number | undefined {\n const value = metadata[key] ?? metadata.number;\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : undefined;\n}\n\n/** The provider number a GitHub card carries — the `#12` its runs and thread titles name it by. */\nexport function workItemNumber(item: Pick<WorkItemBranchInput, 'source' | 'metadata'>): number | undefined {\n const metadata = item.metadata ?? {};\n if (item.source === 'github-issue') return branchNumber(metadata, 'githubIssueNumber');\n if (item.source === 'github-pr') return branchNumber(metadata, 'githubPullRequestNumber');\n return;\n}\n\n/** How a card names its thread: a Linear title already opens with its identifier, a GitHub card gets its number here. */\nexport function workItemThreadTitle(\n item: Pick<WorkItemBranchInput, 'source' | 'metadata'> & { title: string },\n): string {\n const number = workItemNumber(item);\n if (number === undefined) return item.title;\n return `${item.source === 'github-pr' ? 'PR' : 'Issue'} #${number}: ${item.title}`;\n}\n\n/**\n * The git branch an item's runs and sessions share, one grammar for both sides\n * of the wire: the dispatcher names autonomous run branches with it and the\n * board opens card sessions on it, so both converge on one checkout per item.\n * Cards without a provider identity (manual, Slack) and cards whose metadata\n * lost their identifier fall back to the id-derived branch.\n */\nexport function workItemBranch(item: WorkItemBranchInput): string {\n const metadata = item.metadata ?? {};\n const githubNumber = workItemNumber(item);\n if (githubNumber !== undefined) {\n return item.source === 'github-issue' ? `factory/issue-${githubNumber}` : `factory/pr-${githubNumber}`;\n }\n if (item.source === 'linear-issue' && typeof metadata.identifier === 'string') {\n const identifier = metadata.identifier.trim();\n if (identifier) return `factory/linear-${identifier.toLowerCase()}`;\n }\n return `factory/item-${item.id}`;\n}\n\n/** The pull request a `factory/pr-<number>` branch was named after, the inverse of {@link workItemBranch}. */\nexport function pullRequestNumberFromBranch(branch: string): number | undefined {\n const match = /^factory\\/pr-([1-9]\\d*)$/.exec(branch);\n return match ? Number(match[1]) : undefined;\n}\n"],"mappings":";;AAgBA,SAAgB,qBAAqB,gBAAiF;CACpH,IAAI,CAAC,gBAAgB,OAAO;CAC5B,IAAI,eAAe,kBAAkB,UAAU,OAAO;CAGtD,IAAI,eAAe,kBAAkB,UAAU,OAAO;CACtD,OAAO,eAAe,SAAS,iBAAiB,cAAc;AAChE;AAEA,SAAS,aAAa,UAAmC,KAAiC;CACxF,MAAM,QAAQ,SAAS,QAAQ,SAAS;CACxC,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ,IAAI,QAAQ,KAAA;AACrF;;AAGA,SAAgB,eAAe,MAA4E;CACzG,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,IAAI,KAAK,WAAW,gBAAgB,OAAO,aAAa,UAAU,mBAAmB;CACrF,IAAI,KAAK,WAAW,aAAa,OAAO,aAAa,UAAU,yBAAyB;AAE1F;;AAGA,SAAgB,oBACd,MACQ;CACR,MAAM,SAAS,eAAe,IAAI;CAClC,IAAI,WAAW,KAAA,GAAW,OAAO,KAAK;CACtC,OAAO,GAAG,KAAK,WAAW,cAAc,OAAO,QAAQ,IAAI,OAAO,IAAI,KAAK;AAC7E;;;;;;;;AASA,SAAgB,eAAe,MAAmC;CAChE,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,MAAM,eAAe,eAAe,IAAI;CACxC,IAAI,iBAAiB,KAAA,GACnB,OAAO,KAAK,WAAW,iBAAiB,iBAAiB,iBAAiB,cAAc;CAE1F,IAAI,KAAK,WAAW,kBAAkB,OAAO,SAAS,eAAe,UAAU;EAC7E,MAAM,aAAa,SAAS,WAAW,KAAK;EAC5C,IAAI,YAAY,OAAO,kBAAkB,WAAW,YAAY;CAClE;CACA,OAAO,gBAAgB,KAAK;AAC9B;;AAGA,SAAgB,4BAA4B,QAAoC;CAC9E,MAAM,QAAQ,2BAA2B,KAAK,MAAM;CACpD,OAAO,QAAQ,OAAO,MAAM,EAAE,IAAI,KAAA;AACpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAE/E,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,mCAAmC,CAAC;AAItG,OAAO,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAwB9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAO7E,eAAO,MAAM,2BAA2B,QAQQ,CAAC;AAEjD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,SAAS,CAS7F;AAED,eAAO,MAAM,mBAAmB,aAO9B,CAAC;AAEH,qBAAa,kBAAmB,YAAW,WAAW;;IAMlD,QAAQ,CAAC,QAAQ,EAAE,WAAW;gBAArB,QAAQ,EAAE,WAAW,EAC9B,kBAAkB,EAAE,MAAM,EAAE,EAC5B,eAAe,GAAE,MAAM,GAAG,SAA2C;IAqBjE,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO3C,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAMjD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAMrD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAyB7D,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAI7C;AAuDD,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,6BAA6B;IAC5C,iEAAiE;IACjE,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,4BAA4B;IAC5B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,gFAAgF;IAChF,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;iEAE6D;IAC7D,SAAS,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,yBAAyB,CAAC,CAAC;IAC9D,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;IAC/C,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;CAC9C;AAED,KAAK,mBAAmB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEtD,gFAAgF;AAChF,qBAAa,wBAAwB;;IAInC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI/B,QAAQ,CACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,mBAAmB,GAC9B,OAAO,CAAC,OAAO,CAAC;IAWb,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAS1D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,6BAAkC,IAuBlE,4CAA4C,uBAAuB,2MAidlF"}
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAE/E,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,mCAAmC,CAAC;AAItG,OAAO,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAwB9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAQ7E,eAAO,MAAM,2BAA2B,QAQQ,CAAC;AAEjD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,SAAS,CAS7F;AAED,eAAO,MAAM,mBAAmB,aAO9B,CAAC;AAEH,qBAAa,kBAAmB,YAAW,WAAW;;IAMlD,QAAQ,CAAC,QAAQ,EAAE,WAAW;gBAArB,QAAQ,EAAE,WAAW,EAC9B,kBAAkB,EAAE,MAAM,EAAE,EAC5B,eAAe,GAAE,MAAM,GAAG,SAA2C;IAqBjE,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO3C,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAMjD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAMrD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAyB7D,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAI7C;AAuDD,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,6BAA6B;IAC5C,iEAAiE;IACjE,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,4BAA4B;IAC5B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,gFAAgF;IAChF,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;iEAE6D;IAC7D,SAAS,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,yBAAyB,CAAC,CAAC;IAC9D,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;IAC/C,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;CAC9C;AAED,KAAK,mBAAmB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEtD,gFAAgF;AAChF,qBAAa,wBAAwB;;IAInC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI/B,QAAQ,CACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,mBAAmB,GAC9B,OAAO,CAAC,OAAO,CAAC;IAWb,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAS1D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,6BAAkC,IAuBlE,4CAA4C,uBAAuB,2MAkdlF"}
package/dist/workspace.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { timedPhase } from "./timing.js";
2
2
  import { getFactoryAuthOrgId, getFactoryAuthUserFromContext, getFactoryAuthUserId } from "./auth.js";
3
+ import { pullRequestNumberFromBranch } from "./work-item-branch.js";
3
4
  import { getGithubPat } from "./integrations/github/pat.js";
4
5
  import { registerGithubPatKind, registerGithubTokenInjector } from "./integrations/github/token-refresh.js";
5
6
  import { DEFAULT_COMMAND_TIMEOUT_MS, SetupCommandError, checkoutSessionBranch, materializeRepo, runSetupCommand, runTeardownCommand } from "./integrations/github/sandbox.js";
@@ -412,7 +413,8 @@ function createWorkspaceFactory(options = {}) {
412
413
  branch: session.branch,
413
414
  baseBranch: session.baseBranch || projectRepository.branch || repository.defaultBranch,
414
415
  token,
415
- repoFullName
416
+ repoFullName,
417
+ pullRequestNumber: pullRequestNumberFromBranch(session.branch)
416
418
  });
417
419
  if (projectRepository.setupCommand && !gate.setupDone) {
418
420
  if (hasFailedSetupCommand(session.id, projectRepository.setupCommand)) {