agentic-orchestrator 0.1.6 → 0.1.8

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 (438) hide show
  1. package/.prettierignore +10 -0
  2. package/.prettierrc.json +24 -0
  3. package/CLAUDE.md +3 -2
  4. package/README.md +71 -48
  5. package/agentic/orchestrator/defaults/policy.defaults.yaml +1 -1
  6. package/agentic/orchestrator/prompts/planner.system.md +1 -0
  7. package/agentic/orchestrator/schemas/agents.schema.json +5 -22
  8. package/agentic/orchestrator/schemas/gates.schema.json +4 -19
  9. package/agentic/orchestrator/schemas/index.schema.json +3 -14
  10. package/agentic/orchestrator/schemas/multi-project.schema.json +2 -8
  11. package/agentic/orchestrator/schemas/plan.schema.json +6 -26
  12. package/agentic/orchestrator/schemas/policy.schema.json +19 -81
  13. package/agentic/orchestrator/schemas/policy.user.schema.json +1 -5
  14. package/agentic/orchestrator/schemas/qa_test_index.schema.json +5 -29
  15. package/agentic/orchestrator/schemas/state.schema.json +11 -61
  16. package/agentic/orchestrator/tools/catalog.json +33 -164
  17. package/agentic/orchestrator/tools/schemas/input/evidence.latest.input.schema.json +1 -3
  18. package/agentic/orchestrator/tools/schemas/input/feature.delete.input.schema.json +1 -5
  19. package/agentic/orchestrator/tools/schemas/input/feature.get_context.input.schema.json +1 -3
  20. package/agentic/orchestrator/tools/schemas/input/feature.init.input.schema.json +1 -4
  21. package/agentic/orchestrator/tools/schemas/input/feature.log_append.input.schema.json +1 -5
  22. package/agentic/orchestrator/tools/schemas/input/feature.ready_to_merge.input.schema.json +1 -6
  23. package/agentic/orchestrator/tools/schemas/input/feature.state_get.input.schema.json +1 -3
  24. package/agentic/orchestrator/tools/schemas/input/feature.state_patch.input.schema.json +1 -5
  25. package/agentic/orchestrator/tools/schemas/input/gates.run.input.schema.json +1 -5
  26. package/agentic/orchestrator/tools/schemas/input/locks.acquire.input.schema.json +1 -5
  27. package/agentic/orchestrator/tools/schemas/input/locks.release.input.schema.json +1 -5
  28. package/agentic/orchestrator/tools/schemas/input/performance.record_outcome.input.schema.json +10 -1
  29. package/agentic/orchestrator/tools/schemas/input/plan.get.input.schema.json +1 -3
  30. package/agentic/orchestrator/tools/schemas/input/plan.submit.input.schema.json +1 -5
  31. package/agentic/orchestrator/tools/schemas/input/plan.update.input.schema.json +1 -6
  32. package/agentic/orchestrator/tools/schemas/input/qa.test_index_get.input.schema.json +1 -3
  33. package/agentic/orchestrator/tools/schemas/input/qa.test_index_update.input.schema.json +1 -6
  34. package/agentic/orchestrator/tools/schemas/input/repo.apply_patch.input.schema.json +1 -5
  35. package/agentic/orchestrator/tools/schemas/input/repo.diff.input.schema.json +1 -3
  36. package/agentic/orchestrator/tools/schemas/input/repo.diff_bundle.input.schema.json +1 -3
  37. package/agentic/orchestrator/tools/schemas/input/repo.ensure_worktree.input.schema.json +1 -4
  38. package/agentic/orchestrator/tools/schemas/input/repo.read_file.input.schema.json +1 -4
  39. package/agentic/orchestrator/tools/schemas/input/repo.search.input.schema.json +1 -4
  40. package/agentic/orchestrator/tools/schemas/input/repo.status.input.schema.json +1 -3
  41. package/agentic/orchestrator/tools/schemas/input/report.feature_summary.input.schema.json +1 -3
  42. package/agentic/orchestrator/tools/schemas/output/collisions.scan.output.schema.json +1 -3
  43. package/agentic/orchestrator/tools/schemas/output/evidence.latest.output.schema.json +1 -4
  44. package/agentic/orchestrator/tools/schemas/output/feature.delete.output.schema.json +4 -20
  45. package/agentic/orchestrator/tools/schemas/output/feature.discover_specs.output.schema.json +2 -7
  46. package/agentic/orchestrator/tools/schemas/output/feature.get_context.output.schema.json +1 -8
  47. package/agentic/orchestrator/tools/schemas/output/feature.init.output.schema.json +1 -5
  48. package/agentic/orchestrator/tools/schemas/output/feature.log_append.output.schema.json +1 -5
  49. package/agentic/orchestrator/tools/schemas/output/feature.ready_to_merge.output.schema.json +1 -6
  50. package/agentic/orchestrator/tools/schemas/output/feature.state_get.output.schema.json +1 -4
  51. package/agentic/orchestrator/tools/schemas/output/feature.state_patch.output.schema.json +1 -5
  52. package/agentic/orchestrator/tools/schemas/output/gates.list.output.schema.json +2 -7
  53. package/agentic/orchestrator/tools/schemas/output/gates.run.output.schema.json +1 -8
  54. package/agentic/orchestrator/tools/schemas/output/locks.acquire.output.schema.json +1 -7
  55. package/agentic/orchestrator/tools/schemas/output/locks.release.output.schema.json +1 -5
  56. package/agentic/orchestrator/tools/schemas/output/performance.get_analytics.output.schema.json +22 -2
  57. package/agentic/orchestrator/tools/schemas/output/plan.get.output.schema.json +1 -4
  58. package/agentic/orchestrator/tools/schemas/output/plan.submit.output.schema.json +1 -5
  59. package/agentic/orchestrator/tools/schemas/output/plan.update.output.schema.json +1 -5
  60. package/agentic/orchestrator/tools/schemas/output/qa.test_index_get.output.schema.json +1 -5
  61. package/agentic/orchestrator/tools/schemas/output/qa.test_index_update.output.schema.json +1 -4
  62. package/agentic/orchestrator/tools/schemas/output/repo.apply_patch.output.schema.json +1 -6
  63. package/agentic/orchestrator/tools/schemas/output/repo.diff.output.schema.json +1 -4
  64. package/agentic/orchestrator/tools/schemas/output/repo.diff_bundle.output.schema.json +1 -7
  65. package/agentic/orchestrator/tools/schemas/output/repo.ensure_worktree.output.schema.json +1 -6
  66. package/agentic/orchestrator/tools/schemas/output/repo.read_file.output.schema.json +1 -5
  67. package/agentic/orchestrator/tools/schemas/output/repo.search.output.schema.json +1 -5
  68. package/agentic/orchestrator/tools/schemas/output/repo.status.output.schema.json +1 -5
  69. package/agentic/orchestrator/tools/schemas/output/report.dashboard.output.schema.json +1 -4
  70. package/apps/control-plane/scripts/validate-architecture-rules.mjs +16 -5
  71. package/apps/control-plane/scripts/validate-docker-mcp-contract.mjs +30 -8
  72. package/apps/control-plane/scripts/validate-mcp-contracts.ts +13 -7
  73. package/apps/control-plane/src/application/adapters/adapter-registry.ts +35 -15
  74. package/apps/control-plane/src/application/multi-project-loader.ts +27 -10
  75. package/apps/control-plane/src/application/services/activity-monitor-service.ts +26 -14
  76. package/apps/control-plane/src/application/services/collision-queue-service.ts +31 -17
  77. package/apps/control-plane/src/application/services/cost-tracking-service.ts +23 -16
  78. package/apps/control-plane/src/application/services/dependency-scheduler-service.ts +12 -4
  79. package/apps/control-plane/src/application/services/feature-deletion-service.ts +94 -58
  80. package/apps/control-plane/src/application/services/feature-lifecycle-service.ts +19 -13
  81. package/apps/control-plane/src/application/services/feature-state-service.ts +29 -19
  82. package/apps/control-plane/src/application/services/gate-interpolation-service.ts +7 -2
  83. package/apps/control-plane/src/application/services/gate-service.ts +64 -41
  84. package/apps/control-plane/src/application/services/instance-isolation-service.ts +1 -1
  85. package/apps/control-plane/src/application/services/issue-tracker-service.ts +49 -38
  86. package/apps/control-plane/src/application/services/lock-service.ts +75 -49
  87. package/apps/control-plane/src/application/services/merge-service.ts +91 -50
  88. package/apps/control-plane/src/application/services/notifier-service.ts +42 -20
  89. package/apps/control-plane/src/application/services/patch-service.ts +73 -44
  90. package/apps/control-plane/src/application/services/performance-analytics-service.ts +8 -6
  91. package/apps/control-plane/src/application/services/plan-service.ts +148 -89
  92. package/apps/control-plane/src/application/services/policy-loader-service.ts +10 -4
  93. package/apps/control-plane/src/application/services/pr-monitor-service.ts +33 -14
  94. package/apps/control-plane/src/application/services/qa-index-service.ts +20 -16
  95. package/apps/control-plane/src/application/services/reactions-service.ts +30 -15
  96. package/apps/control-plane/src/application/services/reporting-service.ts +16 -12
  97. package/apps/control-plane/src/application/services/run-lease-service.ts +138 -81
  98. package/apps/control-plane/src/application/tools/tool-metadata.ts +5 -5
  99. package/apps/control-plane/src/application/tools/tool-router.ts +6 -3
  100. package/apps/control-plane/src/cli/aop.ts +2 -2
  101. package/apps/control-plane/src/cli/attach-command-handler.ts +9 -9
  102. package/apps/control-plane/src/cli/cleanup-command-handler.ts +16 -11
  103. package/apps/control-plane/src/cli/cli-argument-parser.ts +6 -3
  104. package/apps/control-plane/src/cli/dashboard-command-handler.ts +28 -8
  105. package/apps/control-plane/src/cli/delete-command-handler.ts +7 -7
  106. package/apps/control-plane/src/cli/env-file.ts +115 -0
  107. package/apps/control-plane/src/cli/help-command-handler.ts +61 -32
  108. package/apps/control-plane/src/cli/init-command-handler.ts +182 -56
  109. package/apps/control-plane/src/cli/io.ts +7 -3
  110. package/apps/control-plane/src/cli/resume-command-handler.ts +21 -13
  111. package/apps/control-plane/src/cli/retry-command-handler.ts +12 -11
  112. package/apps/control-plane/src/cli/run-command-handler.ts +12 -8
  113. package/apps/control-plane/src/cli/send-command-handler.ts +6 -6
  114. package/apps/control-plane/src/cli/spec-ingestion-service.ts +14 -8
  115. package/apps/control-plane/src/cli/spec-input-resolver.ts +6 -1
  116. package/apps/control-plane/src/cli/spec-utils.ts +2 -2
  117. package/apps/control-plane/src/cli/status-command-handler.ts +13 -12
  118. package/apps/control-plane/src/cli/tooling.ts +3 -3
  119. package/apps/control-plane/src/cli/types.ts +1 -1
  120. package/apps/control-plane/src/core/collisions.ts +27 -10
  121. package/apps/control-plane/src/core/constants.ts +13 -7
  122. package/apps/control-plane/src/core/error-codes.ts +1 -1
  123. package/apps/control-plane/src/core/fs.ts +11 -5
  124. package/apps/control-plane/src/core/gates.ts +53 -27
  125. package/apps/control-plane/src/core/git.ts +18 -6
  126. package/apps/control-plane/src/core/kernel.ts +513 -227
  127. package/apps/control-plane/src/core/patch.ts +7 -3
  128. package/apps/control-plane/src/core/path-layout.ts +5 -1
  129. package/apps/control-plane/src/core/path-rules.ts +19 -5
  130. package/apps/control-plane/src/core/qa-index.ts +26 -12
  131. package/apps/control-plane/src/core/response.ts +9 -6
  132. package/apps/control-plane/src/core/schemas.ts +29 -10
  133. package/apps/control-plane/src/core/tool-caller.ts +1 -1
  134. package/apps/control-plane/src/core/workspace-hooks.ts +5 -5
  135. package/apps/control-plane/src/index.ts +3 -9
  136. package/apps/control-plane/src/interfaces/cli/bootstrap.ts +79 -35
  137. package/apps/control-plane/src/mcp/kernel-tool-executor.ts +7 -3
  138. package/apps/control-plane/src/mcp/mcp-server-adapter.ts +12 -10
  139. package/apps/control-plane/src/mcp/operation-ledger.ts +18 -8
  140. package/apps/control-plane/src/mcp/protocol-contract.ts +2 -2
  141. package/apps/control-plane/src/mcp/runtime-factory.ts +15 -6
  142. package/apps/control-plane/src/mcp/token-auth-verifier.ts +3 -2
  143. package/apps/control-plane/src/mcp/token-claims-validator.ts +11 -7
  144. package/apps/control-plane/src/mcp/tool-authorizer.ts +1 -3
  145. package/apps/control-plane/src/mcp/tool-client.ts +17 -5
  146. package/apps/control-plane/src/mcp/tool-contract-validator.ts +17 -8
  147. package/apps/control-plane/src/mcp/tool-registry-loader.ts +7 -3
  148. package/apps/control-plane/src/mcp/tool-runtime.ts +66 -39
  149. package/apps/control-plane/src/mcp/tools-markdown-generator.ts +6 -1
  150. package/apps/control-plane/src/providers/providers.ts +137 -54
  151. package/apps/control-plane/src/supervisor/build-wave-executor.ts +44 -25
  152. package/apps/control-plane/src/supervisor/planning-wave-executor.ts +46 -33
  153. package/apps/control-plane/src/supervisor/prompt-bundle-loader.ts +1 -1
  154. package/apps/control-plane/src/supervisor/qa-wave-executor.ts +38 -23
  155. package/apps/control-plane/src/supervisor/run-coordinator.ts +71 -36
  156. package/apps/control-plane/src/supervisor/runtime.ts +59 -35
  157. package/apps/control-plane/src/supervisor/session-orchestrator.ts +48 -31
  158. package/apps/control-plane/src/supervisor/types.ts +22 -7
  159. package/apps/control-plane/src/supervisor/worker-decision-loop.ts +30 -20
  160. package/apps/control-plane/test/activity-monitor.spec.ts +54 -30
  161. package/apps/control-plane/test/adapter-registry.spec.ts +5 -5
  162. package/apps/control-plane/test/aop.spec.ts +4 -4
  163. package/apps/control-plane/test/batch-operations.spec.ts +20 -18
  164. package/apps/control-plane/test/bootstrap-attach.spec.ts +52 -19
  165. package/apps/control-plane/test/bootstrap-edge-cases.spec.ts +58 -27
  166. package/apps/control-plane/test/bootstrap.spec.ts +72 -40
  167. package/apps/control-plane/test/cleanup-command.spec.ts +86 -32
  168. package/apps/control-plane/test/cli-helpers.spec.ts +119 -66
  169. package/apps/control-plane/test/cli.spec.ts +1 -1
  170. package/apps/control-plane/test/cli.unit.spec.ts +226 -167
  171. package/apps/control-plane/test/collision-queue.spec.ts +49 -40
  172. package/apps/control-plane/test/collisions.spec.ts +30 -30
  173. package/apps/control-plane/test/core-utils.spec.ts +29 -15
  174. package/apps/control-plane/test/cost-tracking.spec.ts +38 -22
  175. package/apps/control-plane/test/dashboard-api.integration.spec.ts +68 -36
  176. package/apps/control-plane/test/dashboard-client.spec.ts +18 -12
  177. package/apps/control-plane/test/dashboard-command.spec.ts +11 -7
  178. package/apps/control-plane/test/delete-command-handler.spec.ts +49 -41
  179. package/apps/control-plane/test/dependency-scheduler.spec.ts +47 -20
  180. package/apps/control-plane/test/epoch-tracking.spec.ts +9 -9
  181. package/apps/control-plane/test/feature-deletion-service.spec.ts +60 -52
  182. package/apps/control-plane/test/feature-lifecycle.spec.ts +36 -17
  183. package/apps/control-plane/test/gates.spec.ts +101 -81
  184. package/apps/control-plane/test/git-spawn-error.spec.ts +1 -1
  185. package/apps/control-plane/test/helpers.ts +10 -6
  186. package/apps/control-plane/test/incremental-gates.spec.ts +59 -20
  187. package/apps/control-plane/test/init-wizard.spec.ts +328 -68
  188. package/apps/control-plane/test/instance-isolation.spec.ts +43 -10
  189. package/apps/control-plane/test/issue-tracker.spec.ts +368 -128
  190. package/apps/control-plane/test/kernel-collision-replay.spec.ts +50 -29
  191. package/apps/control-plane/test/kernel.branches.spec.ts +64 -40
  192. package/apps/control-plane/test/kernel.coverage.spec.ts +85 -49
  193. package/apps/control-plane/test/kernel.coverage2.spec.ts +109 -65
  194. package/apps/control-plane/test/kernel.spec.ts +134 -51
  195. package/apps/control-plane/test/lock-service.spec.ts +92 -68
  196. package/apps/control-plane/test/mcp-helpers.spec.ts +53 -39
  197. package/apps/control-plane/test/mcp.spec.ts +231 -115
  198. package/apps/control-plane/test/merge-service.spec.ts +142 -94
  199. package/apps/control-plane/test/multi-project.spec.ts +28 -22
  200. package/apps/control-plane/test/notifier-service.spec.ts +136 -92
  201. package/apps/control-plane/test/parallel-gates.spec.ts +51 -35
  202. package/apps/control-plane/test/patch-service.spec.ts +128 -48
  203. package/apps/control-plane/test/performance-analytics.spec.ts +99 -63
  204. package/apps/control-plane/test/plan-service.spec.ts +50 -39
  205. package/apps/control-plane/test/planning-wave-executor.spec.ts +95 -71
  206. package/apps/control-plane/test/policy-loader-service.spec.ts +41 -19
  207. package/apps/control-plane/test/pr-monitor.spec.ts +113 -64
  208. package/apps/control-plane/test/providers.spec.ts +208 -104
  209. package/apps/control-plane/test/qa-index-service.spec.ts +31 -33
  210. package/apps/control-plane/test/qa-index.spec.ts +58 -61
  211. package/apps/control-plane/test/reactions.spec.ts +88 -45
  212. package/apps/control-plane/test/response.spec.ts +5 -5
  213. package/apps/control-plane/test/resume-command.spec.ts +121 -80
  214. package/apps/control-plane/test/run-coordinator.spec.ts +205 -136
  215. package/apps/control-plane/test/schema-date-time.spec.ts +49 -41
  216. package/apps/control-plane/test/service-retry-paths.spec.ts +77 -57
  217. package/apps/control-plane/test/services.spec.ts +147 -129
  218. package/apps/control-plane/test/session-management.spec.ts +136 -74
  219. package/apps/control-plane/test/spec-ingestion.spec.ts +23 -21
  220. package/apps/control-plane/test/spec-input-resolver.spec.ts +11 -10
  221. package/apps/control-plane/test/supervisor-collaborators.spec.ts +168 -121
  222. package/apps/control-plane/test/supervisor.calltool.spec.ts +21 -18
  223. package/apps/control-plane/test/supervisor.spec.ts +67 -43
  224. package/apps/control-plane/test/supervisor.unit.spec.ts +195 -126
  225. package/apps/control-plane/test/token-auth-verifier.spec.ts +29 -14
  226. package/apps/control-plane/test/tool-registry-loader.spec.ts +51 -27
  227. package/apps/control-plane/test/tool-runtime.spec.ts +63 -46
  228. package/apps/control-plane/test/worker-decision-loop.spec.ts +143 -122
  229. package/apps/control-plane/test/workspace-hooks.spec.ts +61 -23
  230. package/apps/control-plane/tsconfig.build.json +2 -7
  231. package/apps/control-plane/tsconfig.json +1 -5
  232. package/apps/control-plane/vitest.config.ts +7 -7
  233. package/config/agentic/orchestrator/adapters.yaml +3 -0
  234. package/config/agentic/orchestrator/agents.yaml +14 -0
  235. package/config/agentic/orchestrator/gates.yaml +28 -0
  236. package/config/agentic/orchestrator/policy.yaml +22 -0
  237. package/config/agentic/orchestrator/prompts/builder.system.md +1 -0
  238. package/config/agentic/orchestrator/prompts/planner.system.md +16 -0
  239. package/config/agentic/orchestrator/prompts/qa.system.md +1 -0
  240. package/dist/apps/control-plane/application/adapters/adapter-registry.js +12 -5
  241. package/dist/apps/control-plane/application/adapters/adapter-registry.js.map +1 -1
  242. package/dist/apps/control-plane/application/multi-project-loader.js +26 -9
  243. package/dist/apps/control-plane/application/multi-project-loader.js.map +1 -1
  244. package/dist/apps/control-plane/application/services/activity-monitor-service.js +7 -7
  245. package/dist/apps/control-plane/application/services/activity-monitor-service.js.map +1 -1
  246. package/dist/apps/control-plane/application/services/collision-queue-service.js +7 -7
  247. package/dist/apps/control-plane/application/services/collision-queue-service.js.map +1 -1
  248. package/dist/apps/control-plane/application/services/cost-tracking-service.js +6 -8
  249. package/dist/apps/control-plane/application/services/cost-tracking-service.js.map +1 -1
  250. package/dist/apps/control-plane/application/services/dependency-scheduler-service.js.map +1 -1
  251. package/dist/apps/control-plane/application/services/feature-deletion-service.js +37 -29
  252. package/dist/apps/control-plane/application/services/feature-deletion-service.js.map +1 -1
  253. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js +10 -10
  254. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js.map +1 -1
  255. package/dist/apps/control-plane/application/services/feature-state-service.js +11 -11
  256. package/dist/apps/control-plane/application/services/feature-state-service.js.map +1 -1
  257. package/dist/apps/control-plane/application/services/gate-interpolation-service.js +3 -1
  258. package/dist/apps/control-plane/application/services/gate-interpolation-service.js.map +1 -1
  259. package/dist/apps/control-plane/application/services/gate-service.js +26 -26
  260. package/dist/apps/control-plane/application/services/gate-service.js.map +1 -1
  261. package/dist/apps/control-plane/application/services/instance-isolation-service.js +1 -1
  262. package/dist/apps/control-plane/application/services/instance-isolation-service.js.map +1 -1
  263. package/dist/apps/control-plane/application/services/issue-tracker-service.js +25 -15
  264. package/dist/apps/control-plane/application/services/issue-tracker-service.js.map +1 -1
  265. package/dist/apps/control-plane/application/services/lock-service.js +32 -32
  266. package/dist/apps/control-plane/application/services/lock-service.js.map +1 -1
  267. package/dist/apps/control-plane/application/services/merge-service.js +41 -27
  268. package/dist/apps/control-plane/application/services/merge-service.js.map +1 -1
  269. package/dist/apps/control-plane/application/services/notifier-service.js +29 -15
  270. package/dist/apps/control-plane/application/services/notifier-service.js.map +1 -1
  271. package/dist/apps/control-plane/application/services/patch-service.js +21 -19
  272. package/dist/apps/control-plane/application/services/patch-service.js.map +1 -1
  273. package/dist/apps/control-plane/application/services/performance-analytics-service.js +4 -4
  274. package/dist/apps/control-plane/application/services/performance-analytics-service.js.map +1 -1
  275. package/dist/apps/control-plane/application/services/plan-service.js +33 -33
  276. package/dist/apps/control-plane/application/services/plan-service.js.map +1 -1
  277. package/dist/apps/control-plane/application/services/policy-loader-service.js.map +1 -1
  278. package/dist/apps/control-plane/application/services/pr-monitor-service.js +23 -11
  279. package/dist/apps/control-plane/application/services/pr-monitor-service.js.map +1 -1
  280. package/dist/apps/control-plane/application/services/qa-index-service.js +11 -11
  281. package/dist/apps/control-plane/application/services/qa-index-service.js.map +1 -1
  282. package/dist/apps/control-plane/application/services/reactions-service.js +13 -9
  283. package/dist/apps/control-plane/application/services/reactions-service.js.map +1 -1
  284. package/dist/apps/control-plane/application/services/reporting-service.js +11 -9
  285. package/dist/apps/control-plane/application/services/reporting-service.js.map +1 -1
  286. package/dist/apps/control-plane/application/services/run-lease-service.js +34 -33
  287. package/dist/apps/control-plane/application/services/run-lease-service.js.map +1 -1
  288. package/dist/apps/control-plane/application/tools/tool-metadata.js +2 -2
  289. package/dist/apps/control-plane/application/tools/tool-router.js.map +1 -1
  290. package/dist/apps/control-plane/cli/attach-command-handler.js +9 -9
  291. package/dist/apps/control-plane/cli/cleanup-command-handler.js +11 -9
  292. package/dist/apps/control-plane/cli/cleanup-command-handler.js.map +1 -1
  293. package/dist/apps/control-plane/cli/cli-argument-parser.js +4 -3
  294. package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
  295. package/dist/apps/control-plane/cli/dashboard-command-handler.js +23 -7
  296. package/dist/apps/control-plane/cli/dashboard-command-handler.js.map +1 -1
  297. package/dist/apps/control-plane/cli/delete-command-handler.js +7 -7
  298. package/dist/apps/control-plane/cli/env-file.d.ts +4 -0
  299. package/dist/apps/control-plane/cli/env-file.js +89 -0
  300. package/dist/apps/control-plane/cli/env-file.js.map +1 -0
  301. package/dist/apps/control-plane/cli/help-command-handler.js +58 -30
  302. package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
  303. package/dist/apps/control-plane/cli/init-command-handler.js +97 -37
  304. package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
  305. package/dist/apps/control-plane/cli/io.js +2 -2
  306. package/dist/apps/control-plane/cli/io.js.map +1 -1
  307. package/dist/apps/control-plane/cli/resume-command-handler.js +9 -9
  308. package/dist/apps/control-plane/cli/resume-command-handler.js.map +1 -1
  309. package/dist/apps/control-plane/cli/retry-command-handler.js +12 -11
  310. package/dist/apps/control-plane/cli/retry-command-handler.js.map +1 -1
  311. package/dist/apps/control-plane/cli/run-command-handler.js +12 -8
  312. package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -1
  313. package/dist/apps/control-plane/cli/send-command-handler.js +6 -6
  314. package/dist/apps/control-plane/cli/spec-ingestion-service.js +10 -8
  315. package/dist/apps/control-plane/cli/spec-ingestion-service.js.map +1 -1
  316. package/dist/apps/control-plane/cli/spec-input-resolver.js.map +1 -1
  317. package/dist/apps/control-plane/cli/spec-utils.js.map +1 -1
  318. package/dist/apps/control-plane/cli/status-command-handler.js +8 -8
  319. package/dist/apps/control-plane/cli/status-command-handler.js.map +1 -1
  320. package/dist/apps/control-plane/cli/tooling.js +1 -1
  321. package/dist/apps/control-plane/core/collisions.js +11 -8
  322. package/dist/apps/control-plane/core/collisions.js.map +1 -1
  323. package/dist/apps/control-plane/core/constants.js +13 -7
  324. package/dist/apps/control-plane/core/constants.js.map +1 -1
  325. package/dist/apps/control-plane/core/error-codes.js +1 -1
  326. package/dist/apps/control-plane/core/fs.js.map +1 -1
  327. package/dist/apps/control-plane/core/gates.d.ts +2 -2
  328. package/dist/apps/control-plane/core/gates.js +26 -19
  329. package/dist/apps/control-plane/core/gates.js.map +1 -1
  330. package/dist/apps/control-plane/core/git.js +3 -3
  331. package/dist/apps/control-plane/core/git.js.map +1 -1
  332. package/dist/apps/control-plane/core/kernel.d.ts +1 -0
  333. package/dist/apps/control-plane/core/kernel.js +134 -81
  334. package/dist/apps/control-plane/core/kernel.js.map +1 -1
  335. package/dist/apps/control-plane/core/patch.js +7 -3
  336. package/dist/apps/control-plane/core/patch.js.map +1 -1
  337. package/dist/apps/control-plane/core/path-layout.d.ts +1 -0
  338. package/dist/apps/control-plane/core/path-layout.js +4 -1
  339. package/dist/apps/control-plane/core/path-layout.js.map +1 -1
  340. package/dist/apps/control-plane/core/path-rules.js +3 -1
  341. package/dist/apps/control-plane/core/path-rules.js.map +1 -1
  342. package/dist/apps/control-plane/core/qa-index.js +5 -5
  343. package/dist/apps/control-plane/core/qa-index.js.map +1 -1
  344. package/dist/apps/control-plane/core/response.js +3 -3
  345. package/dist/apps/control-plane/core/response.js.map +1 -1
  346. package/dist/apps/control-plane/core/schemas.js +10 -6
  347. package/dist/apps/control-plane/core/schemas.js.map +1 -1
  348. package/dist/apps/control-plane/core/workspace-hooks.js +3 -3
  349. package/dist/apps/control-plane/index.d.ts +1 -1
  350. package/dist/apps/control-plane/index.js +1 -1
  351. package/dist/apps/control-plane/index.js.map +1 -1
  352. package/dist/apps/control-plane/interfaces/cli/bootstrap.js +40 -23
  353. package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
  354. package/dist/apps/control-plane/mcp/kernel-tool-executor.js +1 -1
  355. package/dist/apps/control-plane/mcp/kernel-tool-executor.js.map +1 -1
  356. package/dist/apps/control-plane/mcp/mcp-server-adapter.js +6 -7
  357. package/dist/apps/control-plane/mcp/mcp-server-adapter.js.map +1 -1
  358. package/dist/apps/control-plane/mcp/operation-ledger.js +5 -5
  359. package/dist/apps/control-plane/mcp/operation-ledger.js.map +1 -1
  360. package/dist/apps/control-plane/mcp/protocol-contract.js +2 -2
  361. package/dist/apps/control-plane/mcp/runtime-factory.js +2 -2
  362. package/dist/apps/control-plane/mcp/runtime-factory.js.map +1 -1
  363. package/dist/apps/control-plane/mcp/token-auth-verifier.js +1 -1
  364. package/dist/apps/control-plane/mcp/token-auth-verifier.js.map +1 -1
  365. package/dist/apps/control-plane/mcp/token-claims-validator.js +5 -5
  366. package/dist/apps/control-plane/mcp/token-claims-validator.js.map +1 -1
  367. package/dist/apps/control-plane/mcp/tool-authorizer.js +1 -3
  368. package/dist/apps/control-plane/mcp/tool-authorizer.js.map +1 -1
  369. package/dist/apps/control-plane/mcp/tool-client.js +2 -2
  370. package/dist/apps/control-plane/mcp/tool-client.js.map +1 -1
  371. package/dist/apps/control-plane/mcp/tool-contract-validator.js +3 -3
  372. package/dist/apps/control-plane/mcp/tool-contract-validator.js.map +1 -1
  373. package/dist/apps/control-plane/mcp/tool-registry-loader.js +1 -1
  374. package/dist/apps/control-plane/mcp/tool-registry-loader.js.map +1 -1
  375. package/dist/apps/control-plane/mcp/tool-runtime.js +17 -17
  376. package/dist/apps/control-plane/mcp/tool-runtime.js.map +1 -1
  377. package/dist/apps/control-plane/mcp/tools-markdown-generator.js +6 -1
  378. package/dist/apps/control-plane/mcp/tools-markdown-generator.js.map +1 -1
  379. package/dist/apps/control-plane/providers/providers.d.ts +3 -2
  380. package/dist/apps/control-plane/providers/providers.js +81 -39
  381. package/dist/apps/control-plane/providers/providers.js.map +1 -1
  382. package/dist/apps/control-plane/supervisor/build-wave-executor.js +12 -12
  383. package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
  384. package/dist/apps/control-plane/supervisor/planning-wave-executor.js +19 -16
  385. package/dist/apps/control-plane/supervisor/planning-wave-executor.js.map +1 -1
  386. package/dist/apps/control-plane/supervisor/prompt-bundle-loader.js +1 -1
  387. package/dist/apps/control-plane/supervisor/qa-wave-executor.js +13 -13
  388. package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
  389. package/dist/apps/control-plane/supervisor/run-coordinator.js +37 -20
  390. package/dist/apps/control-plane/supervisor/run-coordinator.js.map +1 -1
  391. package/dist/apps/control-plane/supervisor/runtime.js +25 -21
  392. package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
  393. package/dist/apps/control-plane/supervisor/session-orchestrator.js +29 -23
  394. package/dist/apps/control-plane/supervisor/session-orchestrator.js.map +1 -1
  395. package/dist/apps/control-plane/supervisor/types.d.ts +3 -3
  396. package/dist/apps/control-plane/supervisor/types.js.map +1 -1
  397. package/dist/apps/control-plane/supervisor/worker-decision-loop.js +14 -16
  398. package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -1
  399. package/eslint.config.mjs +20 -20
  400. package/example-configurations/README.md +1 -1
  401. package/example-configurations/java/agents.yaml +3 -3
  402. package/example-configurations/java/policy.yaml +1 -1
  403. package/example-configurations/node/agents.yaml +3 -3
  404. package/example-configurations/node/policy.yaml +1 -1
  405. package/package.json +10 -5
  406. package/packages/web-dashboard/next.config.js +2 -2
  407. package/packages/web-dashboard/src/app/api/actions/route.ts +25 -9
  408. package/packages/web-dashboard/src/app/api/events/route.ts +20 -6
  409. package/packages/web-dashboard/src/app/api/features/[id]/checkout/route.ts +88 -37
  410. package/packages/web-dashboard/src/app/api/features/[id]/evidence/[artifact]/route.ts +8 -5
  411. package/packages/web-dashboard/src/app/api/features/[id]/review/route.ts +27 -9
  412. package/packages/web-dashboard/src/app/api/features/[id]/route.ts +5 -2
  413. package/packages/web-dashboard/src/app/api/projects/route.ts +5 -5
  414. package/packages/web-dashboard/src/app/globals.css +10 -2
  415. package/packages/web-dashboard/src/app/page.tsx +100 -37
  416. package/packages/web-dashboard/src/lib/aop-client.ts +68 -37
  417. package/packages/web-dashboard/src/lib/multi-project-config.ts +28 -7
  418. package/packages/web-dashboard/src/lib/orchestrator-tools.ts +59 -36
  419. package/packages/web-dashboard/tsconfig.json +3 -11
  420. package/scripts/nx-safe.mjs +10 -10
  421. package/spec-files/completed/agentic_orchestrator_cli_delete_command_spec.md +5 -0
  422. package/spec-files/completed/agentic_orchestrator_feature_gaps_closure_spec.md +189 -90
  423. package/spec-files/completed/agentic_orchestrator_init_policy_ux_simplification_spec.md +49 -16
  424. package/spec-files/completed/agentic_orchestrator_mcp_formalization_spec.md +24 -1
  425. package/spec-files/completed/agentic_orchestrator_single_global_orchestrator_spec.md +9 -0
  426. package/spec-files/completed/agentic_orchestrator_spec.md +171 -75
  427. package/spec-files/completed/agentic_orchestrator_validator_hardening_spec.md +25 -17
  428. package/spec-files/outstanding/agentic_orchestrator_artifact_database_publishing_spec.md +40 -5
  429. package/spec-files/outstanding/agentic_orchestrator_enterprise_governance_dashboard_spec.md +23 -12
  430. package/spec-files/outstanding/agentic_orchestrator_knowledge_canary_spec.md +16 -4
  431. package/spec-files/outstanding/agentic_orchestrator_observability_integrity_diagnostics_spec.md +42 -2
  432. package/spec-files/outstanding/agentic_orchestrator_performance_improvements_spec.md +209 -130
  433. package/spec-files/outstanding/agentic_orchestrator_planning_review_quality_spec.md +56 -3
  434. package/spec-files/outstanding/agentic_orchestrator_productization_commercial_spec.md +77 -10
  435. package/spec-files/outstanding/agentic_orchestrator_provider_auth_bootstrap_spec.md +384 -0
  436. package/spec-files/outstanding/agentic_orchestrator_quality_adoption_execution_spec.md +29 -14
  437. package/spec-files/progress.md +186 -175
  438. package/tsconfig.json +2 -8
