@mastra/factory 0.0.0-fix-thread-subscription-multi-instance-redis-streams-20260730204150

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 (313) hide show
  1. package/CHANGELOG.md +695 -0
  2. package/LICENSE.md +30 -0
  3. package/README.md +27 -0
  4. package/dist/auth.d.ts +181 -0
  5. package/dist/auth.d.ts.map +1 -0
  6. package/dist/auth.js +505 -0
  7. package/dist/auth.js.map +1 -0
  8. package/dist/capabilities/connection.d.ts +9 -0
  9. package/dist/capabilities/connection.d.ts.map +1 -0
  10. package/dist/capabilities/connection.js +1 -0
  11. package/dist/capabilities/intake.d.ts +140 -0
  12. package/dist/capabilities/intake.d.ts.map +1 -0
  13. package/dist/capabilities/intake.js +1 -0
  14. package/dist/capabilities/version-control.d.ts +245 -0
  15. package/dist/capabilities/version-control.d.ts.map +1 -0
  16. package/dist/capabilities/version-control.js +1 -0
  17. package/dist/factory.d.ts +156 -0
  18. package/dist/factory.d.ts.map +1 -0
  19. package/dist/factory.js +483 -0
  20. package/dist/factory.js.map +1 -0
  21. package/dist/index.d.ts +14 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +7 -0
  24. package/dist/integrations/base.d.ts +210 -0
  25. package/dist/integrations/base.d.ts.map +1 -0
  26. package/dist/integrations/base.js +1 -0
  27. package/dist/integrations/github/config.d.ts +60 -0
  28. package/dist/integrations/github/config.d.ts.map +1 -0
  29. package/dist/integrations/github/config.js +42 -0
  30. package/dist/integrations/github/config.js.map +1 -0
  31. package/dist/integrations/github/factory-session.d.ts +12 -0
  32. package/dist/integrations/github/factory-session.d.ts.map +1 -0
  33. package/dist/integrations/github/factory-session.js +37 -0
  34. package/dist/integrations/github/factory-session.js.map +1 -0
  35. package/dist/integrations/github/integration.d.ts +191 -0
  36. package/dist/integrations/github/integration.d.ts.map +1 -0
  37. package/dist/integrations/github/integration.js +1077 -0
  38. package/dist/integrations/github/integration.js.map +1 -0
  39. package/dist/integrations/github/issue-triage.d.ts +27 -0
  40. package/dist/integrations/github/issue-triage.d.ts.map +1 -0
  41. package/dist/integrations/github/issue-triage.js +82 -0
  42. package/dist/integrations/github/issue-triage.js.map +1 -0
  43. package/dist/integrations/github/pat.d.ts +38 -0
  44. package/dist/integrations/github/pat.d.ts.map +1 -0
  45. package/dist/integrations/github/pat.js +59 -0
  46. package/dist/integrations/github/pat.js.map +1 -0
  47. package/dist/integrations/github/provenance.d.ts +27 -0
  48. package/dist/integrations/github/provenance.d.ts.map +1 -0
  49. package/dist/integrations/github/provenance.js +75 -0
  50. package/dist/integrations/github/provenance.js.map +1 -0
  51. package/dist/integrations/github/routes.d.ts +69 -0
  52. package/dist/integrations/github/routes.d.ts.map +1 -0
  53. package/dist/integrations/github/routes.js +1324 -0
  54. package/dist/integrations/github/routes.js.map +1 -0
  55. package/dist/integrations/github/rules.d.ts +78 -0
  56. package/dist/integrations/github/rules.d.ts.map +1 -0
  57. package/dist/integrations/github/rules.js +362 -0
  58. package/dist/integrations/github/rules.js.map +1 -0
  59. package/dist/integrations/github/sandbox-release.d.ts +38 -0
  60. package/dist/integrations/github/sandbox-release.d.ts.map +1 -0
  61. package/dist/integrations/github/sandbox-release.js +74 -0
  62. package/dist/integrations/github/sandbox-release.js.map +1 -0
  63. package/dist/integrations/github/sandbox.d.ts +281 -0
  64. package/dist/integrations/github/sandbox.d.ts.map +1 -0
  65. package/dist/integrations/github/sandbox.js +547 -0
  66. package/dist/integrations/github/sandbox.js.map +1 -0
  67. package/dist/integrations/github/session-subscriptions.d.ts +26 -0
  68. package/dist/integrations/github/session-subscriptions.d.ts.map +1 -0
  69. package/dist/integrations/github/session-subscriptions.js +192 -0
  70. package/dist/integrations/github/session-subscriptions.js.map +1 -0
  71. package/dist/integrations/github/subscriptions.d.ts +54 -0
  72. package/dist/integrations/github/subscriptions.d.ts.map +1 -0
  73. package/dist/integrations/github/subscriptions.js +62 -0
  74. package/dist/integrations/github/subscriptions.js.map +1 -0
  75. package/dist/integrations/github/token-refresh.d.ts +12 -0
  76. package/dist/integrations/github/token-refresh.d.ts.map +1 -0
  77. package/dist/integrations/github/token-refresh.js +24 -0
  78. package/dist/integrations/github/token-refresh.js.map +1 -0
  79. package/dist/integrations/github/webhook.d.ts +87 -0
  80. package/dist/integrations/github/webhook.d.ts.map +1 -0
  81. package/dist/integrations/github/webhook.js +397 -0
  82. package/dist/integrations/github/webhook.js.map +1 -0
  83. package/dist/integrations/linear/agent-tools.d.ts +34 -0
  84. package/dist/integrations/linear/agent-tools.d.ts.map +1 -0
  85. package/dist/integrations/linear/agent-tools.js +85 -0
  86. package/dist/integrations/linear/agent-tools.js.map +1 -0
  87. package/dist/integrations/linear/integration.d.ts +233 -0
  88. package/dist/integrations/linear/integration.d.ts.map +1 -0
  89. package/dist/integrations/linear/integration.js +672 -0
  90. package/dist/integrations/linear/integration.js.map +1 -0
  91. package/dist/integrations/linear/routes.d.ts +61 -0
  92. package/dist/integrations/linear/routes.d.ts.map +1 -0
  93. package/dist/integrations/linear/routes.js +239 -0
  94. package/dist/integrations/linear/routes.js.map +1 -0
  95. package/dist/integrations/linear/rules.d.ts +42 -0
  96. package/dist/integrations/linear/rules.d.ts.map +1 -0
  97. package/dist/integrations/linear/rules.js +133 -0
  98. package/dist/integrations/linear/rules.js.map +1 -0
  99. package/dist/integrations/linear/storage.d.ts +65 -0
  100. package/dist/integrations/linear/storage.d.ts.map +1 -0
  101. package/dist/integrations/linear/storage.js +1 -0
  102. package/dist/integrations/platform/api-client.d.ts +26 -0
  103. package/dist/integrations/platform/api-client.d.ts.map +1 -0
  104. package/dist/integrations/platform/api-client.js +156 -0
  105. package/dist/integrations/platform/api-client.js.map +1 -0
  106. package/dist/integrations/platform/github/event-worker.d.ts +49 -0
  107. package/dist/integrations/platform/github/event-worker.d.ts.map +1 -0
  108. package/dist/integrations/platform/github/event-worker.js +348 -0
  109. package/dist/integrations/platform/github/event-worker.js.map +1 -0
  110. package/dist/integrations/platform/github/integration.d.ts +50 -0
  111. package/dist/integrations/platform/github/integration.d.ts.map +1 -0
  112. package/dist/integrations/platform/github/integration.js +961 -0
  113. package/dist/integrations/platform/github/integration.js.map +1 -0
  114. package/dist/integrations/platform/linear/integration.d.ts +46 -0
  115. package/dist/integrations/platform/linear/integration.d.ts.map +1 -0
  116. package/dist/integrations/platform/linear/integration.js +483 -0
  117. package/dist/integrations/platform/linear/integration.js.map +1 -0
  118. package/dist/integrations/workos/integration.d.ts +39 -0
  119. package/dist/integrations/workos/integration.d.ts.map +1 -0
  120. package/dist/integrations/workos/integration.js +91 -0
  121. package/dist/integrations/workos/integration.js.map +1 -0
  122. package/dist/routes/config.d.ts +235 -0
  123. package/dist/routes/config.d.ts.map +1 -0
  124. package/dist/routes/config.js +972 -0
  125. package/dist/routes/config.js.map +1 -0
  126. package/dist/routes/custom-provider-source.d.ts +52 -0
  127. package/dist/routes/custom-provider-source.d.ts.map +1 -0
  128. package/dist/routes/custom-provider-source.js +124 -0
  129. package/dist/routes/custom-provider-source.js.map +1 -0
  130. package/dist/routes/fs.d.ts +151 -0
  131. package/dist/routes/fs.d.ts.map +1 -0
  132. package/dist/routes/fs.js +708 -0
  133. package/dist/routes/fs.js.map +1 -0
  134. package/dist/routes/intake.d.ts +23 -0
  135. package/dist/routes/intake.d.ts.map +1 -0
  136. package/dist/routes/intake.js +179 -0
  137. package/dist/routes/intake.js.map +1 -0
  138. package/dist/routes/oauth.d.ts +43 -0
  139. package/dist/routes/oauth.d.ts.map +1 -0
  140. package/dist/routes/oauth.js +463 -0
  141. package/dist/routes/oauth.js.map +1 -0
  142. package/dist/routes/projects.d.ts +19 -0
  143. package/dist/routes/projects.d.ts.map +1 -0
  144. package/dist/routes/projects.js +461 -0
  145. package/dist/routes/projects.js.map +1 -0
  146. package/dist/routes/provider-credentials.d.ts +81 -0
  147. package/dist/routes/provider-credentials.d.ts.map +1 -0
  148. package/dist/routes/provider-credentials.js +86 -0
  149. package/dist/routes/provider-credentials.js.map +1 -0
  150. package/dist/routes/route.d.ts +48 -0
  151. package/dist/routes/route.d.ts.map +1 -0
  152. package/dist/routes/route.js +15 -0
  153. package/dist/routes/route.js.map +1 -0
  154. package/dist/routes/skills.d.ts +30 -0
  155. package/dist/routes/skills.d.ts.map +1 -0
  156. package/dist/routes/skills.js +168 -0
  157. package/dist/routes/skills.js.map +1 -0
  158. package/dist/routes/surface.d.ts +91 -0
  159. package/dist/routes/surface.d.ts.map +1 -0
  160. package/dist/routes/surface.js +260 -0
  161. package/dist/routes/surface.js.map +1 -0
  162. package/dist/routes/tenant-credentials.d.ts +74 -0
  163. package/dist/routes/tenant-credentials.d.ts.map +1 -0
  164. package/dist/routes/tenant-credentials.js +156 -0
  165. package/dist/routes/tenant-credentials.js.map +1 -0
  166. package/dist/routes/work-items.d.ts +40 -0
  167. package/dist/routes/work-items.d.ts.map +1 -0
  168. package/dist/routes/work-items.js +695 -0
  169. package/dist/routes/work-items.js.map +1 -0
  170. package/dist/rules/binding-context.d.ts +5 -0
  171. package/dist/rules/binding-context.d.ts.map +1 -0
  172. package/dist/rules/binding-context.js +28 -0
  173. package/dist/rules/binding-context.js.map +1 -0
  174. package/dist/rules/defaults.d.ts +9 -0
  175. package/dist/rules/defaults.d.ts.map +1 -0
  176. package/dist/rules/defaults.js +260 -0
  177. package/dist/rules/defaults.js.map +1 -0
  178. package/dist/rules/dispatcher.d.ts +42 -0
  179. package/dist/rules/dispatcher.d.ts.map +1 -0
  180. package/dist/rules/dispatcher.js +518 -0
  181. package/dist/rules/dispatcher.js.map +1 -0
  182. package/dist/rules/index.d.ts +7 -0
  183. package/dist/rules/index.d.ts.map +1 -0
  184. package/dist/rules/index.js +5 -0
  185. package/dist/rules/processor.d.ts +54 -0
  186. package/dist/rules/processor.d.ts.map +1 -0
  187. package/dist/rules/processor.js +378 -0
  188. package/dist/rules/processor.js.map +1 -0
  189. package/dist/rules/resolve.d.ts +17 -0
  190. package/dist/rules/resolve.d.ts.map +1 -0
  191. package/dist/rules/resolve.js +30 -0
  192. package/dist/rules/resolve.js.map +1 -0
  193. package/dist/rules/start-coordinator.d.ts +60 -0
  194. package/dist/rules/start-coordinator.d.ts.map +1 -0
  195. package/dist/rules/start-coordinator.js +194 -0
  196. package/dist/rules/start-coordinator.js.map +1 -0
  197. package/dist/rules/tools.d.ts +10 -0
  198. package/dist/rules/tools.d.ts.map +1 -0
  199. package/dist/rules/tools.js +58 -0
  200. package/dist/rules/tools.js.map +1 -0
  201. package/dist/rules/transition-service.d.ts +49 -0
  202. package/dist/rules/transition-service.d.ts.map +1 -0
  203. package/dist/rules/transition-service.js +232 -0
  204. package/dist/rules/transition-service.js.map +1 -0
  205. package/dist/rules/types.d.ts +234 -0
  206. package/dist/rules/types.d.ts.map +1 -0
  207. package/dist/rules/types.js +38 -0
  208. package/dist/rules/types.js.map +1 -0
  209. package/dist/rules/validation.d.ts +11 -0
  210. package/dist/rules/validation.d.ts.map +1 -0
  211. package/dist/rules/validation.js +308 -0
  212. package/dist/rules/validation.js.map +1 -0
  213. package/dist/sandbox/fleet.d.ts +222 -0
  214. package/dist/sandbox/fleet.d.ts.map +1 -0
  215. package/dist/sandbox/fleet.js +322 -0
  216. package/dist/sandbox/fleet.js.map +1 -0
  217. package/dist/sandbox/reattach.d.ts +3 -0
  218. package/dist/sandbox/reattach.d.ts.map +1 -0
  219. package/dist/sandbox/reattach.js +16 -0
  220. package/dist/sandbox/reattach.js.map +1 -0
  221. package/dist/server-error.d.ts +12 -0
  222. package/dist/server-error.d.ts.map +1 -0
  223. package/dist/server-error.js +16 -0
  224. package/dist/server-error.js.map +1 -0
  225. package/dist/skills/service.d.ts +48 -0
  226. package/dist/skills/service.d.ts.map +1 -0
  227. package/dist/skills/service.js +40 -0
  228. package/dist/skills/service.js.map +1 -0
  229. package/dist/spa-static.d.ts +33 -0
  230. package/dist/spa-static.d.ts.map +1 -0
  231. package/dist/spa-static.js +104 -0
  232. package/dist/spa-static.js.map +1 -0
  233. package/dist/state-signing.d.ts +59 -0
  234. package/dist/state-signing.d.ts.map +1 -0
  235. package/dist/state-signing.js +83 -0
  236. package/dist/state-signing.js.map +1 -0
  237. package/dist/storage/domains/audit/agent-audit.d.ts +27 -0
  238. package/dist/storage/domains/audit/agent-audit.d.ts.map +1 -0
  239. package/dist/storage/domains/audit/agent-audit.js +66 -0
  240. package/dist/storage/domains/audit/agent-audit.js.map +1 -0
  241. package/dist/storage/domains/audit/base.d.ts +140 -0
  242. package/dist/storage/domains/audit/base.d.ts.map +1 -0
  243. package/dist/storage/domains/audit/base.js +184 -0
  244. package/dist/storage/domains/audit/base.js.map +1 -0
  245. package/dist/storage/domains/audit/domain.d.ts +69 -0
  246. package/dist/storage/domains/audit/domain.d.ts.map +1 -0
  247. package/dist/storage/domains/audit/domain.js +167 -0
  248. package/dist/storage/domains/audit/domain.js.map +1 -0
  249. package/dist/storage/domains/channel-identity/base.d.ts +96 -0
  250. package/dist/storage/domains/channel-identity/base.d.ts.map +1 -0
  251. package/dist/storage/domains/channel-identity/base.js +149 -0
  252. package/dist/storage/domains/channel-identity/base.js.map +1 -0
  253. package/dist/storage/domains/credentials/base.d.ts +134 -0
  254. package/dist/storage/domains/credentials/base.d.ts.map +1 -0
  255. package/dist/storage/domains/credentials/base.js +273 -0
  256. package/dist/storage/domains/credentials/base.js.map +1 -0
  257. package/dist/storage/domains/custom-providers/base.d.ts +57 -0
  258. package/dist/storage/domains/custom-providers/base.d.ts.map +1 -0
  259. package/dist/storage/domains/custom-providers/base.js +145 -0
  260. package/dist/storage/domains/custom-providers/base.js.map +1 -0
  261. package/dist/storage/domains/intake/base.d.ts +38 -0
  262. package/dist/storage/domains/intake/base.d.ts.map +1 -0
  263. package/dist/storage/domains/intake/base.js +80 -0
  264. package/dist/storage/domains/intake/base.js.map +1 -0
  265. package/dist/storage/domains/integrations/base.d.ts +126 -0
  266. package/dist/storage/domains/integrations/base.d.ts.map +1 -0
  267. package/dist/storage/domains/integrations/base.js +317 -0
  268. package/dist/storage/domains/integrations/base.js.map +1 -0
  269. package/dist/storage/domains/memory-settings/base.d.ts +62 -0
  270. package/dist/storage/domains/memory-settings/base.d.ts.map +1 -0
  271. package/dist/storage/domains/memory-settings/base.js +126 -0
  272. package/dist/storage/domains/memory-settings/base.js.map +1 -0
  273. package/dist/storage/domains/model-packs/base.d.ts +49 -0
  274. package/dist/storage/domains/model-packs/base.d.ts.map +1 -0
  275. package/dist/storage/domains/model-packs/base.js +96 -0
  276. package/dist/storage/domains/model-packs/base.js.map +1 -0
  277. package/dist/storage/domains/projects/base.d.ts +58 -0
  278. package/dist/storage/domains/projects/base.d.ts.map +1 -0
  279. package/dist/storage/domains/projects/base.js +111 -0
  280. package/dist/storage/domains/projects/base.js.map +1 -0
  281. package/dist/storage/domains/queue-health/base.d.ts +52 -0
  282. package/dist/storage/domains/queue-health/base.d.ts.map +1 -0
  283. package/dist/storage/domains/queue-health/base.js +122 -0
  284. package/dist/storage/domains/queue-health/base.js.map +1 -0
  285. package/dist/storage/domains/source-control/base.d.ts +358 -0
  286. package/dist/storage/domains/source-control/base.d.ts.map +1 -0
  287. package/dist/storage/domains/source-control/base.js +908 -0
  288. package/dist/storage/domains/source-control/base.js.map +1 -0
  289. package/dist/storage/domains/source-control/inmemory.d.ts +175 -0
  290. package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -0
  291. package/dist/storage/domains/source-control/inmemory.js +377 -0
  292. package/dist/storage/domains/source-control/inmemory.js.map +1 -0
  293. package/dist/storage/domains/work-items/base.d.ts +412 -0
  294. package/dist/storage/domains/work-items/base.d.ts.map +1 -0
  295. package/dist/storage/domains/work-items/base.js +1309 -0
  296. package/dist/storage/domains/work-items/base.js.map +1 -0
  297. package/dist/storage/domains/work-items/metrics.d.ts +101 -0
  298. package/dist/storage/domains/work-items/metrics.d.ts.map +1 -0
  299. package/dist/storage/domains/work-items/metrics.js +221 -0
  300. package/dist/storage/domains/work-items/metrics.js.map +1 -0
  301. package/dist/timing.d.ts +15 -0
  302. package/dist/timing.d.ts.map +1 -0
  303. package/dist/timing.js +34 -0
  304. package/dist/timing.js.map +1 -0
  305. package/dist/workspace.d.ts +24 -0
  306. package/dist/workspace.d.ts.map +1 -0
  307. package/dist/workspace.js +286 -0
  308. package/dist/workspace.js.map +1 -0
  309. package/factory-skills/configure-factory-rules/SKILL.md +67 -0
  310. package/factory-skills/factory-plan/SKILL.md +61 -0
  311. package/factory-skills/factory-review/SKILL.md +155 -0
  312. package/factory-skills/factory-triage/SKILL.md +77 -0
  313. package/package.json +81 -0
