@renseiai/agentfactory 0.8.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 (246) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -0
  3. package/dist/src/config/index.d.ts +3 -0
  4. package/dist/src/config/index.d.ts.map +1 -0
  5. package/dist/src/config/index.js +1 -0
  6. package/dist/src/config/repository-config.d.ts +44 -0
  7. package/dist/src/config/repository-config.d.ts.map +1 -0
  8. package/dist/src/config/repository-config.js +88 -0
  9. package/dist/src/config/repository-config.test.d.ts +2 -0
  10. package/dist/src/config/repository-config.test.d.ts.map +1 -0
  11. package/dist/src/config/repository-config.test.js +249 -0
  12. package/dist/src/deployment/deployment-checker.d.ts +110 -0
  13. package/dist/src/deployment/deployment-checker.d.ts.map +1 -0
  14. package/dist/src/deployment/deployment-checker.js +242 -0
  15. package/dist/src/deployment/index.d.ts +3 -0
  16. package/dist/src/deployment/index.d.ts.map +1 -0
  17. package/dist/src/deployment/index.js +2 -0
  18. package/dist/src/frontend/index.d.ts +2 -0
  19. package/dist/src/frontend/index.d.ts.map +1 -0
  20. package/dist/src/frontend/index.js +1 -0
  21. package/dist/src/frontend/types.d.ts +106 -0
  22. package/dist/src/frontend/types.d.ts.map +1 -0
  23. package/dist/src/frontend/types.js +11 -0
  24. package/dist/src/governor/decision-engine.d.ts +52 -0
  25. package/dist/src/governor/decision-engine.d.ts.map +1 -0
  26. package/dist/src/governor/decision-engine.js +220 -0
  27. package/dist/src/governor/decision-engine.test.d.ts +2 -0
  28. package/dist/src/governor/decision-engine.test.d.ts.map +1 -0
  29. package/dist/src/governor/decision-engine.test.js +629 -0
  30. package/dist/src/governor/event-bus.d.ts +43 -0
  31. package/dist/src/governor/event-bus.d.ts.map +1 -0
  32. package/dist/src/governor/event-bus.js +8 -0
  33. package/dist/src/governor/event-deduplicator.d.ts +43 -0
  34. package/dist/src/governor/event-deduplicator.d.ts.map +1 -0
  35. package/dist/src/governor/event-deduplicator.js +53 -0
  36. package/dist/src/governor/event-driven-governor.d.ts +131 -0
  37. package/dist/src/governor/event-driven-governor.d.ts.map +1 -0
  38. package/dist/src/governor/event-driven-governor.js +379 -0
  39. package/dist/src/governor/event-driven-governor.test.d.ts +2 -0
  40. package/dist/src/governor/event-driven-governor.test.d.ts.map +1 -0
  41. package/dist/src/governor/event-driven-governor.test.js +673 -0
  42. package/dist/src/governor/event-types.d.ts +78 -0
  43. package/dist/src/governor/event-types.d.ts.map +1 -0
  44. package/dist/src/governor/event-types.js +32 -0
  45. package/dist/src/governor/governor-types.d.ts +82 -0
  46. package/dist/src/governor/governor-types.d.ts.map +1 -0
  47. package/dist/src/governor/governor-types.js +21 -0
  48. package/dist/src/governor/governor.d.ts +100 -0
  49. package/dist/src/governor/governor.d.ts.map +1 -0
  50. package/dist/src/governor/governor.js +262 -0
  51. package/dist/src/governor/governor.test.d.ts +2 -0
  52. package/dist/src/governor/governor.test.d.ts.map +1 -0
  53. package/dist/src/governor/governor.test.js +514 -0
  54. package/dist/src/governor/human-touchpoints.d.ts +131 -0
  55. package/dist/src/governor/human-touchpoints.d.ts.map +1 -0
  56. package/dist/src/governor/human-touchpoints.js +251 -0
  57. package/dist/src/governor/human-touchpoints.test.d.ts +2 -0
  58. package/dist/src/governor/human-touchpoints.test.d.ts.map +1 -0
  59. package/dist/src/governor/human-touchpoints.test.js +366 -0
  60. package/dist/src/governor/in-memory-event-bus.d.ts +29 -0
  61. package/dist/src/governor/in-memory-event-bus.d.ts.map +1 -0
  62. package/dist/src/governor/in-memory-event-bus.js +79 -0
  63. package/dist/src/governor/index.d.ts +14 -0
  64. package/dist/src/governor/index.d.ts.map +1 -0
  65. package/dist/src/governor/index.js +13 -0
  66. package/dist/src/governor/override-parser.d.ts +60 -0
  67. package/dist/src/governor/override-parser.d.ts.map +1 -0
  68. package/dist/src/governor/override-parser.js +98 -0
  69. package/dist/src/governor/override-parser.test.d.ts +2 -0
  70. package/dist/src/governor/override-parser.test.d.ts.map +1 -0
  71. package/dist/src/governor/override-parser.test.js +312 -0
  72. package/dist/src/governor/platform-adapter.d.ts +69 -0
  73. package/dist/src/governor/platform-adapter.d.ts.map +1 -0
  74. package/dist/src/governor/platform-adapter.js +11 -0
  75. package/dist/src/governor/processing-state.d.ts +66 -0
  76. package/dist/src/governor/processing-state.d.ts.map +1 -0
  77. package/dist/src/governor/processing-state.js +43 -0
  78. package/dist/src/governor/processing-state.test.d.ts +2 -0
  79. package/dist/src/governor/processing-state.test.d.ts.map +1 -0
  80. package/dist/src/governor/processing-state.test.js +96 -0
  81. package/dist/src/governor/top-of-funnel.d.ts +118 -0
  82. package/dist/src/governor/top-of-funnel.d.ts.map +1 -0
  83. package/dist/src/governor/top-of-funnel.js +168 -0
  84. package/dist/src/governor/top-of-funnel.test.d.ts +2 -0
  85. package/dist/src/governor/top-of-funnel.test.d.ts.map +1 -0
  86. package/dist/src/governor/top-of-funnel.test.js +331 -0
  87. package/dist/src/index.d.ts +11 -0
  88. package/dist/src/index.d.ts.map +1 -0
  89. package/dist/src/index.js +10 -0
  90. package/dist/src/linear-cli.d.ts +38 -0
  91. package/dist/src/linear-cli.d.ts.map +1 -0
  92. package/dist/src/linear-cli.js +674 -0
  93. package/dist/src/logger.d.ts +117 -0
  94. package/dist/src/logger.d.ts.map +1 -0
  95. package/dist/src/logger.js +430 -0
  96. package/dist/src/manifest/generate.d.ts +20 -0
  97. package/dist/src/manifest/generate.d.ts.map +1 -0
  98. package/dist/src/manifest/generate.js +65 -0
  99. package/dist/src/manifest/index.d.ts +4 -0
  100. package/dist/src/manifest/index.d.ts.map +1 -0
  101. package/dist/src/manifest/index.js +2 -0
  102. package/dist/src/manifest/route-manifest.d.ts +34 -0
  103. package/dist/src/manifest/route-manifest.d.ts.map +1 -0
  104. package/dist/src/manifest/route-manifest.js +148 -0
  105. package/dist/src/orchestrator/activity-emitter.d.ts +119 -0
  106. package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -0
  107. package/dist/src/orchestrator/activity-emitter.js +306 -0
  108. package/dist/src/orchestrator/api-activity-emitter.d.ts +167 -0
  109. package/dist/src/orchestrator/api-activity-emitter.d.ts.map +1 -0
  110. package/dist/src/orchestrator/api-activity-emitter.js +417 -0
  111. package/dist/src/orchestrator/heartbeat-writer.d.ts +57 -0
  112. package/dist/src/orchestrator/heartbeat-writer.d.ts.map +1 -0
  113. package/dist/src/orchestrator/heartbeat-writer.js +137 -0
  114. package/dist/src/orchestrator/index.d.ts +20 -0
  115. package/dist/src/orchestrator/index.d.ts.map +1 -0
  116. package/dist/src/orchestrator/index.js +22 -0
  117. package/dist/src/orchestrator/log-analyzer.d.ts +160 -0
  118. package/dist/src/orchestrator/log-analyzer.d.ts.map +1 -0
  119. package/dist/src/orchestrator/log-analyzer.js +572 -0
  120. package/dist/src/orchestrator/log-config.d.ts +39 -0
  121. package/dist/src/orchestrator/log-config.d.ts.map +1 -0
  122. package/dist/src/orchestrator/log-config.js +45 -0
  123. package/dist/src/orchestrator/orchestrator.d.ts +316 -0
  124. package/dist/src/orchestrator/orchestrator.d.ts.map +1 -0
  125. package/dist/src/orchestrator/orchestrator.js +3290 -0
  126. package/dist/src/orchestrator/parse-work-result.d.ts +16 -0
  127. package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -0
  128. package/dist/src/orchestrator/parse-work-result.js +135 -0
  129. package/dist/src/orchestrator/parse-work-result.test.d.ts +2 -0
  130. package/dist/src/orchestrator/parse-work-result.test.d.ts.map +1 -0
  131. package/dist/src/orchestrator/parse-work-result.test.js +234 -0
  132. package/dist/src/orchestrator/progress-logger.d.ts +72 -0
  133. package/dist/src/orchestrator/progress-logger.d.ts.map +1 -0
  134. package/dist/src/orchestrator/progress-logger.js +135 -0
  135. package/dist/src/orchestrator/session-logger.d.ts +159 -0
  136. package/dist/src/orchestrator/session-logger.d.ts.map +1 -0
  137. package/dist/src/orchestrator/session-logger.js +275 -0
  138. package/dist/src/orchestrator/state-recovery.d.ts +96 -0
  139. package/dist/src/orchestrator/state-recovery.d.ts.map +1 -0
  140. package/dist/src/orchestrator/state-recovery.js +302 -0
  141. package/dist/src/orchestrator/state-types.d.ts +165 -0
  142. package/dist/src/orchestrator/state-types.d.ts.map +1 -0
  143. package/dist/src/orchestrator/state-types.js +7 -0
  144. package/dist/src/orchestrator/stream-parser.d.ts +151 -0
  145. package/dist/src/orchestrator/stream-parser.d.ts.map +1 -0
  146. package/dist/src/orchestrator/stream-parser.js +137 -0
  147. package/dist/src/orchestrator/types.d.ts +232 -0
  148. package/dist/src/orchestrator/types.d.ts.map +1 -0
  149. package/dist/src/orchestrator/types.js +4 -0
  150. package/dist/src/orchestrator/validate-git-remote.test.d.ts +2 -0
  151. package/dist/src/orchestrator/validate-git-remote.test.d.ts.map +1 -0
  152. package/dist/src/orchestrator/validate-git-remote.test.js +61 -0
  153. package/dist/src/providers/a2a-auth.d.ts +81 -0
  154. package/dist/src/providers/a2a-auth.d.ts.map +1 -0
  155. package/dist/src/providers/a2a-auth.js +188 -0
  156. package/dist/src/providers/a2a-auth.test.d.ts +2 -0
  157. package/dist/src/providers/a2a-auth.test.d.ts.map +1 -0
  158. package/dist/src/providers/a2a-auth.test.js +232 -0
  159. package/dist/src/providers/a2a-provider.d.ts +254 -0
  160. package/dist/src/providers/a2a-provider.d.ts.map +1 -0
  161. package/dist/src/providers/a2a-provider.integration.test.d.ts +9 -0
  162. package/dist/src/providers/a2a-provider.integration.test.d.ts.map +1 -0
  163. package/dist/src/providers/a2a-provider.integration.test.js +665 -0
  164. package/dist/src/providers/a2a-provider.js +811 -0
  165. package/dist/src/providers/a2a-provider.test.d.ts +2 -0
  166. package/dist/src/providers/a2a-provider.test.d.ts.map +1 -0
  167. package/dist/src/providers/a2a-provider.test.js +681 -0
  168. package/dist/src/providers/amp-provider.d.ts +20 -0
  169. package/dist/src/providers/amp-provider.d.ts.map +1 -0
  170. package/dist/src/providers/amp-provider.js +24 -0
  171. package/dist/src/providers/claude-provider.d.ts +18 -0
  172. package/dist/src/providers/claude-provider.d.ts.map +1 -0
  173. package/dist/src/providers/claude-provider.js +437 -0
  174. package/dist/src/providers/codex-provider.d.ts +133 -0
  175. package/dist/src/providers/codex-provider.d.ts.map +1 -0
  176. package/dist/src/providers/codex-provider.js +381 -0
  177. package/dist/src/providers/codex-provider.test.d.ts +2 -0
  178. package/dist/src/providers/codex-provider.test.d.ts.map +1 -0
  179. package/dist/src/providers/codex-provider.test.js +387 -0
  180. package/dist/src/providers/index.d.ts +44 -0
  181. package/dist/src/providers/index.d.ts.map +1 -0
  182. package/dist/src/providers/index.js +85 -0
  183. package/dist/src/providers/spring-ai-provider.d.ts +90 -0
  184. package/dist/src/providers/spring-ai-provider.d.ts.map +1 -0
  185. package/dist/src/providers/spring-ai-provider.integration.test.d.ts +13 -0
  186. package/dist/src/providers/spring-ai-provider.integration.test.d.ts.map +1 -0
  187. package/dist/src/providers/spring-ai-provider.integration.test.js +351 -0
  188. package/dist/src/providers/spring-ai-provider.js +317 -0
  189. package/dist/src/providers/spring-ai-provider.test.d.ts +2 -0
  190. package/dist/src/providers/spring-ai-provider.test.d.ts.map +1 -0
  191. package/dist/src/providers/spring-ai-provider.test.js +200 -0
  192. package/dist/src/providers/types.d.ts +165 -0
  193. package/dist/src/providers/types.d.ts.map +1 -0
  194. package/dist/src/providers/types.js +13 -0
  195. package/dist/src/templates/adapters.d.ts +51 -0
  196. package/dist/src/templates/adapters.d.ts.map +1 -0
  197. package/dist/src/templates/adapters.js +104 -0
  198. package/dist/src/templates/adapters.test.d.ts +2 -0
  199. package/dist/src/templates/adapters.test.d.ts.map +1 -0
  200. package/dist/src/templates/adapters.test.js +165 -0
  201. package/dist/src/templates/agent-definition.d.ts +85 -0
  202. package/dist/src/templates/agent-definition.d.ts.map +1 -0
  203. package/dist/src/templates/agent-definition.js +97 -0
  204. package/dist/src/templates/agent-definition.test.d.ts +2 -0
  205. package/dist/src/templates/agent-definition.test.d.ts.map +1 -0
  206. package/dist/src/templates/agent-definition.test.js +209 -0
  207. package/dist/src/templates/index.d.ts +14 -0
  208. package/dist/src/templates/index.d.ts.map +1 -0
  209. package/dist/src/templates/index.js +11 -0
  210. package/dist/src/templates/loader.d.ts +41 -0
  211. package/dist/src/templates/loader.d.ts.map +1 -0
  212. package/dist/src/templates/loader.js +114 -0
  213. package/dist/src/templates/registry.d.ts +80 -0
  214. package/dist/src/templates/registry.d.ts.map +1 -0
  215. package/dist/src/templates/registry.js +177 -0
  216. package/dist/src/templates/registry.test.d.ts +2 -0
  217. package/dist/src/templates/registry.test.d.ts.map +1 -0
  218. package/dist/src/templates/registry.test.js +198 -0
  219. package/dist/src/templates/renderer.d.ts +29 -0
  220. package/dist/src/templates/renderer.d.ts.map +1 -0
  221. package/dist/src/templates/renderer.js +35 -0
  222. package/dist/src/templates/strategy-templates.test.d.ts +2 -0
  223. package/dist/src/templates/strategy-templates.test.d.ts.map +1 -0
  224. package/dist/src/templates/strategy-templates.test.js +619 -0
  225. package/dist/src/templates/types.d.ts +233 -0
  226. package/dist/src/templates/types.d.ts.map +1 -0
  227. package/dist/src/templates/types.js +127 -0
  228. package/dist/src/templates/types.test.d.ts +2 -0
  229. package/dist/src/templates/types.test.d.ts.map +1 -0
  230. package/dist/src/templates/types.test.js +232 -0
  231. package/dist/src/tools/index.d.ts +6 -0
  232. package/dist/src/tools/index.d.ts.map +1 -0
  233. package/dist/src/tools/index.js +3 -0
  234. package/dist/src/tools/linear-runner.d.ts +34 -0
  235. package/dist/src/tools/linear-runner.d.ts.map +1 -0
  236. package/dist/src/tools/linear-runner.js +700 -0
  237. package/dist/src/tools/plugins/linear.d.ts +9 -0
  238. package/dist/src/tools/plugins/linear.d.ts.map +1 -0
  239. package/dist/src/tools/plugins/linear.js +138 -0
  240. package/dist/src/tools/registry.d.ts +9 -0
  241. package/dist/src/tools/registry.d.ts.map +1 -0
  242. package/dist/src/tools/registry.js +18 -0
  243. package/dist/src/tools/types.d.ts +18 -0
  244. package/dist/src/tools/types.d.ts.map +1 -0
  245. package/dist/src/tools/types.js +1 -0
  246. package/package.json +78 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Governor Event Types