@@ -3,7 +3,7 @@ import {
3
3
  GitHubIssueTracker,
4
4
  LinearIssueTracker,
5
5
  JiraIssueTracker,
6
- createIssueTracker
6
+ createIssueTracker,
7
7
  } from '../src/application/services/issue-tracker-service.js';
8
8
  import type { GhRunner, HttpRunner } from '../src/application/services/issue-tracker-service.js';
9
9
 
@@ -12,7 +12,7 @@ function makeGhRunner(stdout: string, exitCode = 0): GhRunner {
12
12
  }
13
13
 
14
14
  function makeHttpRunner(
15
- responses: Array<{ status?: number; ok?: boolean; body?: unknown }>
15
+ responses: Array<{ status?: number; ok?: boolean; body?: unknown }>,
16
16
  ): HttpRunner & ReturnType<typeof vi.fn> {
17
17
  const queue = [...responses];
18
18
  const runner = vi.fn(async () => {
@@ -26,7 +26,7 @@ function makeHttpRunner(
26
26
  return {
27
27
  status: next.status ?? 200,
28
28
  ok: next.ok ?? true,
29
- body
29
+ body,
30
30
  };
31
31
  });
32
32
  return runner as HttpRunner & ReturnType<typeof vi.fn>;
@@ -40,7 +40,7 @@ describe('G9: Multi-Tracker Support', () => {
40
40
  title: 'Add dark mode',
41
41
  body: 'Users want dark mode.',
42
42
  state: 'OPEN',
43
- url: 'https://github.com/org/repo/issues/42'
43
+ url: 'https://github.com/org/repo/issues/42',
44
44
  });
45
45
  const runner = makeGhRunner(payload);
46
46
  const tracker = new GitHubIssueTracker({ repo: 'org/repo' }, runner);
@@ -69,9 +69,11 @@ describe('G9: Multi-Tracker Support', () => {
69
69
  await tracker.updateIssueStatus('42', 'merged');
70
70
  await tracker.addComment('42', 'AOP: status -> merged');
71
71
 
72
- expect(runner).toHaveBeenCalledWith(expect.arrayContaining(['issue', 'edit', '42', '--state', 'closed']));
73
72
  expect(runner).toHaveBeenCalledWith(
74
- expect.arrayContaining(['issue', 'comment', '42', '--body', 'AOP: status -> merged'])
73
+ expect.arrayContaining(['issue', 'edit', '42', '--state', 'closed']),
74
+ );
75
+ expect(runner).toHaveBeenCalledWith(
76
+ expect.arrayContaining(['issue', 'comment', '42', '--body', 'AOP: status -> merged']),
75
77
  );
76
78
  });
77
79
 
@@ -95,18 +97,18 @@ describe('G9: Multi-Tracker Support', () => {
95
97
  title: 'Ship feature flag',
96
98
  description: 'Implement rollout toggle',
97
99
  url: 'https://linear.app/acme/issue/LIN-123',
98
- state: { name: 'In Progress' }
99
- }
100
- }
101
- }
102
- }
100
+ state: { name: 'In Progress' },
101
+ },
102
+ },
103
+ },
104
+ },
103
105
  ]);
