@mastra/factory 0.13.0-alpha.6 → 0.13.0-alpha.7

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 (78) hide show
  1. package/README.md +35 -0
  2. package/dist/boards/index.d.ts +4 -3
  3. package/dist/boards/index.d.ts.map +1 -1
  4. package/dist/boards/index.js +2 -1
  5. package/dist/boards/index.js.map +1 -1
  6. package/dist/boards/registry.d.ts +16 -0
  7. package/dist/boards/registry.d.ts.map +1 -0
  8. package/dist/boards/registry.js +27 -0
  9. package/dist/boards/registry.js.map +1 -0
  10. package/dist/boards/review.js +1 -1
  11. package/dist/boards/work.js +2 -2
  12. package/dist/factory.d.ts +6 -1
  13. package/dist/factory.d.ts.map +1 -1
  14. package/dist/factory.js +10 -0
  15. package/dist/factory.js.map +1 -1
  16. package/dist/index.d.ts +2 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +3 -2
  19. package/dist/integrations/github/default-rules.d.ts +194 -0
  20. package/dist/integrations/github/default-rules.d.ts.map +1 -0
  21. package/dist/integrations/github/default-rules.js +230 -0
  22. package/dist/integrations/github/default-rules.js.map +1 -0
  23. package/dist/integrations/github/integration.d.ts +4 -0
  24. package/dist/integrations/github/integration.d.ts.map +1 -1
  25. package/dist/integrations/github/integration.js +6 -0
  26. package/dist/integrations/github/integration.js.map +1 -1
  27. package/dist/integrations/github/rules.d.ts +3 -1
  28. package/dist/integrations/github/rules.d.ts.map +1 -1
  29. package/dist/integrations/github/rules.js +1 -2
  30. package/dist/integrations/github/rules.js.map +1 -1
  31. package/dist/integrations/linear/rules.js +1 -1
  32. package/dist/integrations/platform/github/integration.d.ts +4 -0
  33. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  34. package/dist/integrations/platform/github/integration.js +6 -0
  35. package/dist/integrations/platform/github/integration.js.map +1 -1
  36. package/dist/integrations/slack/slack.d.ts +3 -1
  37. package/dist/integrations/slack/slack.d.ts.map +1 -1
  38. package/dist/integrations/slack/slack.js +19 -1
  39. package/dist/integrations/slack/slack.js.map +1 -1
  40. package/dist/routes/surface.d.ts +3 -0
  41. package/dist/routes/surface.d.ts.map +1 -1
  42. package/dist/routes/surface.js +2 -1
  43. package/dist/routes/surface.js.map +1 -1
  44. package/dist/routes/work-items.d.ts +3 -0
  45. package/dist/routes/work-items.d.ts.map +1 -1
  46. package/dist/routes/work-items.js +48 -15
  47. package/dist/routes/work-items.js.map +1 -1
  48. package/dist/rules/defaults.d.ts.map +1 -1
  49. package/dist/rules/defaults.js +1 -229
  50. package/dist/rules/defaults.js.map +1 -1
  51. package/dist/rules/index.d.ts +2 -2
  52. package/dist/rules/index.d.ts.map +1 -1
  53. package/dist/rules/index.js +2 -2
  54. package/dist/rules/processor.d.ts +2 -0
  55. package/dist/rules/processor.d.ts.map +1 -1
  56. package/dist/rules/processor.js +9 -7
  57. package/dist/rules/processor.js.map +1 -1
  58. package/dist/rules/resolve.d.ts +4 -4
  59. package/dist/rules/resolve.d.ts.map +1 -1
  60. package/dist/rules/resolve.js +4 -6
  61. package/dist/rules/resolve.js.map +1 -1
  62. package/dist/rules/transition-service.d.ts +2 -0
  63. package/dist/rules/transition-service.d.ts.map +1 -1
  64. package/dist/rules/transition-service.js +16 -10
  65. package/dist/rules/transition-service.js.map +1 -1
  66. package/dist/rules/types.d.ts +3 -8
  67. package/dist/rules/types.d.ts.map +1 -1
  68. package/dist/rules/types.js +1 -1
  69. package/dist/rules/types.js.map +1 -1
  70. package/dist/rules/validation.d.ts.map +1 -1
  71. package/dist/rules/validation.js +1 -9
  72. package/dist/rules/validation.js.map +1 -1
  73. package/dist/storage/domains/work-items/base.d.ts +11 -1
  74. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  75. package/dist/storage/domains/work-items/base.js +22 -2
  76. package/dist/storage/domains/work-items/base.js.map +1 -1
  77. package/factory-skills/configure-factory-rules/SKILL.md +12 -4
  78. package/package.json +6 -6