3
+ *
4
+ * Discriminated union of events that flow through the GovernorEventBus.
5
+ * Events are produced by webhooks (real-time) and poll sweeps (periodic),
6
+ * then consumed by the EventDrivenGovernor for decision-making.
7
+ */
8
+ import type { GovernorIssue } from './governor-types.js';
9
+ /**
10
+ * Fired when an issue's workflow status changes (e.g., Backlog → Started).
11
+ * Typically produced by webhook `issue-updated` or a poll sweep diff.
12
+ */
13
+ export interface IssueStatusChangedEvent {
14
+ type: 'issue-status-changed';
15
+ issueId: string;
16
+ issue: GovernorIssue;
17
+ previousStatus?: string;
18
+ newStatus: string;
19
+ /** ISO-8601 timestamp */
20
+ timestamp: string;
21
+ /** Where this event originated */
22
+ source: EventSource;
23
+ }
24
+ /**
25
+ * Fired when a comment is added to an issue.
26
+ * Used for parsing human override directives (HOLD, RESUME, PRIORITY, etc.).
27
+ */
28
+ export interface CommentAddedEvent {
29
+ type: 'comment-added';
30
+ issueId: string;
31
+ issue: GovernorIssue;
32
+ commentId: string;
33
+ commentBody: string;
34
+ userId?: string;
35
+ userName?: string;
36
+ /** ISO-8601 timestamp */
37
+ timestamp: string;
38
+ source: EventSource;
39
+ }
40
+ /**
41
+ * Fired when an agent session completes (success or failure).
42
+ * Allows the Governor to re-evaluate the issue immediately.
43
+ */
44
+ export interface SessionCompletedEvent {
45
+ type: 'session-completed';
46
+ issueId: string;
47
+ issue: GovernorIssue;
48
+ sessionId: string;
49
+ outcome: 'success' | 'failure';
50
+ /** ISO-8601 timestamp */
51
+ timestamp: string;
52
+ source: EventSource;
53
+ }
54
+ /**
55
+ * Emitted by periodic poll sweeps. Contains a full snapshot of a single
56
+ * issue so the Governor can evaluate it without an extra API call.
57
+ */
58
+ export interface PollSnapshotEvent {
59
+ type: 'poll-snapshot';
60
+ issueId: string;
61
+ issue: GovernorIssue;
62
+ project: string;
63
+ /** ISO-8601 timestamp */
64
+ timestamp: string;
65
+ source: EventSource;
66
+ }
67
+ export type EventSource = 'webhook' | 'poll' | 'manual';
68
+ export type GovernorEvent = IssueStatusChangedEvent | CommentAddedEvent | SessionCompletedEvent | PollSnapshotEvent;
69
+ /**
70
+ * Generate a deduplication key for an event.
71
+ * Same issue at the same status = duplicate within the dedup window.
72
+ */
73
+ export declare function eventDedupKey(event: GovernorEvent): string;
74
+ /**
75
+ * Create a GovernorEvent timestamp (ISO-8601 now).
76
+ */
77
+ export declare function eventTimestamp(): string;
78
+ //# sourceMappingURL=event-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-types.d.ts","sourceRoot":"","sources":["../../../src/governor/event-types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAMxD;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,sBAAsB,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,aAAa,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,kCAAkC;IAClC,MAAM,EAAE,WAAW,CAAA;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,aAAa,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,mBAAmB,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,aAAa,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,SAAS,GAAG,SAAS,CAAA;IAC9B,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,aAAa,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;CACpB;AAMD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;AAMvD,MAAM,MAAM,aAAa,GACrB,uBAAuB,GACvB,iBAAiB,GACjB,qBAAqB,GACrB,iBAAiB,CAAA;AAMrB;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAW1D;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Governor Event Types
3
+ *
4
+ * Discriminated union of events that flow through the GovernorEventBus.
5
+ * Events are produced by webhooks (real-time) and poll sweeps (periodic),
6
+ * then consumed by the EventDrivenGovernor for decision-making.
7
+ */
8
+ // ---------------------------------------------------------------------------
9
+ // Helpers
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Generate a deduplication key for an event.
13
+ * Same issue at the same status = duplicate within the dedup window.
14
+ */
15
+ export function eventDedupKey(event) {
16
+ switch (event.type) {
17
+ case 'issue-status-changed':
18
+ return `${event.issueId}:${event.newStatus}`;
19
+ case 'comment-added':
20
+ return `${event.issueId}:comment:${event.commentId}`;
21
+ case 'session-completed':
22
+ return `${event.issueId}:session:${event.sessionId}`;
23
+ case 'poll-snapshot':
24
+ return `${event.issueId}:${event.issue.status}`;
25
+ }
26
+ }
27
+ /**
28
+ * Create a GovernorEvent timestamp (ISO-8601 now).
29
+ */
30
+ export function eventTimestamp() {
31
+ return new Date().toISOString();
32
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Governor Types
3
+ *
4
+ * Core type definitions for the Workflow Governor scan loop.
5
+ * The Governor periodically scans Linear projects and dispatches
6
+ * agent work based on issue status and configuration.
7
+ */
8
+ import type { TopOfFunnelConfig } from './top-of-funnel.js';
9
+ /**
10
+ * Actions the Governor can take for a given issue.
11
+ *
12
+ * Each action maps to an agent work type or special handling:
13
+ * - trigger-research: Dispatch a research agent (Icebox, sparse description)
14
+ * - trigger-backlog-creation: Dispatch a backlog-creation agent (Icebox, well-researched)
15
+ * - trigger-development: Dispatch a development agent (Backlog)
16
+ * - trigger-qa: Dispatch a QA agent (Finished)
17
+ * - trigger-acceptance: Dispatch an acceptance agent (Delivered)
18
+ * - trigger-refinement: Dispatch a refinement agent (Rejected)
19
+ * - decompose: Trigger task decomposition (escalation strategy)
20
+ * - escalate-human: Create a human escalation touchpoint
21
+ * - none: No action needed
22
+ */
23
+ export type GovernorAction = 'trigger-research' | 'trigger-backlog-creation' | 'trigger-development' | 'trigger-qa' | 'trigger-acceptance' | 'trigger-refinement' | 'decompose' | 'escalate-human' | 'none';
24
+ /**
25
+ * Configuration for the Workflow Governor scan loop.
26
+ */
27
+ export interface GovernorConfig {
28
+ /** Projects to scan */
29
+ projects: string[];
30
+ /** Scan interval in milliseconds (default: 60000) */
31
+ scanIntervalMs: number;
32
+ /** Maximum concurrent dispatches per scan (default: 3) */
33
+ maxConcurrentDispatches: number;
34
+ /** Enable auto-research from Icebox (default: true) */
35
+ enableAutoResearch: boolean;
36
+ /** Enable auto-backlog-creation from Icebox (default: true) */
37
+ enableAutoBacklogCreation: boolean;
38
+ /** Enable auto-development from Backlog (default: true) */
39
+ enableAutoDevelopment: boolean;
40
+ /** Enable auto-QA from Finished (default: true) */
41
+ enableAutoQA: boolean;
42
+ /** Enable auto-acceptance from Delivered (default: true) */
43
+ enableAutoAcceptance: boolean;
44
+ /** Human response timeout in milliseconds (default: 4 hours) */
45
+ humanResponseTimeoutMs: number;
46
+ /** Top-of-funnel configuration overrides */
47
+ topOfFunnel?: Partial<TopOfFunnelConfig>;
48
+ }
49
+ /**
50
+ * Sensible defaults for the Governor configuration.
51
+ */
52
+ export declare const DEFAULT_GOVERNOR_CONFIG: GovernorConfig;
53
+ /**
54
+ * Result of a single project scan pass.
55
+ */
56
+ export interface ScanResult {
57
+ project: string;
58
+ scannedIssues: number;
59
+ actionsDispatched: number;
60
+ skippedReasons: Map<string, string>;
61
+ errors: Array<{
62
+ issueId: string;
63
+ error: string;
64
+ }>;
65
+ }
66
+ /**
67
+ * Minimal issue representation used by the Governor.
68
+ * Intentionally decoupled from the Linear SDK types so the Governor
69
+ * can be tested and used with any issue source.
70
+ */
71
+ export interface GovernorIssue {
72
+ id: string;
73
+ identifier: string;
74
+ title: string;
75
+ description?: string;
76
+ status: string;
77
+ labels: string[];
78
+ createdAt: number;
79
+ parentId?: string;
80
+ project?: string;
81
+ }
82
+ //# sourceMappingURL=governor-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governor-types.d.ts","sourceRoot":"","sources":["../../../src/governor/governor-types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAM3D;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,0BAA0B,GAC1B,qBAAqB,GACrB,YAAY,GACZ,oBAAoB,GACpB,oBAAoB,GACpB,WAAW,GACX,gBAAgB,GAChB,MAAM,CAAA;AAMV;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,uBAAuB;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,qDAAqD;IACrD,cAAc,EAAE,MAAM,CAAA;IACtB,0DAA0D;IAC1D,uBAAuB,EAAE,MAAM,CAAA;IAC/B,uDAAuD;IACvD,kBAAkB,EAAE,OAAO,CAAA;IAC3B,+DAA+D;IAC/D,yBAAyB,EAAE,OAAO,CAAA;IAClC,2DAA2D;IAC3D,qBAAqB,EAAE,OAAO,CAAA;IAC9B,mDAAmD;IACnD,YAAY,EAAE,OAAO,CAAA;IACrB,4DAA4D;IAC5D,oBAAoB,EAAE,OAAO,CAAA;IAC7B,gEAAgE;IAChE,sBAAsB,EAAE,MAAM,CAAA;IAC9B,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;CACzC;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAUrC,CAAA;AAMD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAClD;AAMD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Governor Types
3
+ *
4
+ * Core type definitions for the Workflow Governor scan loop.
5
+ * The Governor periodically scans Linear projects and dispatches
6
+ * agent work based on issue status and configuration.
7
+ */
8
+ /**
9
+ * Sensible defaults for the Governor configuration.
10
+ */
11
+ export const DEFAULT_GOVERNOR_CONFIG = {
12
+ projects: [],
13
+ scanIntervalMs: 60_000,
14
+ maxConcurrentDispatches: 3,
15
+ enableAutoResearch: false,
16
+ enableAutoBacklogCreation: false,
17
+ enableAutoDevelopment: true,
18
+ enableAutoQA: true,
19
+ enableAutoAcceptance: true,
20
+ humanResponseTimeoutMs: 4 * 60 * 60 * 1000, // 4 hours
21
+ };
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Workflow Governor
3
+ *
4
+ * Periodically scans Linear projects and dispatches agent work based on
5
+ * issue status and configuration. The Governor is the central scheduler
6
+ * that replaces webhook-driven execution with a polling-based model.
7
+ *
8
+ * The Governor is designed with dependency injection so it can be tested
9
+ * without any external services (Linear, Redis, etc.).
10
+ */
11
+ import type { GovernorAction, GovernorConfig, GovernorIssue, ScanResult } from './governor-types.js';
12
+ import type { OverridePriority } from './override-parser.js';
13
+ /**
14
+ * Abstract dependencies that the Governor needs to interact with
15
+ * external systems. Callers inject these at construction time.
16
+ *
17
+ * This design keeps the Governor testable and decoupled from
18
+ * concrete implementations (Linear SDK, Redis, etc.).
19
+ */
20
+ export interface GovernorDependencies {
21
+ /** List non-terminal issues for a project */
22
+ listIssues: (project: string) => Promise<GovernorIssue[]>;
23
+ /** Check if an issue has an active agent session */
24
+ hasActiveSession: (issueId: string) => Promise<boolean>;
25
+ /** Check if an issue is within cooldown (e.g., just failed QA) */
26
+ isWithinCooldown: (issueId: string) => Promise<boolean>;
27
+ /** Check if an issue is a parent (has sub-issues) */
28
+ isParentIssue: (issueId: string) => Promise<boolean>;
29
+ /** Check if an issue has a HOLD override active */
30
+ isHeld: (issueId: string) => Promise<boolean>;
31
+ /** Get the PRIORITY override for an issue (high > medium > low) */
32
+ getOverridePriority: (issueId: string) => Promise<OverridePriority | null>;
33
+ /** Get the workflow escalation strategy for an issue */
34
+ getWorkflowStrategy: (issueId: string) => Promise<string | undefined>;
35
+ /** Check if the research phase has been completed for an issue */
36
+ isResearchCompleted: (issueId: string) => Promise<boolean>;
37
+ /** Check if the backlog-creation phase has been completed for an issue */
38
+ isBacklogCreationCompleted: (issueId: string) => Promise<boolean>;
39
+ /** Count completed agent sessions for an issue (for circuit breaker) */
40
+ getCompletedSessionCount: (issueId: string) => Promise<number>;
41
+ /** Dispatch work for an issue with a specific action */
42
+ dispatchWork: (issue: GovernorIssue, action: GovernorAction) => Promise<void>;
43
+ }
44
+ /**
45
+ * The Workflow Governor scans projects on a configurable interval,
46
+ * evaluates each issue against the decision engine, and dispatches
47
+ * agent work for actionable issues.
48
+ */
49
+ export interface WorkflowGovernorCallbacks {
50
+ onScanComplete?: (results: ScanResult[]) => void | Promise<void>;
51
+ }
52
+ export declare class WorkflowGovernor {
53
+ private readonly config;
54
+ private readonly deps;
55
+ private readonly callbacks;
56
+ private intervalHandle;
57
+ private running;
58
+ private scanning;
59
+ constructor(config: Partial<GovernorConfig>, deps: GovernorDependencies, callbacks?: WorkflowGovernorCallbacks);
60
+ /**
61
+ * Start the scan loop. Runs `scanOnce()` immediately, then repeats
62
+ * on the configured interval.
63
+ */
64
+ start(): void;
65
+ /**
66
+ * Stop the scan loop gracefully. If a scan is in progress it will
67
+ * finish before the Governor is fully stopped.
68
+ */
69
+ stop(): void;
70
+ /**
71
+ * Check if the Governor is running.
72
+ */
73
+ isRunning(): boolean;
74
+ /**
75
+ * Run a single scan pass across all configured projects.
76
+ *
77
+ * For each project:
78
+ * 1. List all non-terminal issues
79
+ * 2. Gather context for each issue (active session, cooldown, etc.)
80
+ * 3. Run the decision engine
81
+ * 4. Dispatch actions up to `maxConcurrentDispatches`
82
+ *
83
+ * Returns an array of ScanResult (one per project).
84
+ */
85
+ scanOnce(): Promise<ScanResult[]>;
86
+ /**
87
+ * Scan a single project and dispatch actions.
88
+ *
89
+ * Issues are evaluated in two passes:
90
+ * 1. Evaluate all issues to determine actions and gather priority overrides
91
+ * 2. Sort actionable issues by PRIORITY override (high > medium > low > none)
92
+ * and dispatch up to `maxConcurrentDispatches`
93
+ */
94
+ private scanProject;
95
+ /**
96
+ * Gather context for a single issue and run it through the decision engine.
97
+ */
98
+ private evaluateIssue;
99
+ }
100
+ //# sourceMappingURL=governor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governor.d.ts","sourceRoot":"","sources":["../../../src/governor/governor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,UAAU,EACX,MAAM,qBAAqB,CAAA;AAG5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAsC5D;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,6CAA6C;IAC7C,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;IACzD,oDAAoD;IACpD,gBAAgB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACvD,kEAAkE;IAClE,gBAAgB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACvD,qDAAqD;IACrD,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACpD,mDAAmD;IACnD,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7C,mEAAmE;IACnE,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;IAC1E,wDAAwD;IACxD,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACrE,kEAAkE;IAClE,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1D,0EAA0E;IAC1E,0BAA0B,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACjE,wEAAwE;IACxE,wBAAwB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9D,wDAAwD;IACxD,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9E;AAMD;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACjE;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2B;IACrD,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,SAAS,CAAC,EAAE,yBAAyB;IAU9G;;;OAGG;IACH,KAAK,IAAI,IAAI;IAuBb;;;OAGG;IACH,IAAI,IAAI,IAAI;IAgBZ;;OAEG;IACH,SAAS,IAAI,OAAO;IAQpB;;;;;;;;;;OAUG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IA4BvC;;;;;;;OAOG;YACW,WAAW;IA2GzB;;OAEG;YACW,aAAa;CAqC5B"}
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Workflow Governor
3
+ *
4
+ * Periodically scans Linear projects and dispatches agent work based on
5
+ * issue status and configuration. The Governor is the central scheduler
6
+ * that replaces webhook-driven execution with a polling-based model.
7
+ *
8
+ * The Governor is designed with dependency injection so it can be tested
9
+ * without any external services (Linear, Redis, etc.).
10
+ */
11
+ import { DEFAULT_GOVERNOR_CONFIG } from './governor-types.js';
12
+ import { decideAction } from './decision-engine.js';
13
+ // ---------------------------------------------------------------------------
14
+ // Logging
15
+ // ---------------------------------------------------------------------------
16
+ const log = {
17
+ info: (msg, data) => console.log(`[governor] ${msg}`, data ? JSON.stringify(data) : ''),
18
+ warn: (msg, data) => console.warn(`[governor] ${msg}`, data ? JSON.stringify(data) : ''),
19
+ error: (msg, data) => console.error(`[governor] ${msg}`, data ? JSON.stringify(data) : ''),
20
+ debug: (_msg, _data) => { },
21
+ };
22
+ // ---------------------------------------------------------------------------
23
+ // Priority ordering
24
+ // ---------------------------------------------------------------------------
25
+ /** Map priority to a sort weight (lower = higher priority = dispatched first) */
26
+ function priorityWeight(priority) {
27
+ switch (priority) {
28
+ case 'high':
29
+ return 0;
30
+ case 'medium':
31
+ return 1;
32
+ case 'low':
33
+ return 2;
34
+ default:
35
+ return 3;
36
+ }
37
+ }
38
+ export class WorkflowGovernor {
39
+ config;
40
+ deps;
41
+ callbacks;
42
+ intervalHandle = null;
43
+ running = false;
44
+ scanning = false;
45
+ constructor(config, deps, callbacks) {
46
+ this.config = { ...DEFAULT_GOVERNOR_CONFIG, ...config };
47
+ this.deps = deps;
48
+ this.callbacks = callbacks ?? {};
49
+ }
50
+ // -------------------------------------------------------------------------
51
+ // Lifecycle
52
+ // -------------------------------------------------------------------------
53
+ /**
54
+ * Start the scan loop. Runs `scanOnce()` immediately, then repeats
55
+ * on the configured interval.
56
+ */
57
+ start() {
58
+ if (this.running) {
59
+ log.warn('Governor is already running');
60
+ return;
61
+ }
62
+ this.running = true;
63
+ log.info('Governor started', {
64
+ projects: this.config.projects,
65
+ scanIntervalMs: this.config.scanIntervalMs,
66
+ maxConcurrentDispatches: this.config.maxConcurrentDispatches,
67
+ });
68
+ // Run the first scan immediately (fire and forget — errors logged internally)
69
+ void this.scanOnce();
70
+ // Schedule subsequent scans
71
+ this.intervalHandle = setInterval(() => {
72
+ void this.scanOnce();
73
+ }, this.config.scanIntervalMs);
74
+ }
75
+ /**
76
+ * Stop the scan loop gracefully. If a scan is in progress it will
77
+ * finish before the Governor is fully stopped.
78
+ */
79
+ stop() {
80
+ if (!this.running) {
81
+ log.warn('Governor is not running');
82
+ return;
83
+ }
84
+ this.running = false;
85
+ if (this.intervalHandle !== null) {
86
+ clearInterval(this.intervalHandle);
87
+ this.intervalHandle = null;
88
+ }
89
+ log.info('Governor stopped');
90
+ }
91
+ /**
92
+ * Check if the Governor is running.
93
+ */
94
+ isRunning() {
95
+ return this.running;
96
+ }
97
+ // -------------------------------------------------------------------------
98
+ // Scan
99
+ // -------------------------------------------------------------------------
100
+ /**
101
+ * Run a single scan pass across all configured projects.
102
+ *
103
+ * For each project:
104
+ * 1. List all non-terminal issues
105
+ * 2. Gather context for each issue (active session, cooldown, etc.)
106
+ * 3. Run the decision engine
107
+ * 4. Dispatch actions up to `maxConcurrentDispatches`
108
+ *
109
+ * Returns an array of ScanResult (one per project).
110
+ */
111
+ async scanOnce() {
112
+ // Guard against overlapping scans
113
+ if (this.scanning) {
114
+ log.debug('Scan already in progress, skipping');
115
+ return [];
116
+ }
117
+ this.scanning = true;
118
+ const results = [];
119
+ try {
120
+ for (const project of this.config.projects) {
121
+ const result = await this.scanProject(project);
122
+ results.push(result);
123
+ }
124
+ }
125
+ finally {
126
+ this.scanning = false;
127
+ }
128
+ await this.callbacks.onScanComplete?.(results);
129
+ return results;
130
+ }
131
+ // -------------------------------------------------------------------------
132
+ // Internal
133
+ // -------------------------------------------------------------------------
134
+ /**
135
+ * Scan a single project and dispatch actions.
136
+ *
137
+ * Issues are evaluated in two passes:
138
+ * 1. Evaluate all issues to determine actions and gather priority overrides
139
+ * 2. Sort actionable issues by PRIORITY override (high > medium > low > none)
140
+ * and dispatch up to `maxConcurrentDispatches`
141
+ */
142
+ async scanProject(project) {
143
+ const result = {
144
+ project,
145
+ scannedIssues: 0,
146
+ actionsDispatched: 0,
147
+ skippedReasons: new Map(),
148
+ errors: [],
149
+ };
150
+ let issues;
151
+ try {
152
+ issues = await this.deps.listIssues(project);
153
+ }
154
+ catch (err) {
155
+ const errorMsg = err instanceof Error ? err.message : String(err);
156
+ log.error('Failed to list issues for project', { project, error: errorMsg });
157
+ result.errors.push({ issueId: `project:${project}`, error: errorMsg });
158
+ return result;
159
+ }
160
+ result.scannedIssues = issues.length;
161
+ log.info('Scanning project', {
162
+ project,
163
+ issueCount: issues.length,
164
+ });
165
+ // Pass 1: Evaluate all issues and gather priority overrides
166
+ const actionable = [];
167
+ for (const issue of issues) {
168
+ try {
169
+ const [decision, priority] = await Promise.all([
170
+ this.evaluateIssue(issue),
171
+ this.deps.getOverridePriority(issue.id),
172
+ ]);
173
+ if (decision.action === 'none') {
174
+ result.skippedReasons.set(issue.identifier, decision.reason);
175
+ continue;
176
+ }
177
+ actionable.push({
178
+ issue,
179
+ action: decision.action,
180
+ reason: decision.reason,
181
+ priority,
182
+ });
183
+ }
184
+ catch (err) {
185
+ const errorMsg = err instanceof Error ? err.message : String(err);
186
+ log.error('Error evaluating issue', {
187
+ issueIdentifier: issue.identifier,
188
+ error: errorMsg,
189
+ });
190
+ result.errors.push({ issueId: issue.identifier, error: errorMsg });
191
+ }
192
+ }
193
+ // Pass 2: Sort by priority override (high > medium > low > none)
194
+ actionable.sort((a, b) => priorityWeight(a.priority) - priorityWeight(b.priority));
195
+ // Pass 3: Dispatch up to the limit
196
+ for (const item of actionable) {
197
+ if (result.actionsDispatched >= this.config.maxConcurrentDispatches) {
198
+ log.info('Dispatch limit reached', {
199
+ project,
200
+ limit: this.config.maxConcurrentDispatches,
201
+ dispatched: result.actionsDispatched,
202
+ });
203
+ break;
204
+ }
205
+ try {
206
+ await this.deps.dispatchWork(item.issue, item.action);
207
+ result.actionsDispatched++;
208
+ log.info('Dispatched action', {
209
+ issueIdentifier: item.issue.identifier,
210
+ action: item.action,
211
+ reason: item.reason,
212
+ priority: item.priority ?? 'none',
213
+ });
214
+ }
215
+ catch (err) {
216
+ const errorMsg = err instanceof Error ? err.message : String(err);
217
+ log.error('Error dispatching issue', {
218
+ issueIdentifier: item.issue.identifier,
219
+ error: errorMsg,
220
+ });
221
+ result.errors.push({ issueId: item.issue.identifier, error: errorMsg });
222
+ }
223
+ }
224
+ log.info('Project scan complete', {
225
+ project,
226
+ scanned: result.scannedIssues,
227
+ dispatched: result.actionsDispatched,
228
+ skipped: result.skippedReasons.size,
229
+ errors: result.errors.length,
230
+ });
231
+ return result;
232
+ }
233
+ /**
234
+ * Gather context for a single issue and run it through the decision engine.
235
+ */
236
+ async evaluateIssue(issue) {
237
+ // Gather all context in parallel for efficiency
238
+ const [hasActiveSession, isWithinCooldown, isParentIssue, isHeld, workflowStrategy, researchCompleted, backlogCreationCompleted, completedSessionCount,] = await Promise.all([
239
+ this.deps.hasActiveSession(issue.id),
240
+ this.deps.isWithinCooldown(issue.id),
241
+ this.deps.isParentIssue(issue.id),
242
+ this.deps.isHeld(issue.id),
243
+ this.deps.getWorkflowStrategy(issue.id),
244
+ this.deps.isResearchCompleted(issue.id),
245
+ this.deps.isBacklogCreationCompleted(issue.id),
246
+ this.deps.getCompletedSessionCount(issue.id),
247
+ ]);
248
+ const ctx = {
249
+ issue,
250
+ config: this.config,
251
+ hasActiveSession,
252
+ isHeld,
253
+ isWithinCooldown,
254
+ isParentIssue,
255
+ workflowStrategy,
256
+ researchCompleted,
257
+ backlogCreationCompleted,
258
+ completedSessionCount,
259
+ };
260
+ return decideAction(ctx);
261
+ }
262
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=governor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governor.test.d.ts","sourceRoot":"","sources":["../../../src/governor/governor.test.ts"],"names":[],"mappings":""}