104
106
  const tracker = new LinearIssueTracker(
105
107
  {
106
108
  token: 'linear-token',
107
- base_url: 'https://api.linear.app/graphql'
109
+ base_url: 'https://api.linear.app/graphql',
108
110
  },
109
- httpRunner
111
+ httpRunner,
110
112
  );
111
113
 
112
114
  const issue = await tracker.getIssue('LIN-123');
@@ -116,7 +118,7 @@ describe('G9: Multi-Tracker Support', () => {
116
118
  title: 'Ship feature flag',
117
119
  body: 'Implement rollout toggle',
118
120
  status: 'in progress',
119
- url: 'https://linear.app/acme/issue/LIN-123'
121
+ url: 'https://linear.app/acme/issue/LIN-123',
120
122
  });
121
123
  expect(httpRunner).toHaveBeenCalledTimes(1);
122
124
  expect(httpRunner).toHaveBeenCalledWith(
@@ -124,9 +126,9 @@ describe('G9: Multi-Tracker Support', () => {
124
126
  expect.objectContaining({
125
127
  method: 'POST',
126
128
  headers: expect.objectContaining({
127
- Authorization: 'Bearer linear-token'
128
- })
129
- })
129
+ Authorization: 'Bearer linear-token',
130
+ }),
131
+ }),
130
132
  );