package/README.md CHANGED
@@ -29,6 +29,41 @@ A host application calls `MastraFactory.prepare()`, constructs its `Mastra` inst
29
29
 
30
30
  `prepare()` initializes the Factory-owned resources needed before Mastra is constructed. `finalize()` connects those resources to the completed host, including Factory routes, integrations, storage-backed behavior, and agent-controller features. Consumers should keep frontend concerns in `factory-ui` and host-specific environment or deployment wiring in `web` rather than adding them to this package.
31
31
 
32
+ ### GitHub event rules
33
+
34
+ Both `GithubIntegration` and `PlatformGithubIntegration` own their GitHub event handlers. Existing installations retain the defaults without additional configuration.
35
+
36
+ ```typescript
37
+ import { PlatformGithubIntegration } from '@mastra/factory/integrations/platform/github/integration';
38
+
39
+ const github = new PlatformGithubIntegration({
40
+ rules: {
41
+ issueOpened: context => ({
42
+ type: 'reject',
43
+ code: 'manual_intake',
44
+ reason: 'This deployment manages issue intake manually.',
45
+ }),
46
+ issueCommentCreated: null,
47
+ },
48
+ });
49
+ ```
50
+
51
+ Pass the integration in `MastraFactory`'s `integrations` array. The direct `GithubIntegration` accepts the same `rules` option alongside its GitHub App credentials. A function replaces one default handler without composing with it. `null` disables that event's handler, not authentication, webhook ingestion, or reconciliation bookkeeping. Omitted events and `undefined` retain their defaults. Each instance copies and freezes its resolved handler map; unknown event names and invalid handler values are rejected during construction.
52
+
53
+ **Migration:** Move each global `rules.github[event].onEvent` value to the integration constructor's `rules[event]` option:
54
+
55
+ ```typescript
56
+ // Before: global Factory rule overrides
57
+ const overrides = { github: { issueCommentCreated: { onEvent: null } } };
58
+
59
+ // After: GitHub integration constructor options
60
+ const github = new PlatformGithubIntegration({ rules: { issueCommentCreated: null } });
61
+ ```
62
+
63
+ Work, Review, tool, and Linear configuration remain unchanged. The global rule version remains shared audit metadata, including for GitHub evaluations; it is not a hash of custom handler code and does not change delivery replay semantics. Update the deployment-owned version when changing handler behavior.
64
+
65
+ Handlers receive the existing typed GitHub context and return one decision or `undefined`. External titles, bodies, and comments remain untrusted data after webhook authentication. Custom handlers must preserve any required actor-permission checks explicitly.
66
+
32
67
  ### GitHub review commands
33
68
 
34
69
  A repository maintainer with write or admin access can start a Factory review from a pull-request comment by posting the exact first-line command:
@@ -1,10 +1,11 @@
1
- import type { FactoryRuleBoard } from '../rules/types.js';
2
1
  export { BoardDefinitionError, defineBoard } from './define-board.js';
3
2
  export type { BoardDefinition, BoardPhaseDefinition, BoardTransition } from './define-board.js';
3
+ export { createBoardRegistry, defaultBoards } from './registry.js';
4
+ export type { BoardRegistry, InstalledBoard } from './registry.js';
4
5
  export { reviewBoard } from './review.js';
5
6
  export type { ReviewBoardPhase } from './review.js';
6
7
  export { workBoard } from './work.js';
7
8
  export type { WorkBoardPhase } from './work.js';