@@ -0,0 +1,234 @@
1
+ export type WorkItemSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'manual';
2
+ export declare const FACTORY_RULE_STAGES: readonly ["intake", "triage", "planning", "execute", "review", "done", "canceled"];
3
+ export type FactoryRuleStage = (typeof FACTORY_RULE_STAGES)[number];
4
+ export declare const FACTORY_RULE_BOARDS: readonly ["work", "review"];
5
+ export type FactoryRuleBoard = (typeof FACTORY_RULE_BOARDS)[number];
6
+ export declare const FACTORY_RULE_SOURCES: readonly ["issue", "pullRequest", "linearIssue", "manual"];
7
+ export type FactoryRuleSource = (typeof FACTORY_RULE_SOURCES)[number];
8
+ export declare const FACTORY_GITHUB_EVENTS: readonly ["issueOpened", "pullRequestOpened", "pullRequestUpdated", "pullRequestReviewRequested", "pullRequestMerged", "pullRequestClosed"];
9
+ export type FactoryGithubEventName = (typeof FACTORY_GITHUB_EVENTS)[number];
10
+ export declare const FACTORY_LINEAR_EVENTS: readonly ["issueObserved"];
11
+ export type FactoryLinearEventName = (typeof FACTORY_LINEAR_EVENTS)[number];
12
+ export type FactoryRuleJsonValue = null | boolean | number | string | FactoryRuleJsonValue[] | {
13
+ [key: string]: FactoryRuleJsonValue;
14
+ };
15
+ export interface FactoryRuleItemContext {
16
+ id: string;
17
+ source: WorkItemSource;
18
+ sourceKey: string | null;
19
+ parentWorkItemId: string | null;
20
+ title: string;
21
+ url: string | null;
22
+ stages: readonly string[];
23
+ }
24
+ export type FactoryRuleActor = {
25
+ type: 'human';
26
+ id: string;
27
+ } | {
28
+ type: 'agent';
29
+ bindingId: string;
30
+ role: string;
31
+ } | {
32
+ type: 'github';
33
+ login: string;
34
+ trusted: boolean;
35
+ factoryAuthored: boolean;
36
+ } | {
37
+ type: 'system';
38
+ id: string;
39
+ };
40
+ export interface FactoryRuleIngressIdentity {
41
+ type: 'human' | 'agent' | 'toolResult' | 'github' | 'linear' | 'rule';
42
+ id: string;
43
+ }
44
+ export interface FactoryRuleCausalEntry {
45
+ ingressId: string;
46
+ decisionType: FactoryCommitDecision['type'];
47
+ }
48
+ export interface FactoryRuleContextBase {
49
+ tenant: {
50
+ orgId: string;
51
+ projectId: string;
52
+ };
53
+ actor: FactoryRuleActor;
54
+ ingress: FactoryRuleIngressIdentity;
55
+ cause: string;
56
+ causalChain: readonly FactoryRuleCausalEntry[];
57
+ ruleSetVersion: string;
58
+ }
59
+ export interface FactoryBoundRuleContext extends FactoryRuleContextBase {
60
+ item: FactoryRuleItemContext;
61
+ board: FactoryRuleBoard;
62
+ itemRevision: number;
63
+ }
64
+ export interface FactoryStageRuleContext extends FactoryBoundRuleContext {
65
+ source: FactoryRuleSource;
66
+ stage: FactoryRuleStage;
67
+ fromStage: FactoryRuleStage;
68
+ toStage: FactoryRuleStage;
69
+ }
70
+ export interface FactoryToolResultRuleContext extends FactoryBoundRuleContext {
71
+ toolName: string;
72
+ threadId: string;
73
+ assistantMessageId: string;
74
+ toolCallId: string;
75
+ result: {
76
+ status: 'success' | 'error';
77
+ value: FactoryRuleJsonValue;
78
+ };
79
+ }
80
+ export interface FactoryGithubRuleContext extends FactoryRuleContextBase {
81
+ item?: FactoryRuleItemContext;
82
+ board?: FactoryRuleBoard;
83
+ itemRevision?: number;
84
+ event: FactoryGithubEventName;
85
+ deliveryId: string;
86
+ factory: {
87
+ createdAt: string;
88
+ };
89
+ repository: {
90
+ id: number;
91
+ fullName: string;
92
+ };
93
+ issue?: {
94
+ number: number;
95
+ title: string;
96
+ url: string;
97
+ createdAt?: string;
98
+ };
99
+ pullRequest?: {
100
+ number: number;
101
+ title: string;
102
+ url: string;
103
+ createdAt?: string;
104
+ state: 'open' | 'closed';
105
+ merged: boolean;
106
+ headBranch: string;
107
+ baseBranch: string;
108
+ };
109
+ }
110
+ export interface FactoryLinearRuleContext extends FactoryRuleContextBase {
111
+ item?: FactoryRuleItemContext;
112
+ board?: FactoryRuleBoard;
113
+ itemRevision?: number;
114
+ event: FactoryLinearEventName;
115
+ issue: {
116
+ id: string;
117
+ identifier: string;
118
+ title: string;
119
+ url: string;
120
+ state: string;
121
+ stateType: string;
122
+ priorityLabel: string;
123
+ assignee: string | null;
124
+ team: string | null;
125
+ labels: readonly string[];
126
+ createdAt: string;
127
+ updatedAt: string;
128
+ };
129
+ }
130
+ export type FactoryRuleHandler<TContext> = (context: Readonly<TContext>) => FactoryRuleDecision | void | Promise<FactoryRuleDecision | void>;
131
+ export interface FactoryBoardRuleLeaf {
132
+ onEnter?: FactoryRuleHandler<FactoryStageRuleContext>;
133
+ onExit?: FactoryRuleHandler<FactoryStageRuleContext>;
134
+ }
135
+ export interface FactoryToolRuleLeaf {
136
+ onResult?: FactoryRuleHandler<FactoryToolResultRuleContext>;
137
+ }
138
+ export interface FactoryGithubRuleLeaf {
139
+ onEvent?: FactoryRuleHandler<FactoryGithubRuleContext>;
140
+ }
141
+ export interface FactoryLinearRuleLeaf {
142
+ onEvent?: FactoryRuleHandler<FactoryLinearRuleContext>;
143
+ }
144
+ export type FactoryBoardRules = Partial<Record<FactoryRuleStage, Partial<Record<FactoryRuleSource, FactoryBoardRuleLeaf>>>>;
145
+ export interface FactoryRules {
146
+ version: string;
147
+ work: FactoryBoardRules;
148
+ review: FactoryBoardRules;
149
+ tools: Record<string, FactoryToolRuleLeaf>;
150
+ github: Partial<Record<FactoryGithubEventName, FactoryGithubRuleLeaf>>;
151
+ linear: Partial<Record<FactoryLinearEventName, FactoryLinearRuleLeaf>>;
152
+ }
153
+ export interface FactoryRulesOverrides {
154
+ work?: FactoryBoardRules;
155
+ review?: FactoryBoardRules;
156
+ tools?: Record<string, FactoryToolRuleLeaf>;
157
+ github?: Partial<Record<FactoryGithubEventName, FactoryGithubRuleLeaf>>;
158
+ linear?: Partial<Record<FactoryLinearEventName, FactoryLinearRuleLeaf>>;
159
+ }
160
+ export type FactoryRuleRejectionCode = 'forbidden' | 'invalid_transition' | 'missing_binding' | 'stale' | 'timeout' | 'rule_error' | 'causal_depth_exceeded' | 'repeated_transition';
161
+ export interface FactoryRuleRejectDecision {
162
+ type: 'reject';
163
+ code: FactoryRuleRejectionCode;
164
+ reason: string;
165
+ }
166
+ interface FactoryCommitDecisionBase {
167
+ idempotencyKey: string;
168
+ }
169
+ export interface FactoryTransitionDecision extends FactoryCommitDecisionBase {
170
+ type: 'transition';
171
+ board: FactoryRuleBoard;
172
+ stage: FactoryRuleStage;
173
+ /**
174
+ * Delivered to the item's active session (waking it if idle) after the
175
+ * transition commits. Skipped when the item has no active run binding, so
176
+ * informational messages never fail the transition.
177
+ */
178
+ message?: {
179
+ text: string;
180
+ role?: string;
181
+ };
182
+ }
183
+ export interface FactoryUpsertLinkedWorkItemDecision extends FactoryCommitDecisionBase {
184
+ type: 'upsertLinkedWorkItem';
185
+ board: FactoryRuleBoard;
186
+ source: WorkItemSource;
187
+ sourceKey: string;
188
+ title: string;
189
+ url: string | null;
190
+ stage: FactoryRuleStage;
191
+ metadata?: Record<string, FactoryRuleJsonValue>;
192
+ }
193
+ export interface FactoryInvokeSkillDecision extends FactoryCommitDecisionBase {
194
+ type: 'invokeSkill';
195
+ role: string;
196
+ skillName: string;
197
+ arguments?: string;
198
+ precedingMessage?: string;
199
+ }
200
+ export interface FactorySendMessageDecision extends FactoryCommitDecisionBase {
201
+ type: 'sendMessage';
202
+ role: string;
203
+ message: string;
204
+ priority?: 'medium' | 'high' | 'urgent';
205
+ idleBehavior?: 'persist' | 'wake';
206
+ prepareBinding?: boolean;
207
+ }
208
+ export interface FactoryNotifyDecision extends FactoryCommitDecisionBase {
209
+ type: 'notify';
210
+ title: string;
211
+ body?: string;
212
+ level?: 'info' | 'warning' | 'error';
213
+ }
214
+ export type FactoryCommitDecision = FactoryTransitionDecision | FactoryUpsertLinkedWorkItemDecision | FactoryInvokeSkillDecision | FactorySendMessageDecision | FactoryNotifyDecision;
215
+ export type FactoryRuleDecision = FactoryRuleRejectDecision | FactoryCommitDecision;
216
+ export interface FactoryTransitionResultAccepted {
217
+ status: 'accepted';
218
+ transitionId: string;
219
+ itemId: string;
220
+ revision: number;
221
+ stage: FactoryRuleStage;
222
+ decisions: FactoryCommitDecision[];
223
+ }
224
+ export interface FactoryTransitionResultRejected {
225
+ status: 'rejected';
226
+ transitionId: string;
227
+ itemId: string;
228
+ code: FactoryRuleRejectionCode;
229
+ reason: string;
230
+ }
231
+ export type FactoryTransitionResult = FactoryTransitionResultAccepted | FactoryTransitionResultRejected;
232
+ export declare function factoryRuleSourceForWorkItem(source: WorkItemSource): FactoryRuleSource;
233
+ export {};
234
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rules/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ //#region src/rules/types.ts
2
+ const FACTORY_RULE_STAGES = [
3
+ "intake",
4
+ "triage",
5
+ "planning",
6
+ "execute",
7
+ "review",
8
+ "done",
9
+ "canceled"
10
+ ];
11
+ const FACTORY_RULE_BOARDS = ["work", "review"];
12
+ const FACTORY_RULE_SOURCES = [
13
+ "issue",
14
+ "pullRequest",
15
+ "linearIssue",
16
+ "manual"
17
+ ];
18
+ const FACTORY_GITHUB_EVENTS = [
19
+ "issueOpened",
20
+ "pullRequestOpened",
21
+ "pullRequestUpdated",
22
+ "pullRequestReviewRequested",
23
+ "pullRequestMerged",
24
+ "pullRequestClosed"
25
+ ];
26
+ const FACTORY_LINEAR_EVENTS = ["issueObserved"];
27
+ function factoryRuleSourceForWorkItem(source) {
28
+ switch (source) {
29
+ case "github-issue": return "issue";
30
+ case "github-pr": return "pullRequest";
31
+ case "linear-issue": return "linearIssue";
32
+ case "manual": return "manual";
33
+ }
34
+ }
35
+ //#endregion
36
+ export { FACTORY_GITHUB_EVENTS, FACTORY_LINEAR_EVENTS, FACTORY_RULE_BOARDS, FACTORY_RULE_SOURCES, FACTORY_RULE_STAGES, factoryRuleSourceForWorkItem };
37
+
38
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/rules/types.ts"],"sourcesContent":["export type WorkItemSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'manual';\n\nexport const FACTORY_RULE_STAGES = ['intake', 'triage', 'planning', 'execute', 'review', 'done', 'canceled'] as const;\nexport type FactoryRuleStage = (typeof FACTORY_RULE_STAGES)[number];\n\nexport const FACTORY_RULE_BOARDS = ['work', 'review'] as const;\nexport type FactoryRuleBoard = (typeof FACTORY_RULE_BOARDS)[number];\n\nexport const FACTORY_RULE_SOURCES = ['issue', 'pullRequest', 'linearIssue', 'manual'] as const;\nexport type FactoryRuleSource = (typeof FACTORY_RULE_SOURCES)[number];\n\nexport const FACTORY_GITHUB_EVENTS = [\n 'issueOpened',\n 'pullRequestOpened',\n 'pullRequestUpdated',\n 'pullRequestReviewRequested',\n 'pullRequestMerged',\n 'pullRequestClosed',\n] as const;\nexport type FactoryGithubEventName = (typeof FACTORY_GITHUB_EVENTS)[number];\n\nexport const FACTORY_LINEAR_EVENTS = ['issueObserved'] as const;\nexport type FactoryLinearEventName = (typeof FACTORY_LINEAR_EVENTS)[number];\n\nexport type FactoryRuleJsonValue =\n | null\n | boolean\n | number\n | string\n | FactoryRuleJsonValue[]\n | { [key: string]: FactoryRuleJsonValue };\n\nexport interface FactoryRuleItemContext {\n id: string;\n source: WorkItemSource;\n sourceKey: string | null;\n parentWorkItemId: string | null;\n title: string;\n url: string | null;\n stages: readonly string[];\n}\n\nexport type FactoryRuleActor =\n | { type: 'human'; id: string }\n | { type: 'agent'; bindingId: string; role: string }\n | { type: 'github'; login: string; trusted: boolean; factoryAuthored: boolean }\n | { type: 'system'; id: string };\n\nexport interface FactoryRuleIngressIdentity {\n type: 'human' | 'agent' | 'toolResult' | 'github' | 'linear' | 'rule';\n id: string;\n}\n\nexport interface FactoryRuleCausalEntry {\n ingressId: string;\n decisionType: FactoryCommitDecision['type'];\n}\n\nexport interface FactoryRuleContextBase {\n tenant: { orgId: string; projectId: string };\n actor: FactoryRuleActor;\n ingress: FactoryRuleIngressIdentity;\n cause: string;\n causalChain: readonly FactoryRuleCausalEntry[];\n ruleSetVersion: string;\n}\n\nexport interface FactoryBoundRuleContext extends FactoryRuleContextBase {\n item: FactoryRuleItemContext;\n board: FactoryRuleBoard;\n itemRevision: number;\n}\n\nexport interface FactoryStageRuleContext extends FactoryBoundRuleContext {\n source: FactoryRuleSource;\n stage: FactoryRuleStage;\n fromStage: FactoryRuleStage;\n toStage: FactoryRuleStage;\n}\n\nexport interface FactoryToolResultRuleContext extends FactoryBoundRuleContext {\n toolName: string;\n threadId: string;\n assistantMessageId: string;\n toolCallId: string;\n result: {\n status: 'success' | 'error';\n value: FactoryRuleJsonValue;\n };\n}\n\nexport interface FactoryGithubRuleContext extends FactoryRuleContextBase {\n item?: FactoryRuleItemContext;\n board?: FactoryRuleBoard;\n itemRevision?: number;\n event: FactoryGithubEventName;\n deliveryId: string;\n factory: { createdAt: string };\n repository: { id: number; fullName: string };\n issue?: { number: number; title: string; url: string; createdAt?: string };\n pullRequest?: {\n number: number;\n title: string;\n url: string;\n createdAt?: string;\n state: 'open' | 'closed';\n merged: boolean;\n headBranch: string;\n baseBranch: string;\n };\n}\n\nexport interface FactoryLinearRuleContext extends FactoryRuleContextBase {\n item?: FactoryRuleItemContext;\n board?: FactoryRuleBoard;\n itemRevision?: number;\n event: FactoryLinearEventName;\n issue: {\n id: string;\n identifier: string;\n title: string;\n url: string;\n state: string;\n stateType: string;\n priorityLabel: string;\n assignee: string | null;\n team: string | null;\n labels: readonly string[];\n createdAt: string;\n updatedAt: string;\n };\n}\n\nexport type FactoryRuleHandler<TContext> = (\n context: Readonly<TContext>,\n) => FactoryRuleDecision | void | Promise<FactoryRuleDecision | void>;\n\nexport interface FactoryBoardRuleLeaf {\n onEnter?: FactoryRuleHandler<FactoryStageRuleContext>;\n onExit?: FactoryRuleHandler<FactoryStageRuleContext>;\n}\n\nexport interface FactoryToolRuleLeaf {\n onResult?: FactoryRuleHandler<FactoryToolResultRuleContext>;\n}\n\nexport interface FactoryGithubRuleLeaf {\n onEvent?: FactoryRuleHandler<FactoryGithubRuleContext>;\n}\n\nexport interface FactoryLinearRuleLeaf {\n onEvent?: FactoryRuleHandler<FactoryLinearRuleContext>;\n}\n\nexport type FactoryBoardRules = Partial<\n Record<FactoryRuleStage, Partial<Record<FactoryRuleSource, FactoryBoardRuleLeaf>>>\n>;\n\nexport interface FactoryRules {\n version: string;\n work: FactoryBoardRules;\n review: FactoryBoardRules;\n tools: Record<string, FactoryToolRuleLeaf>;\n github: Partial<Record<FactoryGithubEventName, FactoryGithubRuleLeaf>>;\n linear: Partial<Record<FactoryLinearEventName, FactoryLinearRuleLeaf>>;\n}\n\nexport interface FactoryRulesOverrides {\n work?: FactoryBoardRules;\n review?: FactoryBoardRules;\n tools?: Record<string, FactoryToolRuleLeaf>;\n github?: Partial<Record<FactoryGithubEventName, FactoryGithubRuleLeaf>>;\n linear?: Partial<Record<FactoryLinearEventName, FactoryLinearRuleLeaf>>;\n}\n\nexport type FactoryRuleRejectionCode =\n | 'forbidden'\n | 'invalid_transition'\n | 'missing_binding'\n | 'stale'\n | 'timeout'\n | 'rule_error'\n | 'causal_depth_exceeded'\n | 'repeated_transition';\n\nexport interface FactoryRuleRejectDecision {\n type: 'reject';\n code: FactoryRuleRejectionCode;\n reason: string;\n}\n\ninterface FactoryCommitDecisionBase {\n idempotencyKey: string;\n}\n\nexport interface FactoryTransitionDecision extends FactoryCommitDecisionBase {\n type: 'transition';\n board: FactoryRuleBoard;\n stage: FactoryRuleStage;\n /**\n * Delivered to the item's active session (waking it if idle) after the\n * transition commits. Skipped when the item has no active run binding, so\n * informational messages never fail the transition.\n */\n message?: { text: string; role?: string };\n}\n\nexport interface FactoryUpsertLinkedWorkItemDecision extends FactoryCommitDecisionBase {\n type: 'upsertLinkedWorkItem';\n board: FactoryRuleBoard;\n source: WorkItemSource;\n sourceKey: string;\n title: string;\n url: string | null;\n stage: FactoryRuleStage;\n metadata?: Record<string, FactoryRuleJsonValue>;\n}\n\nexport interface FactoryInvokeSkillDecision extends FactoryCommitDecisionBase {\n type: 'invokeSkill';\n role: string;\n skillName: string;\n arguments?: string;\n precedingMessage?: string;\n}\n\nexport interface FactorySendMessageDecision extends FactoryCommitDecisionBase {\n type: 'sendMessage';\n role: string;\n message: string;\n priority?: 'medium' | 'high' | 'urgent';\n idleBehavior?: 'persist' | 'wake';\n prepareBinding?: boolean;\n}\n\nexport interface FactoryNotifyDecision extends FactoryCommitDecisionBase {\n type: 'notify';\n title: string;\n body?: string;\n level?: 'info' | 'warning' | 'error';\n}\n\nexport type FactoryCommitDecision =\n | FactoryTransitionDecision\n | FactoryUpsertLinkedWorkItemDecision\n | FactoryInvokeSkillDecision\n | FactorySendMessageDecision\n | FactoryNotifyDecision;\n\nexport type FactoryRuleDecision = FactoryRuleRejectDecision | FactoryCommitDecision;\n\nexport interface FactoryTransitionResultAccepted {\n status: 'accepted';\n transitionId: string;\n itemId: string;\n revision: number;\n stage: FactoryRuleStage;\n decisions: FactoryCommitDecision[];\n}\n\nexport interface FactoryTransitionResultRejected {\n status: 'rejected';\n transitionId: string;\n itemId: string;\n code: FactoryRuleRejectionCode;\n reason: string;\n}\n\nexport type FactoryTransitionResult = FactoryTransitionResultAccepted | FactoryTransitionResultRejected;\n\nexport function factoryRuleSourceForWorkItem(source: WorkItemSource): FactoryRuleSource {\n switch (source) {\n case 'github-issue':\n return 'issue';\n case 'github-pr':\n return 'pullRequest';\n case 'linear-issue':\n return 'linearIssue';\n case 'manual':\n return 'manual';\n }\n}\n"],"mappings":";AAEA,MAAa,sBAAsB;CAAC;CAAU;CAAU;CAAY;CAAW;CAAU;CAAQ;AAAU;AAG3G,MAAa,sBAAsB,CAAC,QAAQ,QAAQ;AAGpD,MAAa,uBAAuB;CAAC;CAAS;CAAe;CAAe;AAAQ;AAGpF,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,wBAAwB,CAAC,eAAe;AAyPrD,SAAgB,6BAA6B,QAA2C;CACtF,QAAQ,QAAR;EACE,KAAK,gBACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,gBACH,OAAO;EACT,KAAK,UACH,OAAO;CACX;AACF"}
@@ -0,0 +1,11 @@
1
+ import type { FactoryCommitDecision, FactoryRuleDecision, FactoryRuleJsonValue, FactoryRules } from './types.js';
2
+ export declare const MAX_FACTORY_RULE_CAUSAL_DEPTH = 8;
3
+ export declare class FactoryRuleValidationError extends Error {
4
+ readonly code = "invalid_factory_rule";
5
+ constructor(message: string);
6
+ }
7
+ export declare function normalizeFactoryRuleJsonValue(value: unknown, depth?: number, seen?: Set<object>): FactoryRuleJsonValue;
8
+ export declare function assertFactoryRules(rules: unknown): asserts rules is FactoryRules;
9
+ export declare function validateFactoryRuleDecision(value: unknown, causalDepth?: number): FactoryRuleDecision;
10
+ export declare function validateFactoryRuleDecisions(values: readonly unknown[], causalDepth?: number): FactoryCommitDecision[];
11
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/rules/validation.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEV,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EAGb,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,6BAA6B,IAAI,CAAC;AA+B/C,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,0BAA0B;gBAE3B,OAAO,EAAE,MAAM;CAI5B;AAoCD,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,EACd,KAAK,SAAI,EACT,IAAI,cAAoB,GACvB,oBAAoB,CAkCtB;AA8BD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,YAAY,CAqChF;AAQD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,SAAI,GAAG,mBAAmB,CAmIhG;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,EAAE,WAAW,SAAI,GAAG,qBAAqB,EAAE,CAiBjH"}
@@ -0,0 +1,308 @@
1
+ import { FACTORY_GITHUB_EVENTS, FACTORY_LINEAR_EVENTS, FACTORY_RULE_BOARDS, FACTORY_RULE_SOURCES, FACTORY_RULE_STAGES } from "./types.js";
2
+ //#region src/rules/validation.ts
3
+ const MAX_FACTORY_RULE_CAUSAL_DEPTH = 8;
4
+ const MAX_VERSION_LENGTH = 128;
5
+ const MAX_IDEMPOTENCY_KEY_LENGTH = 256;
6
+ const MAX_REASON_LENGTH = 512;
7
+ const MAX_TITLE_LENGTH = 512;
8
+ const MAX_MESSAGE_LENGTH = 8192;
9
+ const MAX_ARGUMENTS_LENGTH = 4096;
10
+ const MAX_ROLE_LENGTH = 32;
11
+ const MAX_SKILL_NAME_LENGTH = 128;
12
+ const MAX_SOURCE_KEY_LENGTH = 256;
13
+ const MAX_URL_LENGTH = 2048;
14
+ const MAX_METADATA_JSON_LENGTH = 16384;
15
+ const MAX_JSON_DEPTH = 8;
16
+ const MAX_JSON_COLLECTION_SIZE = 100;
17
+ const IDENTIFIER_RE = /^[a-z0-9][a-z0-9_-]*$/i;
18
+ const SKILL_NAME_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
19
+ const SENSITIVE_KEY_RE = /(?:authorization|cookie|credential|password|secret|token)/i;
20
+ const WORK_ITEM_SOURCES = [
21
+ "github-issue",
22
+ "github-pr",
23
+ "linear-issue",
24
+ "manual"
25
+ ];
26
+ const REJECTION_CODES = [
27
+ "forbidden",
28
+ "invalid_transition",
29
+ "missing_binding",
30
+ "stale",
31
+ "timeout",
32
+ "rule_error",
33
+ "causal_depth_exceeded",
34
+ "repeated_transition"
35
+ ];
36
+ var FactoryRuleValidationError = class extends Error {
37
+ code = "invalid_factory_rule";
38
+ constructor(message) {
39
+ super(message);
40
+ this.name = "FactoryRuleValidationError";
41
+ }
42
+ };
43
+ function isPlainObject(value) {
44
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
45
+ const prototype = Object.getPrototypeOf(value);
46
+ return prototype === Object.prototype || prototype === null;
47
+ }
48
+ function assertExactKeys(value, keys, label) {
49
+ const allowed = new Set(keys);
50
+ if (Object.keys(value).some((key) => !allowed.has(key))) throw new FactoryRuleValidationError(`${label} contains an unsupported field.`);
51
+ }
52
+ function boundedString(value, label, max, pattern) {
53
+ if (typeof value !== "string") throw new FactoryRuleValidationError(`${label} must be a string.`);
54
+ const normalized = value.trim();
55
+ if (normalized.length === 0 || normalized.length > max || pattern && !pattern.test(normalized)) throw new FactoryRuleValidationError(`${label} is invalid.`);
56
+ return normalized;
57
+ }
58
+ function optionalBoundedString(value, label, max) {
59
+ if (value === void 0) return void 0;
60
+ return boundedString(value, label, max);
61
+ }
62
+ function enumValue(value, allowed, label) {
63
+ if (typeof value !== "string" || !allowed.includes(value)) throw new FactoryRuleValidationError(`${label} is invalid.`);
64
+ return value;
65
+ }
66
+ function normalizeFactoryRuleJsonValue(value, depth = 0, seen = /* @__PURE__ */ new Set()) {
67
+ if (value === null || typeof value === "boolean" || typeof value === "string") return value;
68
+ if (typeof value === "number") {
69
+ if (!Number.isFinite(value)) throw new FactoryRuleValidationError("Rule metadata must contain finite numbers.");
70
+ return value;
71
+ }
72
+ if (depth >= MAX_JSON_DEPTH || typeof value !== "object" && !Array.isArray(value)) throw new FactoryRuleValidationError("Rule metadata is not bounded JSON.");
73
+ if (seen.has(value)) throw new FactoryRuleValidationError("Rule metadata must not contain cycles.");
74
+ seen.add(value);
75
+ try {
76
+ if (Array.isArray(value)) {
77
+ if (value.length > MAX_JSON_COLLECTION_SIZE) throw new FactoryRuleValidationError("Rule metadata contains too many entries.");
78
+ return value.map((entry) => normalizeFactoryRuleJsonValue(entry, depth + 1, seen));
79
+ }
80
+ if (!isPlainObject(value)) throw new FactoryRuleValidationError("Rule metadata must use plain objects.");
81
+ const entries = Object.entries(value);
82
+ if (entries.length > MAX_JSON_COLLECTION_SIZE) throw new FactoryRuleValidationError("Rule metadata contains too many fields.");
83
+ const sanitized = {};
84
+ for (const [key, entry] of entries) {
85
+ const normalizedKey = boundedString(key, "Rule metadata key", 128, IDENTIFIER_RE);
86
+ sanitized[normalizedKey] = SENSITIVE_KEY_RE.test(normalizedKey) ? "[REDACTED]" : normalizeFactoryRuleJsonValue(entry, depth + 1, seen);
87
+ }
88
+ return sanitized;
89
+ } finally {
90
+ seen.delete(value);
91
+ }
92
+ }
93
+ function sanitizeMetadata(value) {
94
+ if (value === void 0) return void 0;
95
+ const sanitized = normalizeFactoryRuleJsonValue(value);
96
+ if (!isPlainObject(sanitized)) throw new FactoryRuleValidationError("Rule metadata must be an object.");
97
+ if (JSON.stringify(sanitized).length > MAX_METADATA_JSON_LENGTH) throw new FactoryRuleValidationError("Rule metadata is too large.");
98
+ return sanitized;
99
+ }
100
+ function validateBoardRules(rules, label) {
101
+ if (!isPlainObject(rules)) throw new FactoryRuleValidationError(`${label} must be an object.`);
102
+ for (const [stage, sources] of Object.entries(rules)) {
103
+ enumValue(stage, FACTORY_RULE_STAGES, `${label} stage`);
104
+ if (!isPlainObject(sources)) throw new FactoryRuleValidationError(`${label}.${stage} must be an object.`);
105
+ for (const [source, leaf] of Object.entries(sources)) {
106
+ enumValue(source, FACTORY_RULE_SOURCES, `${label}.${stage} source`);
107
+ if (!isPlainObject(leaf)) throw new FactoryRuleValidationError(`${label}.${stage}.${source} must be an object.`);
108
+ assertExactKeys(leaf, ["onEnter", "onExit"], `${label}.${stage}.${source}`);
109
+ for (const handler of Object.values(leaf)) if (handler !== void 0 && typeof handler !== "function") throw new FactoryRuleValidationError(`${label}.${stage}.${source} handlers must be functions.`);
110
+ }
111
+ }
112
+ }
113
+ function assertFactoryRules(rules) {
114
+ if (!isPlainObject(rules)) throw new FactoryRuleValidationError("Factory rules must be an object.");
115
+ assertExactKeys(rules, [
116
+ "version",
117
+ "work",
118
+ "review",
119
+ "tools",
120
+ "github",
121
+ "linear"
122
+ ], "Factory rules");
123
+ boundedString(rules.version, "Factory rule version", MAX_VERSION_LENGTH);
124
+ validateBoardRules(rules.work, "Factory rules.work");
125
+ validateBoardRules(rules.review, "Factory rules.review");
126
+ if (!isPlainObject(rules.tools)) throw new FactoryRuleValidationError("Factory rules.tools must be an object.");
127
+ for (const [toolName, leaf] of Object.entries(rules.tools)) {
128
+ boundedString(toolName, "Factory tool name", 128, IDENTIFIER_RE);
129
+ if (!isPlainObject(leaf)) throw new FactoryRuleValidationError(`Factory rules.tools.${toolName} must be an object.`);
130
+ assertExactKeys(leaf, ["onResult"], `Factory rules.tools.${toolName}`);
131
+ if (leaf.onResult !== void 0 && typeof leaf.onResult !== "function") throw new FactoryRuleValidationError(`Factory rules.tools.${toolName}.onResult must be a function.`);
132
+ }
133
+ if (!isPlainObject(rules.github)) throw new FactoryRuleValidationError("Factory rules.github must be an object.");
134
+ for (const [event, leaf] of Object.entries(rules.github)) {
135
+ enumValue(event, FACTORY_GITHUB_EVENTS, "Factory GitHub event");
136
+ if (!isPlainObject(leaf)) throw new FactoryRuleValidationError(`Factory rules.github.${event} must be an object.`);
137
+ assertExactKeys(leaf, ["onEvent"], `Factory rules.github.${event}`);
138
+ if (leaf.onEvent !== void 0 && typeof leaf.onEvent !== "function") throw new FactoryRuleValidationError(`Factory rules.github.${event}.onEvent must be a function.`);
139
+ }
140
+ if (!isPlainObject(rules.linear)) throw new FactoryRuleValidationError("Factory rules.linear must be an object.");
141
+ for (const [event, leaf] of Object.entries(rules.linear)) {
142
+ enumValue(event, FACTORY_LINEAR_EVENTS, "Factory Linear event");
143
+ if (!isPlainObject(leaf)) throw new FactoryRuleValidationError(`Factory rules.linear.${event} must be an object.`);
144
+ assertExactKeys(leaf, ["onEvent"], `Factory rules.linear.${event}`);
145
+ if (leaf.onEvent !== void 0 && typeof leaf.onEvent !== "function") throw new FactoryRuleValidationError(`Factory rules.linear.${event}.onEvent must be a function.`);
146
+ }
147
+ }
148
+ function commonCommitFields(value) {
149
+ return { idempotencyKey: boundedString(value.idempotencyKey, "Factory decision idempotencyKey", MAX_IDEMPOTENCY_KEY_LENGTH) };
150
+ }
151
+ function validateFactoryRuleDecision(value, causalDepth = 0) {
152
+ if (causalDepth > 8) throw new FactoryRuleValidationError("Factory rule causal depth exceeded.");
153
+ if (!isPlainObject(value)) throw new FactoryRuleValidationError("Factory rule decision must be an object.");
154
+ const type = value.type;
155
+ if (typeof type !== "string") throw new FactoryRuleValidationError("Factory rule decision type is required.");
156
+ switch (type) {
157
+ case "reject":
158
+ assertExactKeys(value, [
159
+ "type",
160
+ "code",
161
+ "reason"
162
+ ], "Factory reject decision");
163
+ return {
164
+ type,
165
+ code: enumValue(value.code, REJECTION_CODES, "Factory rejection code"),
166
+ reason: boundedString(value.reason, "Factory rejection reason", MAX_REASON_LENGTH)
167
+ };
168
+ case "transition": {
169
+ assertExactKeys(value, [
170
+ "type",
171
+ "idempotencyKey",
172
+ "board",
173
+ "stage",
174
+ "message"
175
+ ], "Factory transition decision");
176
+ let message;
177
+ if (value.message !== void 0) {
178
+ if (!isPlainObject(value.message)) throw new FactoryRuleValidationError("Factory transition message must be an object.");
179
+ assertExactKeys(value.message, ["text", "role"], "Factory transition message");
180
+ const role = value.message.role === void 0 ? void 0 : boundedString(value.message.role, "Factory transition message role", MAX_ROLE_LENGTH, IDENTIFIER_RE);
181
+ message = {
182
+ text: boundedString(value.message.text, "Factory transition message text", MAX_MESSAGE_LENGTH),
183
+ ...role ? { role } : {}
184
+ };
185
+ }
186
+ return {
187
+ type,
188
+ ...commonCommitFields(value),
189
+ board: enumValue(value.board, FACTORY_RULE_BOARDS, "Factory transition board"),
190
+ stage: enumValue(value.stage, FACTORY_RULE_STAGES, "Factory transition stage"),
191
+ ...message ? { message } : {}
192
+ };
193
+ }
194
+ case "upsertLinkedWorkItem": {
195
+ assertExactKeys(value, [
196
+ "type",
197
+ "idempotencyKey",
198
+ "board",
199
+ "source",
200
+ "sourceKey",
201
+ "title",
202
+ "url",
203
+ "stage",
204
+ "metadata"
205
+ ], "Factory linked work item decision");
206
+ const url = value.url;
207
+ if (url !== null && (typeof url !== "string" || url.length > MAX_URL_LENGTH || !/^https?:\/\//.test(url))) throw new FactoryRuleValidationError("Factory linked work item URL is invalid.");
208
+ const metadata = sanitizeMetadata(value.metadata);
209
+ return {
210
+ type,
211
+ ...commonCommitFields(value),
212
+ board: enumValue(value.board, FACTORY_RULE_BOARDS, "Factory linked work item board"),
213
+ source: enumValue(value.source, WORK_ITEM_SOURCES, "Factory linked work item source"),
214
+ sourceKey: boundedString(value.sourceKey, "Factory linked work item sourceKey", MAX_SOURCE_KEY_LENGTH),
215
+ title: boundedString(value.title, "Factory linked work item title", MAX_TITLE_LENGTH),
216
+ url,
217
+ stage: enumValue(value.stage, FACTORY_RULE_STAGES, "Factory linked work item stage"),
218
+ ...metadata ? { metadata } : {}
219
+ };
220
+ }
221
+ case "invokeSkill": {
222
+ assertExactKeys(value, [
223
+ "type",
224
+ "idempotencyKey",
225
+ "role",
226
+ "skillName",
227
+ "arguments",
228
+ "precedingMessage"
229
+ ], "Factory invoke skill decision");
230
+ const args = optionalBoundedString(value.arguments, "Factory skill arguments", MAX_ARGUMENTS_LENGTH);
231
+ const precedingMessage = optionalBoundedString(value.precedingMessage, "Factory skill preceding message", MAX_MESSAGE_LENGTH);
232
+ return {
233
+ type,
234
+ ...commonCommitFields(value),
235
+ role: boundedString(value.role, "Factory skill role", MAX_ROLE_LENGTH, IDENTIFIER_RE),
236
+ skillName: boundedString(value.skillName, "Factory skill name", MAX_SKILL_NAME_LENGTH, SKILL_NAME_RE),
237
+ ...args ? { arguments: args } : {},
238
+ ...precedingMessage ? { precedingMessage } : {}
239
+ };
240
+ }
241
+ case "sendMessage": {
242
+ assertExactKeys(value, [
243
+ "type",
244
+ "idempotencyKey",
245
+ "role",
246
+ "message",
247
+ "priority",
248
+ "idleBehavior",
249
+ "prepareBinding"
250
+ ], "Factory send message decision");
251
+ const priority = value.priority === void 0 ? void 0 : enumValue(value.priority, [
252
+ "medium",
253
+ "high",
254
+ "urgent"
255
+ ], "Factory message priority");
256
+ const idleBehavior = value.idleBehavior === void 0 ? void 0 : enumValue(value.idleBehavior, ["persist", "wake"], "Factory message idle behavior");
257
+ if (value.prepareBinding !== void 0 && typeof value.prepareBinding !== "boolean") throw new FactoryRuleValidationError("Factory message prepareBinding must be a boolean.");
258
+ return {
259
+ type,
260
+ ...commonCommitFields(value),
261
+ role: boundedString(value.role, "Factory message role", MAX_ROLE_LENGTH, IDENTIFIER_RE),
262
+ message: boundedString(value.message, "Factory message", MAX_MESSAGE_LENGTH),
263
+ ...priority ? { priority } : {},
264
+ ...idleBehavior ? { idleBehavior } : {},
265
+ ...value.prepareBinding === true ? { prepareBinding: true } : {}
266
+ };
267
+ }
268
+ case "notify": {
269
+ assertExactKeys(value, [
270
+ "type",
271
+ "idempotencyKey",
272
+ "title",
273
+ "body",
274
+ "level"
275
+ ], "Factory notify decision");
276
+ const body = optionalBoundedString(value.body, "Factory notification body", MAX_MESSAGE_LENGTH);
277
+ const level = value.level === void 0 ? void 0 : enumValue(value.level, [
278
+ "info",
279
+ "warning",
280
+ "error"
281
+ ], "Factory notification level");
282
+ return {
283
+ type,
284
+ ...commonCommitFields(value),
285
+ title: boundedString(value.title, "Factory notification title", MAX_TITLE_LENGTH),
286
+ ...body ? { body } : {},
287
+ ...level ? { level } : {}
288
+ };
289
+ }
290
+ default: throw new FactoryRuleValidationError("Factory rule decision type is unsupported.");
291
+ }
292
+ }
293
+ function validateFactoryRuleDecisions(values, causalDepth = 0) {
294
+ if (values.length > MAX_JSON_COLLECTION_SIZE) throw new FactoryRuleValidationError("Factory rule produced too many decisions.");
295
+ const decisions = [];
296
+ for (const value of values) {
297
+ const decision = validateFactoryRuleDecision(value, causalDepth);
298
+ if (decision.type === "reject") throw new FactoryRuleValidationError("A rejection cannot be persisted with commit decisions.");
299
+ decisions.push(decision);
300
+ }
301
+ const keys = decisions.map((decision) => decision.idempotencyKey);
302
+ if (new Set(keys).size !== keys.length) throw new FactoryRuleValidationError("Factory decisions require unique idempotency keys.");
303
+ return decisions;
304
+ }
305
+ //#endregion
306
+ export { FactoryRuleValidationError, MAX_FACTORY_RULE_CAUSAL_DEPTH, assertFactoryRules, normalizeFactoryRuleJsonValue, validateFactoryRuleDecision, validateFactoryRuleDecisions };
307
+
308
+ //# sourceMappingURL=validation.js.map