131
133
  });
132
134
 
@@ -141,26 +143,26 @@ describe('G9: Multi-Tracker Support', () => {
141
143
  title: 'Refactor queue',
142
144
  description: '',
143
145
  url: 'https://linear.app/acme/issue/LIN-200',
144
- state: { name: 'Todo' }
145
- }
146
- }
147
- }
146
+ state: { name: 'Todo' },
147
+ },
148
+ },
149
+ },
148
150
  },
149
151
  {
150
152
  body: {
151
153
  data: {
152
154
  issueUpdate: {
153
- success: true
154
- }
155
- }
156
- }
157
- }
155
+ success: true,
156
+ },
157
+ },
158
+ },
159
+ },
158
160
  ]);
159
161
  const tracker = new LinearIssueTracker(
160
162
  {
161
- state_id_building: 'state_in_progress'
163
+ state_id_building: 'state_in_progress',
162
164
  },
163
- httpRunner
165
+ httpRunner,
164
166
  );
165
167
 
166
168
  await tracker.updateIssueStatus('LIN-200', 'building');
@@ -170,7 +172,7 @@ describe('G9: Multi-Tracker Support', () => {
170
172
  expect(secondCallBody.query).toContain('issueUpdate');
171
173
  expect(secondCallBody.variables).toMatchObject({
172
174
  id: 'lin_uuid_2',
173
- stateId: 'state_in_progress'
175
+ stateId: 'state_in_progress',
174
176
  });
175
177
  });