8
- export declare function builtInBoard(board: FactoryRuleBoard): import("./define-board.js").BoardDefinition<"review", "intake" | "review" | "done" | "canceled"> | import("./define-board.js").BoardDefinition<"work", "intake" | "triage" | "planning" | "execute" | "review" | "done" | "canceled">;
9
- export declare function allowsBuiltInBoardTransition(board: FactoryRuleBoard, from: string, to: string): boolean;
9
+ export declare function builtInBoard(board: 'work' | 'review'): import("./define-board.js").BoardDefinition<"review", "intake" | "review" | "done" | "canceled"> | import("./define-board.js").BoardDefinition<"work", "intake" | "triage" | "planning" | "execute" | "review" | "done" | "canceled">;
10
+ export declare function allowsBuiltInBoardTransition(board: 'work' | 'review', from: string, to: string): boolean;
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/boards/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAI1D,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACtE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIhD,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,yOAEnD;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAKvG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/boards/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACtE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAInE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIhD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,yOAEpD;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAKxG"}
@@ -1,6 +1,7 @@
1
1
  import { BoardDefinitionError, defineBoard } from "./define-board.js";
2
2
  import { isReviewBoardPhase, reviewBoard } from "./review.js";
3
3
  import { isWorkBoardPhase, workBoard } from "./work.js";
4
+ import { createBoardRegistry, defaultBoards } from "./registry.js";
4
5
  //#region src/boards/index.ts