176
178
 
@@ -185,20 +187,20 @@ describe('G9: Multi-Tracker Support', () => {
185
187
  title: 'Fix race condition',
186
188
  description: '',
187
189
  url: 'https://linear.app/acme/issue/LIN-300',
188
- state: { name: 'Todo' }
189
- }
190
- }
191
- }
190
+ state: { name: 'Todo' },
191
+ },
192
+ },
193
+ },
192
194
  },
193
195
  {
194
196
  body: {
195
197
  data: {
196
198
  commentCreate: {
197
- success: true
198
- }
199
- }
200
- }
201
- }
199
+ success: true,
200
+ },
201
+ },
202
+ },
203
+ },
202
204
  ]);
203
205
  const tracker = new LinearIssueTracker({}, httpRunner);
204
206
 
@@ -209,7 +211,7 @@ describe('G9: Multi-Tracker Support', () => {
209
211
  expect(secondCallBody.query).toContain('commentCreate');
210
212
  expect(secondCallBody.variables).toMatchObject({
211
213
  issueId: 'lin_uuid_3',
212
- body: 'AOP: feature status changed to `qa`'
214
+ body: 'AOP: feature status changed to `qa`',
213
215
  });
214
216
  });
215
217
 
@@ -223,7 +225,7 @@ describe('G9: Multi-Tracker Support', () => {
223
225
  title: '',
224
226
  body: '',
225
227
  status: 'unknown',
226
- url: ''
228
+ url: '',
227
229
  });
228
230
  });
229
231
  });
@@ -237,18 +239,18 @@ describe('G9: Multi-Tracker Support', () => {
237
239
  fields: {
238
240
  summary: 'Fix flaky pipeline',
239
241
  description: 'Investigate and stabilize',
240
- status: { name: 'In Progress' }
241
- }
242
- }
243
- }
242
+ status: { name: 'In Progress' },
243
+ },
244
+ },
245
+ },
244
246
  ]);
245
247
  const tracker = new JiraIssueTracker(
246
248
  {
247
249
  base_url: 'https://jira.example.com',
248
250
  email: 'dev@example.com',
249
- token: 'jira-token'
251
+ token: 'jira-token',
250
252
  },
251
- httpRunner
253
+ httpRunner,
252
254
  );
253
255
 
254
256
  const issue = await tracker.getIssue('PROJ-42');
@@ -257,16 +259,16 @@ describe('G9: Multi-Tracker Support', () => {
257
259
  title: 'Fix flaky pipeline',
258
260
  body: 'Investigate and stabilize',
259
261
  status: 'in progress',
260
- url: 'https://jira.example.com/browse/PROJ-42'
262
+ url: 'https://jira.example.com/browse/PROJ-42',
261
263
  });
262
264
  expect(httpRunner).toHaveBeenCalledWith(
263
265
  'https://jira.example.com/rest/api/2/issue/PROJ-42?fields=summary,description,status',
264
266
  expect.objectContaining({
265
267
  method: 'GET',
266
268
  headers: expect.objectContaining({
267
- Authorization: expect.stringContaining('Basic ')
268
- })
269
- })
269
+ Authorization: expect.stringContaining('Basic '),
270
+ }),
271
+ }),
270
272
  );
271
273
  });
272
274
 
@@ -277,20 +279,20 @@ describe('G9: Multi-Tracker Support', () => {
277
279
  transitions: [
278
280
  { id: '11', name: 'To Do' },
279
281
  { id: '22', name: 'In Progress' },
280
- { id: '33', name: 'Done' }
281
- ]
282
- }
282
+ { id: '33', name: 'Done' },
283
+ ],
284
+ },
283
285
  },
284
286
  {
285
- body: {}
286
- }
287
+ body: {},
288
+ },
287
289
  ]);
288
290
  const tracker = new JiraIssueTracker(
289
291
  {
290
292
  base_url: 'https://jira.example.com',
291
- transition_building: 'In Progress'
293
+ transition_building: 'In Progress',
292
294
  },
293
- httpRunner
295
+ httpRunner,
294
296
  );
295
297
 
296
298
  await tracker.updateIssueStatus('PROJ-7', 'building');
@@ -301,8 +303,8 @@ describe('G9: Multi-Tracker Support', () => {
301
303
  'https://jira.example.com/rest/api/2/issue/PROJ-7/transitions',
302
304
  expect.objectContaining({
303
305
  method: 'POST',
304
- body: JSON.stringify({ transition: { id: '22' } })
305
- })
306
+ body: JSON.stringify({ transition: { id: '22' } }),
307
+ }),
306
308
  );
307
309
  });
308
310
 
@@ -316,8 +318,8 @@ describe('G9: Multi-Tracker Support', () => {
316
318
  'https://jira.example.com/rest/api/2/issue/PROJ-8/comment',
317
319
  expect.objectContaining({
318
320
  method: 'POST',
319
- body: JSON.stringify({ body: 'AOP: feature status changed to `merged`' })
320
- })
321
+ body: JSON.stringify({ body: 'AOP: feature status changed to `merged`' }),
322
+ }),
321
323
  );
322
324
  });
323
325
  });
@@ -345,7 +347,8 @@ describe('G9: Multi-Tracker Support', () => {
345
347
  describe('issue-tracker-service branch coverage', () => {
346
348
  describe('createGhRunner', () => {
347
349
  it('GIVEN_function_provided_WHEN_createGhRunner_called_THEN_returns_that_function', async () => {
348
- const { createGhRunner } = await import('../src/application/services/issue-tracker-service.js');
350
+ const { createGhRunner } =
351
+ await import('../src/application/services/issue-tracker-service.js');
349
352
  const custom = vi.fn(async () => ({ stdout: 'ok', exitCode: 0 }));
350
353
  const runner = createGhRunner(custom as GhRunner);
351
354
  expect(runner).toBe(custom);
@@ -375,8 +378,16 @@ describe('issue-tracker-service branch coverage', () => {
375
378
  const runner: HttpRunner = async (_url, init) => {
376
379
  const body = JSON.parse(init.body as string) as Record<string, unknown>;
377
380
  const vars = body['variables'] as Record<string, unknown> | undefined;
378
- calls.push([body['query'] as string, vars?.['issueId'] as string, vars?.['stateId'] as string]);
379
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueUpdate: { success: true } } }) };
381
+ calls.push([
382
+ body['query'] as string,
383
+ vars?.['issueId'] as string,
384
+ vars?.['stateId'] as string,
385
+ ]);
386
+ return {
387
+ status: 200,
388
+ ok: true,
389
+ body: JSON.stringify({ data: { issueUpdate: { success: true } } }),
390
+ };
380
391
  };
381
392
  const tracker = new LinearIssueTracker({ token: 'tok', state_blocked: 'state_b' }, runner);
382
393
  await tracker.updateIssueStatus('LIN-1', 'blocked');
@@ -384,7 +395,9 @@ describe('issue-tracker-service branch coverage', () => {
384
395
  });
385
396
 
386
397
  it('GIVEN_http_failure_WHEN_getIssue_called_THEN_returns_fallback_unknown', async () => {
387
- const runner: HttpRunner = async () => { throw new Error('network error'); };
398
+ const runner: HttpRunner = async () => {
399
+ throw new Error('network error');
400
+ };
388
401
  const tracker = new LinearIssueTracker({ token: 'tok' }, runner as never);
389
402
  const issue = await tracker.getIssue('LIN-999');
390
403
  expect(issue.id).toBe('LIN-999');
@@ -404,14 +417,19 @@ describe('issue-tracker-service branch coverage', () => {
404
417
  callCount += 1;
405
418
  if (url.includes('transitions') && (!init.method || init.method === 'GET')) {
406
419
  return {
407
- status: 200, ok: true, body: JSON.stringify({
408
- transitions: [{ id: 't1', name: 'To Do' }]
409
- })
420
+ status: 200,
421
+ ok: true,
422
+ body: JSON.stringify({
423
+ transitions: [{ id: 't1', name: 'To Do' }],
424
+ }),
410
425
  };
411
426
  }
412
427
  return runner(url, init);
413
428
  };
414
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'tok', email: 'me@example.com' }, mockRunner);
429
+ const tracker = new JiraIssueTracker(
430
+ { base_url: 'https://jira.example.com', token: 'tok', email: 'me@example.com' },
431
+ mockRunner,
432
+ );
415
433
  await tracker.updateIssueStatus('PROJ-1', 'planning');
416
434
  expect(callCount).toBeGreaterThan(0);
417
435
  });
@@ -422,7 +440,10 @@ describe('JiraIssueTracker additional branch coverage', () => {
422
440
  it('GIVEN_requestJson_returns_null_WHEN_getIssue_called_THEN_returns_fallback', async () => {
423
441
  // Return non-ok response → requestJson returns null
424
442
  const runner: HttpRunner = async () => ({ status: 404, ok: false, body: '' });
425
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'tok' }, runner);
443
+ const tracker = new JiraIssueTracker(
444
+ { base_url: 'https://jira.example.com', token: 'tok' },
445
+ runner,
446
+ );
426
447
  const issue = await tracker.getIssue('PROJ-999');
427
448
  expect(issue.id).toBe('PROJ-999');
428
449
  expect(issue.status).toBe('unknown');
@@ -434,10 +455,15 @@ describe('JiraIssueTracker additional branch coverage', () => {
434
455
  calls.push(`${String(init.method ?? 'GET')} ${url}`);
435
456
  // Only GET for transitions, no matching transition name
436
457
  return {
437
- status: 200, ok: true, body: JSON.stringify({ transitions: [{ id: 'x', name: 'To Do' }] })
458
+ status: 200,
459
+ ok: true,
460
+ body: JSON.stringify({ transitions: [{ id: 'x', name: 'To Do' }] }),
438
461
  };
439
462
  };
440
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'tok' }, runner);
463
+ const tracker = new JiraIssueTracker(
464
+ { base_url: 'https://jira.example.com', token: 'tok' },
465
+ runner,
466
+ );
441
467
  // 'building' maps to 'in progress' but transitions only have 'To Do'
442
468
  await tracker.updateIssueStatus('PROJ-1', 'building');
443
469
  // Only GET should have been called (no POST)
@@ -455,9 +481,19 @@ describe('JiraIssueTracker additional branch coverage', () => {
455
481
  let capturedAuth: string | undefined;
456
482
  const runner: HttpRunner = async (_, init) => {
457
483
  capturedAuth = (init.headers as Record<string, string>)?.['Authorization'];
458
- return { status: 200, ok: true, body: JSON.stringify({ key: 'PROJ-1', fields: { summary: 'Test', status: { name: 'Open' } } }) };
484
+ return {
485
+ status: 200,
486
+ ok: true,
487
+ body: JSON.stringify({
488
+ key: 'PROJ-1',
489
+ fields: { summary: 'Test', status: { name: 'Open' } },
490
+ }),
491
+ };
459
492
  };
460
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'mytoken' }, runner);
493
+ const tracker = new JiraIssueTracker(
494
+ { base_url: 'https://jira.example.com', token: 'mytoken' },
495
+ runner,
496
+ );
461
497
  await tracker.getIssue('PROJ-1');
462
498
  expect(capturedAuth).toBe('Bearer mytoken');
463
499
  });
@@ -471,10 +507,17 @@ describe('issue-tracker-service additional branch coverage', () => {
471
507
  ok: true,
472
508
  body: JSON.stringify({
473
509
  key: 'PROJ-1',
474
- fields: { summary: 'Test', description: { type: 'doc', content: [] }, status: { name: 'Open' } }
475
- })
510
+ fields: {
511
+ summary: 'Test',
512
+ description: { type: 'doc', content: [] },
513
+ status: { name: 'Open' },
514
+ },
515
+ }),
476
516
  });
477
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'tok' }, runner);
517
+ const tracker = new JiraIssueTracker(
518
+ { base_url: 'https://jira.example.com', token: 'tok' },
519
+ runner,
520
+ );
478
521
  // getIssue passes the description through toJiraDescription when calling addComment
479
522
  const issue = await tracker.getIssue('PROJ-1');
480
523
  // description field (object) should be stringified
@@ -489,7 +532,7 @@ describe('issue-tracker-service additional branch coverage', () => {
489
532
  return {
490
533
  status: 200,
491
534
  ok: true,
492
- body: JSON.stringify({ transitions: [{ id: '99', name: 'Custom Done' }] })
535
+ body: JSON.stringify({ transitions: [{ id: '99', name: 'Custom Done' }] }),
493
536
  };
494
537
  }
495
538
  return { status: 204, ok: true, body: '' };
@@ -497,7 +540,7 @@ describe('issue-tracker-service additional branch coverage', () => {
497
540
  // config has explicit transition for 'merged' → 'custom done'
498
541
  const tracker = new JiraIssueTracker(
499
542
  { base_url: 'https://jira.example.com', token: 'tok', transition_merged: 'custom done' },
500
- runner
543
+ runner,
501
544
  );
502
545
  await tracker.updateIssueStatus('PROJ-2', 'merged');
503
546
  // POST should have been called since 'custom done' matches 'Custom Done' (case-insensitive)
@@ -511,15 +554,34 @@ describe('issue-tracker-service additional branch coverage', () => {
511
554
  // First call: resolveIssueNode → return a valid issue
512
555
  if (bodies.length === 1) {
513
556
  return {
514
- status: 200, ok: true,
515
- body: JSON.stringify({ data: { issueByIdentifier: { id: 'lin-uuid-1', identifier: 'LIN-1', title: 'T', description: '', url: '', state: { name: 'Backlog' } } } })
557
+ status: 200,
558
+ ok: true,
559
+ body: JSON.stringify({
560
+ data: {
561
+ issueByIdentifier: {
562
+ id: 'lin-uuid-1',
563
+ identifier: 'LIN-1',
564
+ title: 'T',
565
+ description: '',
566
+ url: '',
567
+ state: { name: 'Backlog' },
568
+ },
569
+ },
570
+ }),
516
571
  };
517
572
  }
518
573
  // Second call: mutation
519
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueUpdate: { success: true } } }) };
574
+ return {
575
+ status: 200,
576
+ ok: true,
577
+ body: JSON.stringify({ data: { issueUpdate: { success: true } } }),
578
+ };
520
579
  };
521
580
  // Provide state_id_backlog so resolveStateId returns non-null → mutation is called
522
- const tracker = new LinearIssueTracker({ token: 'tok', state_id_backlog: 'state-backlog-id' }, runner);
581
+ const tracker = new LinearIssueTracker(
582
+ { token: 'tok', state_id_backlog: 'state-backlog-id' },
583
+ runner,
584
+ );
523
585
  await tracker.updateIssueStatus('LIN-1', 'planning');
524
586
  // mapDefaultLinearStatus('planning') → 'backlog' → state_id_backlog → mutation called
525
587
  expect(bodies.length).toBe(2);
@@ -532,14 +594,33 @@ describe('issue-tracker-service additional branch coverage', () => {
532
594
  bodies.push((init.body as string) ?? '');
533
595
  if (bodies.length === 1) {
534
596
  return {
535
- status: 200, ok: true,
536
- body: JSON.stringify({ data: { issueByIdentifier: { id: 'lin-uuid-2', identifier: 'LIN-2', title: 'T', description: '', url: '', state: { name: 'In Review' } } } })
597
+ status: 200,
598
+ ok: true,
599
+ body: JSON.stringify({
600
+ data: {
601
+ issueByIdentifier: {
602
+ id: 'lin-uuid-2',
603
+ identifier: 'LIN-2',
604
+ title: 'T',
605
+ description: '',
606
+ url: '',
607
+ state: { name: 'In Review' },
608
+ },
609
+ },
610
+ }),
537
611
  };
538
612
  }
539
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueUpdate: { success: true } } }) };
613
+ return {
614
+ status: 200,
615
+ ok: true,
616
+ body: JSON.stringify({ data: { issueUpdate: { success: true } } }),
617
+ };
540
618
  };
541
619
  // Provide state_id_in_review so resolveStateId returns non-null → mutation is called
542
- const tracker = new LinearIssueTracker({ token: 'tok', state_id_in_review: 'state-inreview-id' }, runner);
620
+ const tracker = new LinearIssueTracker(
621
+ { token: 'tok', state_id_in_review: 'state-inreview-id' },
622
+ runner,
623
+ );
543
624
  await tracker.updateIssueStatus('LIN-2', 'qa');
544
625
  // mapDefaultLinearStatus('qa') → 'in_review' → state_id_in_review → mutation called
545
626
  expect(bodies.length).toBe(2);
@@ -554,12 +635,15 @@ describe('issue-tracker-service additional branch coverage', () => {
554
635
  return {
555
636
  status: 200,
556
637
  ok: true,
557
- body: JSON.stringify({ transitions: [{ id: '5', name: 'In Progress' }] })
638
+ body: JSON.stringify({ transitions: [{ id: '5', name: 'In Progress' }] }),
558
639
  };
559
640
  }
560
641
  return { status: 204, ok: true, body: '' };
561
642
  };
562
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'tok' }, runner);
643
+ const tracker = new JiraIssueTracker(
644
+ { base_url: 'https://jira.example.com', token: 'tok' },
645
+ runner,
646
+ );
563
647
  await tracker.updateIssueStatus('PROJ-3', 'building');