5
6
  const builtInBoards = {
6
7
  work: workBoard,
@@ -14,6 +15,6 @@ function allowsBuiltInBoardTransition(board, from, to) {
14
15
  return isReviewBoardPhase(from) && isReviewBoardPhase(to) && reviewBoard.allowsTransition(from, to);
15
16
  }
16
17
  //#endregion
17
- export { BoardDefinitionError, allowsBuiltInBoardTransition, builtInBoard, defineBoard, reviewBoard, workBoard };
18
+ export { BoardDefinitionError, allowsBuiltInBoardTransition, builtInBoard, createBoardRegistry, defaultBoards, defineBoard, reviewBoard, workBoard };
18
19
 
19
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/boards/index.ts"],"sourcesContent":["import type { FactoryRuleBoard } from '../rules/types.js';\nimport { isReviewBoardPhase, reviewBoard } from './review.js';\nimport { isWorkBoardPhase, workBoard } from './work.js';\n\nexport { BoardDefinitionError, defineBoard } from './define-board.js';\nexport type { BoardDefinition, BoardPhaseDefinition, BoardTransition } from './define-board.js';\nexport { reviewBoard } from './review.js';\nexport type { ReviewBoardPhase } from './review.js';\nexport { workBoard } from './work.js';\nexport type { WorkBoardPhase } from './work.js';\n\nconst builtInBoards = { work: workBoard, review: reviewBoard } as const;\n\nexport function builtInBoard(board: FactoryRuleBoard) {\n return builtInBoards[board];\n}\n\nexport function allowsBuiltInBoardTransition(board: FactoryRuleBoard, from: string, to: string): boolean {\n if (board === 'work') {\n return isWorkBoardPhase(from) && isWorkBoardPhase(to) && workBoard.allowsTransition(from, to);\n }\n return isReviewBoardPhase(from) && isReviewBoardPhase(to) && reviewBoard.allowsTransition(from, to);\n}\n"],"mappings":";;;;AAWA,MAAM,gBAAgB;CAAE,MAAM;CAAW,QAAQ;AAAY;AAE7D,SAAgB,aAAa,OAAyB;CACpD,OAAO,cAAc;AACvB;AAEA,SAAgB,6BAA6B,OAAyB,MAAc,IAAqB;CACvG,IAAI,UAAU,QACZ,OAAO,iBAAiB,IAAI,KAAK,iBAAiB,EAAE,KAAK,UAAU,iBAAiB,MAAM,EAAE;CAE9F,OAAO,mBAAmB,IAAI,KAAK,mBAAmB,EAAE,KAAK,YAAY,iBAAiB,MAAM,EAAE;AACpG"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/boards/index.ts"],"sourcesContent":["export { BoardDefinitionError, defineBoard } from './define-board.js';\nexport type { BoardDefinition, BoardPhaseDefinition, BoardTransition } from './define-board.js';\nexport { createBoardRegistry, defaultBoards } from './registry.js';\nexport type { BoardRegistry, InstalledBoard } from './registry.js';\nimport { isReviewBoardPhase, reviewBoard } from './review.js';\nimport { isWorkBoardPhase, workBoard } from './work.js';\n\nexport { reviewBoard } from './review.js';\nexport type { ReviewBoardPhase } from './review.js';\nexport { workBoard } from './work.js';\nexport type { WorkBoardPhase } from './work.js';\n\nconst builtInBoards = { work: workBoard, review: reviewBoard } as const;\n\nexport function builtInBoard(board: 'work' | 'review') {\n return builtInBoards[board];\n}\n\nexport function allowsBuiltInBoardTransition(board: 'work' | 'review', from: string, to: string): boolean {\n if (board === 'work') {\n return isWorkBoardPhase(from) && isWorkBoardPhase(to) && workBoard.allowsTransition(from, to);\n }\n return isReviewBoardPhase(from) && isReviewBoardPhase(to) && reviewBoard.allowsTransition(from, to);\n}\n"],"mappings":";;;;;AAYA,MAAM,gBAAgB;CAAE,MAAM;CAAW,QAAQ;AAAY;AAE7D,SAAgB,aAAa,OAA0B;CACrD,OAAO,cAAc;AACvB;AAEA,SAAgB,6BAA6B,OAA0B,MAAc,IAAqB;CACxG,IAAI,UAAU,QACZ,OAAO,iBAAiB,IAAI,KAAK,iBAAiB,EAAE,KAAK,UAAU,iBAAiB,MAAM,EAAE;CAE9F,OAAO,mBAAmB,IAAI,KAAK,mBAAmB,EAAE,KAAK,YAAY,iBAAiB,MAAM,EAAE;AACpG"}
@@ -0,0 +1,16 @@
1
+ import type { BoardDefinition } from './define-board.js';
2
+ export type InstalledBoard = BoardDefinition<string, string>;
3
+ export interface BoardRegistry extends Iterable<[string, InstalledBoard]> {
4
+ readonly size: number;
5
+ get(id: string): InstalledBoard | undefined;
6
+ has(id: string): boolean;
7
+ keys(): MapIterator<string>;
8
+ values(): MapIterator<InstalledBoard>;
9
+ entries(): MapIterator<[string, InstalledBoard]>;
10
+ }
11
+ export declare const defaultBoards: readonly InstalledBoard[];
12
+ export declare function createBoardRegistry(options?: {
13
+ boards?: readonly InstalledBoard[];
14
+ includeDefaultBoards?: boolean;
15
+ }): BoardRegistry;
16
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/boards/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC7D,MAAM,WAAW,aAAc,SAAQ,QAAQ,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAC5C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,IAAI,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,IAAI,WAAW,CAAC,cAAc,CAAC,CAAC;IACtC,OAAO,IAAI,WAAW,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;CAClD;AAED,eAAO,MAAM,aAAa,EAA8C,SAAS,cAAc,EAAE,CAAC;AAGlG,wBAAgB,mBAAmB,CACjC,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACnC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC3B,GACL,aAAa,CA0Bf"}
@@ -0,0 +1,27 @@
1
+ import { reviewBoard } from "./review.js";
2
+ import { workBoard } from "./work.js";
3
+ //#region src/boards/registry.ts
4
+ const defaultBoards = Object.freeze([workBoard, reviewBoard]);
5
+ const reservedBoardIds = new Set(defaultBoards.map((board) => board.id));
6
+ function createBoardRegistry(options = {}) {
7
+ const installed = options.includeDefaultBoards === false ? [] : defaultBoards;
8
+ const registry = /* @__PURE__ */ new Map();
9
+ for (const board of options.boards ?? []) if (reservedBoardIds.has(board.id)) throw new Error(`MastraFactory: board id '${board.id}' is reserved for a built-in board.`);
10
+ for (const board of [...installed, ...options.boards ?? []]) {
11
+ if (registry.has(board.id)) throw new Error(`MastraFactory: duplicate board id '${board.id}' in 'boards'.`);
12
+ registry.set(board.id, board);
13
+ }
14
+ return Object.freeze({
15
+ size: registry.size,
16
+ get: registry.get.bind(registry),
17
+ has: registry.has.bind(registry),
18
+ keys: registry.keys.bind(registry),
19
+ values: registry.values.bind(registry),
20
+ entries: registry.entries.bind(registry),
21
+ [Symbol.iterator]: registry[Symbol.iterator].bind(registry)
22
+ });
23
+ }
24
+ //#endregion
25
+ export { createBoardRegistry, defaultBoards };
26
+
27
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../src/boards/registry.ts"],"sourcesContent":["import type { BoardDefinition } from './define-board.js';\nimport { reviewBoard } from './review.js';\nimport { workBoard } from './work.js';\n\nexport type InstalledBoard = BoardDefinition<string, string>;\nexport interface BoardRegistry extends Iterable<[string, InstalledBoard]> {\n readonly size: number;\n get(id: string): InstalledBoard | undefined;\n has(id: string): boolean;\n keys(): MapIterator<string>;\n values(): MapIterator<InstalledBoard>;\n entries(): MapIterator<[string, InstalledBoard]>;\n}\n\nexport const defaultBoards = Object.freeze([workBoard, reviewBoard]) as readonly InstalledBoard[];\nconst reservedBoardIds = new Set(defaultBoards.map(board => board.id));\n\nexport function createBoardRegistry(\n options: {\n boards?: readonly InstalledBoard[];\n includeDefaultBoards?: boolean;\n } = {},\n): BoardRegistry {\n const installed = options.includeDefaultBoards === false ? [] : defaultBoards;\n const registry = new Map<string, InstalledBoard>();\n\n for (const board of options.boards ?? []) {\n if (reservedBoardIds.has(board.id)) {\n throw new Error(`MastraFactory: board id '${board.id}' is reserved for a built-in board.`);\n }\n }\n\n for (const board of [...installed, ...(options.boards ?? [])]) {\n if (registry.has(board.id)) {\n throw new Error(`MastraFactory: duplicate board id '${board.id}' in 'boards'.`);\n }\n registry.set(board.id, board);\n }\n\n return Object.freeze({\n size: registry.size,\n get: registry.get.bind(registry),\n has: registry.has.bind(registry),\n keys: registry.keys.bind(registry),\n values: registry.values.bind(registry),\n entries: registry.entries.bind(registry),\n [Symbol.iterator]: registry[Symbol.iterator].bind(registry),\n });\n}\n"],"mappings":";;;AAcA,MAAa,gBAAgB,OAAO,OAAO,CAAC,WAAW,WAAW,CAAC;AACnE,MAAM,mBAAmB,IAAI,IAAI,cAAc,KAAI,UAAS,MAAM,EAAE,CAAC;AAErE,SAAgB,oBACd,UAGI,CAAC,GACU;CACf,MAAM,YAAY,QAAQ,yBAAyB,QAAQ,CAAC,IAAI;CAChE,MAAM,2BAAW,IAAI,IAA4B;CAEjD,KAAK,MAAM,SAAS,QAAQ,UAAU,CAAC,GACrC,IAAI,iBAAiB,IAAI,MAAM,EAAE,GAC/B,MAAM,IAAI,MAAM,4BAA4B,MAAM,GAAG,oCAAoC;CAI7F,KAAK,MAAM,SAAS,CAAC,GAAG,WAAW,GAAI,QAAQ,UAAU,CAAC,CAAE,GAAG;EAC7D,IAAI,SAAS,IAAI,MAAM,EAAE,GACvB,MAAM,IAAI,MAAM,sCAAsC,MAAM,GAAG,eAAe;EAEhF,SAAS,IAAI,MAAM,IAAI,KAAK;CAC9B;CAEA,OAAO,OAAO,OAAO;EACnB,MAAM,SAAS;EACf,KAAK,SAAS,IAAI,KAAK,QAAQ;EAC/B,KAAK,SAAS,IAAI,KAAK,QAAQ;EAC/B,MAAM,SAAS,KAAK,KAAK,QAAQ;EACjC,QAAQ,SAAS,OAAO,KAAK,QAAQ;EACrC,SAAS,SAAS,QAAQ,KAAK,QAAQ;GACtC,OAAO,WAAW,SAAS,OAAO,SAAS,CAAC,KAAK,QAAQ;CAC5D,CAAC;AACH"}
@@ -1,5 +1,5 @@
1
- import { workItemNumber } from "../work-item-branch.js";
2
1
  import { defineBoard } from "./define-board.js";