564
648
  // mapDefaultJiraTransition('building') → 'in progress' → matches 'In Progress'
565
649
  expect(calls.some((c) => c.startsWith('POST'))).toBe(true);
@@ -573,12 +657,15 @@ describe('issue-tracker-service additional branch coverage', () => {
573
657
  return {
574
658
  status: 200,
575
659
  ok: true,
576
- body: JSON.stringify({ transitions: [{ id: '1', name: 'To Do' }] })
660
+ body: JSON.stringify({ transitions: [{ id: '1', name: 'To Do' }] }),
577
661
  };
578
662
  }
579
663
  return { status: 204, ok: true, body: '' };
580
664
  };
581
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'tok' }, runner);
665
+ const tracker = new JiraIssueTracker(
666
+ { base_url: 'https://jira.example.com', token: 'tok' },
667
+ runner,
668
+ );
582
669
  await tracker.updateIssueStatus('PROJ-4', 'planning');
583
670
  // mapDefaultJiraTransition('planning') → 'to do' → matches 'To Do'
584
671
  expect(calls.some((c) => c.startsWith('POST'))).toBe(true);
@@ -592,12 +679,15 @@ describe('issue-tracker-service additional branch coverage', () => {
592
679
  return {
593
680
  status: 200,
594
681
  ok: true,
595
- body: JSON.stringify({ transitions: [{ id: '7', name: 'Blocked' }] })
682
+ body: JSON.stringify({ transitions: [{ id: '7', name: 'Blocked' }] }),
596
683
  };
597
684
  }
598
685
  return { status: 204, ok: true, body: '' };
599
686
  };
600
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'tok' }, runner);
687
+ const tracker = new JiraIssueTracker(
688
+ { base_url: 'https://jira.example.com', token: 'tok' },
689
+ runner,
690
+ );
601
691
  await tracker.updateIssueStatus('PROJ-5', 'blocked');
602
692
  expect(calls.some((c) => c.startsWith('POST'))).toBe(true);
603
693
  });
@@ -605,7 +695,8 @@ describe('issue-tracker-service additional branch coverage', () => {
605
695
 
606
696
  describe('Issue tracker additional branch coverage', () => {
607
697
  it('GIVEN_createHttpRunner_called_without_fn_WHEN_fetch_throws_THEN_returns_zero_status', async () => {
608
- const { createHttpRunner } = await import('../src/application/services/issue-tracker-service.js');
698
+ const { createHttpRunner } =
699
+ await import('../src/application/services/issue-tracker-service.js');
609
700
  const fetchSpy = vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('network error'));
610
701
  const runner = createHttpRunner();
611
702
  const result = await runner('https://example.com', { method: 'GET' });
@@ -619,7 +710,7 @@ describe('Issue tracker additional branch coverage', () => {
619
710
  const runner: HttpRunner = async () => ({
620
711
  status: 200,
621
712
  ok: true,
622
- body: JSON.stringify({ data: {}, errors: [{ message: 'GraphQL error' }] })
713
+ body: JSON.stringify({ data: {}, errors: [{ message: 'GraphQL error' }] }),
623
714
  });
624
715
  const tracker = new LinearIssueTracker({ token: 'tok' }, runner);
625
716
  const issue = await tracker.getIssue('LIN-99');
@@ -632,7 +723,7 @@ describe('Issue tracker additional branch coverage', () => {
632
723
  const runner: HttpRunner = async () => ({
633
724
  status: 200,
634
725
  ok: true,
635
- body: JSON.stringify({ data: null })
726
+ body: JSON.stringify({ data: null }),
636
727
  });
637
728
  const tracker = new LinearIssueTracker({ token: 'tok' }, runner);
638
729
  const issue = await tracker.getIssue('LIN-100');
@@ -645,14 +736,33 @@ describe('Issue tracker additional branch coverage', () => {
645
736
  bodies.push((init.body as string) ?? '');
646
737
  if (bodies.length === 1) {
647
738
  return {
648
- status: 200, ok: true,
649
- body: JSON.stringify({ data: { issueByIdentifier: { id: 'lin-uuid-3', identifier: 'LIN-3', title: 'T', description: '', url: '', state: null } } })
739
+ status: 200,
740
+ ok: true,
741
+ body: JSON.stringify({
742
+ data: {
743
+ issueByIdentifier: {
744
+ id: 'lin-uuid-3',
745
+ identifier: 'LIN-3',
746
+ title: 'T',
747
+ description: '',
748
+ url: '',
749
+ state: null,
750
+ },
751
+ },
752
+ }),
650
753
  };
651
754
  }
652
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueUpdate: { success: true } } }) };
755
+ return {
756
+ status: 200,
757
+ ok: true,
758
+ body: JSON.stringify({ data: { issueUpdate: { success: true } } }),
759
+ };
653
760
  };
654
761
  // Provide state_id_in_progress to cover the 'in_progress' default mapping for unknown status
655
- const tracker = new LinearIssueTracker({ token: 'tok', state_id_in_progress: 'state-inprogress-id' }, runner);
762
+ const tracker = new LinearIssueTracker(
763
+ { token: 'tok', state_id_in_progress: 'state-inprogress-id' },
764
+ runner,
765
+ );
656
766
  await tracker.updateIssueStatus('LIN-3', 'some_random_unknown_status');
657
767
  // mapDefaultLinearStatus returns 'in_progress' → state_id_in_progress → mutation called
658
768
  expect(bodies.length).toBe(2);
@@ -664,8 +774,20 @@ describe('Issue tracker additional branch coverage', () => {
664
774
  callCount += 1;
665
775
  if (callCount === 1) {
666
776
  return {
667
- status: 200, ok: true,
668
- body: JSON.stringify({ data: { issueByIdentifier: { id: 'lin-uuid-4', identifier: 'LIN-4', title: 'T', description: '', url: '', state: null } } })
777
+ status: 200,
778
+ ok: true,
779
+ body: JSON.stringify({
780
+ data: {
781
+ issueByIdentifier: {
782
+ id: 'lin-uuid-4',
783
+ identifier: 'LIN-4',
784
+ title: 'T',
785
+ description: '',
786
+ url: '',
787
+ state: null,
788
+ },
789
+ },
790
+ }),
669
791
  };
670
792
  }
671
793
  return { status: 200, ok: true, body: JSON.stringify({ data: {} }) };
@@ -681,9 +803,19 @@ describe('Issue tracker additional branch coverage', () => {
681
803
  const calls: { auth?: string }[] = [];
682
804
  const runner: HttpRunner = async (_, init) => {
683
805
  calls.push({ auth: (init.headers as Record<string, string>)['Authorization'] });
684
- return { status: 200, ok: true, body: JSON.stringify({ key: 'PROJ-1', fields: { summary: 'Test', description: 'Body', status: { name: 'Open' } } }) };
806
+ return {
807
+ status: 200,
808
+ ok: true,
809
+ body: JSON.stringify({
810
+ key: 'PROJ-1',
811
+ fields: { summary: 'Test', description: 'Body', status: { name: 'Open' } },
812
+ }),
813
+ };
685
814
  };
686
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'my-token' }, runner);
815
+ const tracker = new JiraIssueTracker(
816
+ { base_url: 'https://jira.example.com', token: 'my-token' },
817
+ runner,
818
+ );
687
819
  const issue = await tracker.getIssue('PROJ-1');
688
820
  expect(issue.title).toBe('Test');
689
821
  expect(calls[0].auth).toMatch(/^Bearer /);
@@ -701,9 +833,16 @@ describe('Issue tracker additional branch coverage', () => {
701
833
  const calls: string[] = [];
702
834
  const runner: HttpRunner = async (_url, init) => {
703
835
  calls.push(init.method ?? 'GET');
704
- return { status: 200, ok: true, body: JSON.stringify({ transitions: [{ id: '1', name: 'Open' }] }) };
836
+ return {
837
+ status: 200,
838
+ ok: true,
839
+ body: JSON.stringify({ transitions: [{ id: '1', name: 'Open' }] }),
840
+ };
705
841
  };
706
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'tok' }, runner);
842
+ const tracker = new JiraIssueTracker(
843
+ { base_url: 'https://jira.example.com', token: 'tok' },
844
+ runner,
845
+ );
707
846
  await tracker.updateIssueStatus('PROJ-1', 'merged'); // mapDefaultJiraTransition → 'done', no matching transition
708
847
  expect(calls.filter((m) => m === 'POST')).toHaveLength(0);
709
848
  });
@@ -712,7 +851,14 @@ describe('Issue tracker additional branch coverage', () => {
712
851
  const calls: { hasAuth: boolean }[] = [];
713
852
  const runner: HttpRunner = async (_, init) => {
714
853
  calls.push({ hasAuth: 'Authorization' in (init.headers as Record<string, string>) });
715
- return { status: 200, ok: true, body: JSON.stringify({ key: 'PROJ-1', fields: { summary: '', description: null, status: { name: 'Open' } } }) };
854
+ return {
855
+ status: 200,
856
+ ok: true,
857
+ body: JSON.stringify({
858
+ key: 'PROJ-1',
859
+ fields: { summary: '', description: null, status: { name: 'Open' } },
860
+ }),
861
+ };
716
862
  };
717
863
  const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com' }, runner);
718
864
  await tracker.getIssue('PROJ-1');
@@ -728,17 +874,21 @@ describe('Issue tracker additional branch coverage', () => {
728
874
 
729
875
  it('GIVEN_jira_description_is_object_WHEN_getIssue_called_THEN_returns_json_string', async () => {
730
876
  const runner: HttpRunner = async () => ({
731
- status: 200, ok: true,
877
+ status: 200,
878
+ ok: true,
732
879
  body: JSON.stringify({
733
880
  key: 'PROJ-2',
734
881
  fields: {
735
882
  summary: 'Test',
736
883
  description: { type: 'doc', content: [] },
737
- status: { name: 'In Progress' }
738
- }
739
- })
884
+ status: { name: 'In Progress' },
885
+ },
886
+ }),
740
887
  });
741
- const tracker = new JiraIssueTracker({ base_url: 'https://jira.example.com', token: 'tok' }, runner);
888
+ const tracker = new JiraIssueTracker(
889
+ { base_url: 'https://jira.example.com', token: 'tok' },
890
+ runner,
891
+ );
742
892
  const issue = await tracker.getIssue('PROJ-2');
743
893
  expect(issue.body).toContain('doc');
744
894
  });
@@ -750,7 +900,7 @@ describe('LinearIssueTracker addComment and updateIssueStatus guard branches', (
750
900
  const runner: HttpRunner = async () => ({
751
901
  status: 200,
752
902
  ok: true,
753
- body: JSON.stringify({ data: { issueByIdentifier: null } })
903
+ body: JSON.stringify({ data: { issueByIdentifier: null } }),
754
904
  });
755
905
  // Should not throw and should not call graphql mutation
756
906
  let callCount = 0;
@@ -769,7 +919,9 @@ describe('LinearIssueTracker addComment and updateIssueStatus guard branches', (
769
919
  const runner: HttpRunner = async () => ({
770
920
  status: 200,
771
921
  ok: true,
772
- body: JSON.stringify({ data: { issueByIdentifier: { identifier: 'LIN-1', title: 'T', description: '', url: '' } } })
922
+ body: JSON.stringify({
923
+ data: { issueByIdentifier: { identifier: 'LIN-1', title: 'T', description: '', url: '' } },
924
+ }),
773
925
  });
774
926
  const tracker = new LinearIssueTracker({}, runner);
775
927
  await expect(tracker.addComment('LIN-1', 'comment')).resolves.toBeUndefined();
@@ -779,7 +931,7 @@ describe('LinearIssueTracker addComment and updateIssueStatus guard branches', (
779
931
  const runner: HttpRunner = async () => ({
780
932
  status: 200,
781
933
  ok: true,
782
- body: JSON.stringify({ data: { issueByIdentifier: null } })
934
+ body: JSON.stringify({ data: { issueByIdentifier: null } }),
783
935
  });
784
936
  const tracker = new LinearIssueTracker({ token: 'tok', state_id_building: 'state-id' }, runner);
785
937
  await expect(tracker.updateIssueStatus('LIN-999', 'building')).resolves.toBeUndefined();
@@ -792,7 +944,7 @@ describe('LinearIssueTracker graphQl invalid body branch', () => {
792
944
  const runner: HttpRunner = async () => ({
793
945
  status: 200,
794
946
  ok: true,
795
- body: 'not valid json {{ response'
947
+ body: 'not valid json {{ response',
796
948
  });
797
949
  const tracker = new LinearIssueTracker({}, runner);
798
950
  const issue = await tracker.getIssue('LIN-invalid-json');
@@ -805,7 +957,7 @@ describe('LinearIssueTracker graphQl invalid body branch', () => {
805
957
  const runner: HttpRunner = async () => ({
806
958
  status: 200,
807
959
  ok: true,
808
- body: ''
960
+ body: '',
809
961
  });
810
962
  const tracker = new LinearIssueTracker({}, runner);
811
963
  const issue = await tracker.getIssue('LIN-empty-body');
@@ -821,12 +973,34 @@ describe('LinearIssueTracker mapDefaultLinearStatus building branch', () => {
821
973
  const runner: HttpRunner = async () => {
822
974
  callCount++;
823
975
  if (callCount === 1) {
824
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueByIdentifier: { id: 'lin-uuid-build', identifier: 'LIN-B', title: 'T', description: '', url: '', state: null } } }) };
976
+ return {
977
+ status: 200,
978
+ ok: true,
979
+ body: JSON.stringify({
980
+ data: {
981
+ issueByIdentifier: {
982
+ id: 'lin-uuid-build',
983
+ identifier: 'LIN-B',
984
+ title: 'T',
985
+ description: '',
986
+ url: '',
987
+ state: null,
988
+ },
989
+ },
990
+ }),
991
+ };
825
992
  }
826
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueUpdate: { success: true } } }) };
993
+ return {
994
+ status: 200,
995
+ ok: true,
996
+ body: JSON.stringify({ data: { issueUpdate: { success: true } } }),
997
+ };
827
998
  };
828
999
  // No state_id_building but has state_id_in_progress → mapDefaultLinearStatus('building') → 'in_progress'
829
- const tracker = new LinearIssueTracker({ token: 'tok', state_id_in_progress: 'state-ip-id' }, runner);
1000
+ const tracker = new LinearIssueTracker(
1001
+ { token: 'tok', state_id_in_progress: 'state-ip-id' },
1002
+ runner,
1003
+ );
830
1004
  await tracker.updateIssueStatus('LIN-B', 'building');
831
1005
  // Mutation should be called (callCount > 2 if resolveIssueNode needs 2 calls)
832
1006
  expect(callCount).toBeGreaterThan(1);
@@ -840,11 +1014,33 @@ describe('LinearIssueTracker mapDefaultLinearStatus OR branches and lowerCaseSta
840
1014
  const runner: HttpRunner = async () => {
841
1015
  callCount++;
842
1016
  if (callCount === 1) {
843
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueByIdentifier: { id: 'lin-closed', identifier: 'LIN-C', title: 'T', description: '', url: '', state: null } } }) };
1017
+ return {
1018
+ status: 200,
1019
+ ok: true,
1020
+ body: JSON.stringify({
1021
+ data: {
1022
+ issueByIdentifier: {
1023
+ id: 'lin-closed',
1024
+ identifier: 'LIN-C',
1025
+ title: 'T',
1026
+ description: '',
1027
+ url: '',
1028
+ state: null,
1029
+ },
1030
+ },
1031
+ }),
1032
+ };
844
1033
  }
845
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueUpdate: { success: true } } }) };
1034
+ return {
1035
+ status: 200,
1036
+ ok: true,
1037
+ body: JSON.stringify({ data: { issueUpdate: { success: true } } }),
1038
+ };
846
1039
  };
847
- const tracker = new LinearIssueTracker({ token: 'tok', state_id_done: 'state-done-id' }, runner);
1040
+ const tracker = new LinearIssueTracker(
1041
+ { token: 'tok', state_id_done: 'state-done-id' },
1042
+ runner,
1043
+ );
848
1044
  await tracker.updateIssueStatus('LIN-C', 'closed');
849
1045
  expect(callCount).toBeGreaterThan(1);
850
1046
  });
@@ -855,11 +1051,33 @@ describe('LinearIssueTracker mapDefaultLinearStatus OR branches and lowerCaseSta
855
1051
  const runner: HttpRunner = async () => {
856
1052
  callCount++;
857
1053
  if (callCount === 1) {
858
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueByIdentifier: { id: 'lin-failed', identifier: 'LIN-F', title: 'T', description: '', url: '', state: null } } }) };
1054
+ return {
1055
+ status: 200,
1056
+ ok: true,
1057
+ body: JSON.stringify({
1058
+ data: {
1059
+ issueByIdentifier: {
1060
+ id: 'lin-failed',
1061
+ identifier: 'LIN-F',
1062
+ title: 'T',
1063
+ description: '',
1064
+ url: '',
1065
+ state: null,
1066
+ },
1067
+ },
1068
+ }),
1069
+ };
859
1070
  }
860
- return { status: 200, ok: true, body: JSON.stringify({ data: { issueUpdate: { success: true } } }) };
1071
+ return {
1072
+ status: 200,
1073
+ ok: true,
1074
+ body: JSON.stringify({ data: { issueUpdate: { success: true } } }),
1075
+ };
861
1076
  };
862
- const tracker = new LinearIssueTracker({ token: 'tok', state_id_blocked: 'state-blocked-id' }, runner);
1077
+ const tracker = new LinearIssueTracker(
1078
+ { token: 'tok', state_id_blocked: 'state-blocked-id' },
1079
+ runner,
1080
+ );
863
1081
  await tracker.updateIssueStatus('LIN-F', 'failed');
864
1082
  expect(callCount).toBeGreaterThan(1);
865
1083
  });
@@ -869,7 +1087,18 @@ describe('LinearIssueTracker mapDefaultLinearStatus OR branches and lowerCaseSta
869
1087
  const runner: HttpRunner = async () => ({
870
1088
  status: 200,
871
1089
  ok: true,
872
- body: JSON.stringify({ data: { issueByIdentifier: { id: 'lin-nostate', identifier: 'LIN-NS', title: 'No State', description: 'desc', url: 'https://x', state: null } } })
1090
+ body: JSON.stringify({
1091
+ data: {
1092
+ issueByIdentifier: {
1093
+ id: 'lin-nostate',
1094
+ identifier: 'LIN-NS',
1095
+ title: 'No State',
1096
+ description: 'desc',
1097
+ url: 'https://x',
1098
+ state: null,
1099
+ },
1100
+ },
1101
+ }),
873
1102
  });
874
1103
  const tracker = new LinearIssueTracker({}, runner);
875
1104
  const issue = await tracker.getIssue('LIN-NS');
@@ -881,7 +1110,18 @@ describe('LinearIssueTracker mapDefaultLinearStatus OR branches and lowerCaseSta
881
1110
  const runner: HttpRunner = async () => ({
882
1111
  status: 200,
883
1112
  ok: true,
884
- body: JSON.stringify({ data: { issueByIdentifier: { id: 'lin-raw-id', identifier: '', title: 'T', description: 'desc', url: 'https://x', state: { name: 'In Progress' } } } })
1113
+ body: JSON.stringify({
1114
+ data: {
1115
+ issueByIdentifier: {
1116
+ id: 'lin-raw-id',
1117
+ identifier: '',
1118
+ title: 'T',
1119
+ description: 'desc',
1120
+ url: 'https://x',
1121
+ state: { name: 'In Progress' },
1122
+ },
1123
+ },
1124
+ }),
885
1125
  });
886
1126
  const tracker = new LinearIssueTracker({}, runner);
887
1127
  const issue = await tracker.getIssue('LIN-NOID');