2
+ import { workItemNumber } from "../work-item-branch.js";
3
3
  //#region src/boards/review.ts
4
4
  function sourceRef(item) {
5
5
  const link = item.url ? ` (${item.url})` : "";
@@ -1,6 +1,6 @@
1
- import { needsApproval } from "../rules/types.js";
2
- import { workItemNumber } from "../work-item-branch.js";
3
1
  import { defineBoard } from "./define-board.js";
2
+ import { workItemNumber } from "../work-item-branch.js";
3
+ import { needsApproval } from "../rules/types.js";
4
4
  //#region src/boards/work.ts
5
5
  function linearIdentifier(item) {
6
6
  const identifier = item.metadata?.identifier;
package/dist/factory.d.ts CHANGED
@@ -22,6 +22,7 @@ import type { Mastra } from '@mastra/core/mastra';
22
22
  import type { IMastraAuthProvider } from '@mastra/core/server';
23
23
  import type { FactoryStorage } from '@mastra/core/storage';
24
24
  import type { MastraVector } from '@mastra/core/vector';
25
+ import type { InstalledBoard } from './boards/index.js';
25
26
  import type { FactoryIntegration } from './integrations/base.js';
26
27
  import type { FactoryRules } from './rules/types.js';
27
28
  import type { MastraFactorySandboxConfig } from './sandbox/session-sandbox.js';
@@ -114,12 +115,16 @@ export interface MastraFactoryConfig {
114
115
  */
115
116
  integrations?: FactoryIntegration[];
116
117
  /**
117
- * Authoritative Factory board, tool-result, and GitHub-event rules. Construct
118
+ * Authoritative Factory board, tool-result, and Linear-event rules. Construct
118
119
  * with `defaultFactoryRules({ version, overrides })` so deployment policy has
119
120
  * an explicit version and exact handler leaves replace rather than compose.
120
121
  * Omitted → conservative built-in rules for the current deployment.
121
122
  */
122
123
  rules?: FactoryRules;
124
+ /** Board definitions installed for this Factory instance. */
125
+ boards?: readonly InstalledBoard[];
126
+ /** Whether the built-in Work and Review boards are installed. Default: true. */
127
+ includeDefaultBoards?: boolean;
123
128
  /**
124
129
  * Platform-specific overrides. `githubAppSlug` identifies Factory's own
125
130
  * GitHub App writes so their webhook deliveries do not retrigger triage.
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAWxD,OAAO,KAAK,EAAE,kBAAkB,EAAgD,MAAM,wBAAwB,CAAC;AA0B/G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAE/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAqCtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAI1D,8EAA8E;AAC9E,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC,qBAAqB,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClC;;;;;;;OAOG;IACH,OAAO,EAAE,cAAc,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC;;;;OAIG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,mDAAmD;IACnD,UAAU,CAAC,EAAE,6BAA6B,CAAC;IAC3C;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;IAC3C;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IAErB;;;OAGG;IACH,QAAQ,CAAC,EAAE;QACT,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,YAAY,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC/E,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAyED,qBAAa,aAAa;;gBAOZ,MAAM,EAAE,mBAAmB;IAWvC;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IAszBpC;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAY/B,iFAAiF;IAC3E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAWxD,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEvE,OAAO,KAAK,EAAE,kBAAkB,EAAgD,MAAM,wBAAwB,CAAC;AA0B/G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAE/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAqCtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAI1D,8EAA8E;AAC9E,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC,qBAAqB,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClC;;;;;;;OAOG;IACH,OAAO,EAAE,cAAc,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC;;;;OAIG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,mDAAmD;IACnD,UAAU,CAAC,EAAE,6BAA6B,CAAC;IAC3C;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;IAC3C;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACnC,gFAAgF;IAChF,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,EAAE;QACT,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,YAAY,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC/E,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAyED,qBAAa,aAAa;;gBAQZ,MAAM,EAAE,mBAAmB;IAevC;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IAyzBpC;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAY/B,iFAAiF;IAC3E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC"}
package/dist/factory.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { timedPhase } from "./timing.js";
2
2
  import { buildAuthRoutes, createFactoryAuthGate, createFactoryRouteAuth, getFactoryAuthOrgId, getFactoryAuthUserFromContext, getFactoryAuthUserId } from "./auth.js";
3
+ import { createBoardRegistry } from "./boards/registry.js";
4
+ import "./boards/index.js";
3
5
  import { touchFeed } from "./feed-events.js";
4
6
  import { reconcileGithubAcceptanceLabels } from "./integrations/github/acceptance-labels.js";
5
7
  import { recordFactoryPullRequestProvenance, resolveFactoryPullRequestParentWorkItemId } from "./integrations/github/provenance.js";
@@ -133,12 +135,17 @@ function parentDomainFromPublicUrl(publicUrl) {
133
135
  }
134
136
  var MastraFactory = class {
135
137
  #config;
138
+ #boards;
136
139
  #prepared;
137
140
  #dispatcher;
138
141
  #factoryProcessor;
139
142
  #preparing = false;
140
143
  constructor(config) {
141
144
  if (!config?.storage) throw new Error("MastraFactory: 'storage' is required. Pass a FactoryStorage backend — e.g. new PgFactoryStorage({ connectionString }) from '@mastra/pg' for deployments, or new LibSQLFactoryStorage({ url }) from '@mastra/libsql' for local dev.");
145
+ this.#boards = createBoardRegistry({
146
+ boards: config.boards,
147
+ includeDefaultBoards: config.includeDefaultBoards
148
+ });
142
149
  this.#config = config;
143
150
  }
144
151
  /**
@@ -286,6 +293,7 @@ var MastraFactory = class {
286
293
  }) : retireTerminalSessions;
287
294
  const transitionService = workItemsReady ? new FactoryTransitionService({
288
295
  rules,
296
+ boards: this.#boards,
289
297
  storage: workItemsStorage,
290
298
  ...onTerminalStage ? { onTerminalStage } : {},
291
299
  ...githubIntegration ? { onAccepted: (args) => reconcileGithubAcceptanceLabels(githubIntegration, sourceControlStorage.forIntegration(githubIntegration.id), args) } : {}
@@ -324,6 +332,7 @@ var MastraFactory = class {
324
332
  const factoryProcessor = workItemsReady ? new FactoryPhaseStateProcessor({
325
333
  rules,
326
334
  storage: workItemsStorage,
335
+ boardRegistry: this.#boards,
327
336
  ...transitionService ? { transitionService } : {},
328
337
  ...githubIntegration ? { recordPullRequestProvenance: (input) => recordFactoryPullRequestProvenance(githubIntegration, sourceControlStorage.forIntegration("github"), integrationStorage.forIntegration("github"), workItemsStorage, input) } : {},
329
338
  messageReader: { listMessages: async (input) => {
@@ -482,6 +491,7 @@ var MastraFactory = class {
482
491
  factoryReady,
483
492
  knowledgeEnabled,
484
493
  rules,
494
+ boardRegistry: this.#boards,
485
495
  factoryTransitionService: transitionService,
486
496
  onFactoryRuntime: ({ transitionService: runtimeTransitionService, prepareBinding }) => {
487
497
  this.#dispatcher ??= new FactoryDecisionDispatcher({