issue-flow 0.16.0 → 0.18.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 (168) hide show
  1. package/dist/agent-HMZTXCRT.js +30 -0
  2. package/dist/{analyze-556KCJKZ.js → analyze-Q4ONIWRZ.js} +22 -22
  3. package/dist/{apply-WVV7G7WN.js → apply-EEFPY2W4.js} +14 -14
  4. package/dist/{bench-UBFGKUHR.js → bench-WWWXLTFH.js} +23 -23
  5. package/dist/{chunk-GV2DABNZ.js → chunk-34OCSKOB.js} +12 -12
  6. package/dist/chunk-3R27MJ5R.js +25 -0
  7. package/dist/chunk-3R27MJ5R.js.map +1 -0
  8. package/dist/{chunk-PGN2VX4Y.js → chunk-45WZ6GMI.js} +32 -48
  9. package/dist/chunk-45WZ6GMI.js.map +1 -0
  10. package/dist/{chunk-H3EYBJZU.js → chunk-62GVVZQO.js} +10 -10
  11. package/dist/{chunk-GPLP7EPL.js → chunk-6K2LCFG6.js} +10 -10
  12. package/dist/{chunk-GPLP7EPL.js.map → chunk-6K2LCFG6.js.map} +1 -1
  13. package/dist/{chunk-OGVWJO4S.js → chunk-7F7LGMVO.js} +3 -3
  14. package/dist/{chunk-X6GY3CM2.js → chunk-7UMMFOL2.js} +104 -104
  15. package/dist/chunk-7UMMFOL2.js.map +1 -0
  16. package/dist/{chunk-OLUOZLU5.js → chunk-CWSQVHVV.js} +1691 -1075
  17. package/dist/chunk-CWSQVHVV.js.map +1 -0
  18. package/dist/{chunk-MXCOSPLJ.js → chunk-DGRTJD5R.js} +3 -3
  19. package/dist/{chunk-ROIIEVZH.js → chunk-DUS5ZNKL.js} +474 -361
  20. package/dist/chunk-DUS5ZNKL.js.map +1 -0
  21. package/dist/{chunk-BSBJXPLC.js → chunk-E4I6MMHD.js} +10 -10
  22. package/dist/{chunk-QZOBR6YF.js → chunk-ECU7YO7S.js} +4 -4
  23. package/dist/chunk-ECU7YO7S.js.map +1 -0
  24. package/dist/{chunk-EPFC4LHT.js → chunk-EG2MGDP5.js} +9 -9
  25. package/dist/chunk-HOAHMERN.js +229 -0
  26. package/dist/chunk-HOAHMERN.js.map +1 -0
  27. package/dist/{chunk-QVLIIGBU.js → chunk-ICM463EO.js} +60 -13
  28. package/dist/chunk-ICM463EO.js.map +1 -0
  29. package/dist/{chunk-4FUWWBTP.js → chunk-KMCS76ZW.js} +8 -8
  30. package/dist/{chunk-SW2MF47D.js → chunk-KRAGAUKD.js} +19 -19
  31. package/dist/{chunk-OOX3RMD3.js → chunk-LGHND47K.js} +4 -4
  32. package/dist/{chunk-VTF4RWS5.js → chunk-LI35PIIS.js} +7 -7
  33. package/dist/{chunk-Q2TZA6AC.js → chunk-LTH6XYZ3.js} +14 -14
  34. package/dist/{chunk-YA6FWFYW.js → chunk-NEWNXZ65.js} +62 -11
  35. package/dist/chunk-NEWNXZ65.js.map +1 -0
  36. package/dist/{chunk-2H43OVTU.js → chunk-OODXFCQV.js} +11 -11
  37. package/dist/{chunk-KV2K7MK2.js → chunk-PMLE7KAQ.js} +20 -12
  38. package/dist/chunk-PMLE7KAQ.js.map +1 -0
  39. package/dist/{chunk-R42YHLDV.js → chunk-PPZ3K4YM.js} +2 -2
  40. package/dist/{chunk-J2LJB2OH.js → chunk-QF7VEL3M.js} +739 -579
  41. package/dist/chunk-QF7VEL3M.js.map +1 -0
  42. package/dist/{chunk-VK65RNFA.js → chunk-QJ44VG5G.js} +3 -3
  43. package/dist/{chunk-FKWYD44M.js → chunk-QPGEFLMY.js} +2 -2
  44. package/dist/{chunk-NQCR3HSU.js → chunk-RNFUVKC3.js} +3 -3
  45. package/dist/{chunk-G5LACAXO.js → chunk-RYOUZ6EK.js} +2 -2
  46. package/dist/{chunk-MCLPSL6B.js → chunk-SA6HXL4Y.js} +3 -3
  47. package/dist/{chunk-GVOZ6NDO.js → chunk-SOM4QA6C.js} +3 -3
  48. package/dist/{chunk-73TS2H42.js → chunk-TZYINKCC.js} +154 -34
  49. package/dist/chunk-TZYINKCC.js.map +1 -0
  50. package/dist/{chunk-DBEMD34J.js → chunk-V7QOIQYC.js} +8 -8
  51. package/dist/{chunk-IAMIBZRF.js → chunk-WCCZJL7W.js} +2 -2
  52. package/dist/{chunk-OGN2NX57.js → chunk-XUEMATVY.js} +9 -9
  53. package/dist/{chunk-SVDEWOUD.js → chunk-XZUEFTUP.js} +6 -6
  54. package/dist/{chunk-WLJVL25O.js → chunk-YUNBOUQH.js} +6 -6
  55. package/dist/{chunk-WNROH2YE.js → chunk-YVPZUN6X.js} +2 -2
  56. package/dist/chunk-ZVZMWNCG.js +415 -0
  57. package/dist/chunk-ZVZMWNCG.js.map +1 -0
  58. package/dist/cli.js +57 -49
  59. package/dist/cli.js.map +1 -1
  60. package/dist/{config-UE7IP36J.js → config-LEBZZCJP.js} +13 -13
  61. package/dist/{conventions-Z3QC2NSG.js → conventions-XOT6YW5L.js} +15 -15
  62. package/dist/{diagnostics-2Z5HFQOO.js → diagnostics-HTCWF7F4.js} +7 -7
  63. package/dist/execute-LELOSR5T.js +37 -0
  64. package/dist/{generate-PB4L7V5N.js → generate-JGW5JSKB.js} +22 -22
  65. package/dist/{git-7MUOGVRG.js → git-A2IP32PQ.js} +2 -2
  66. package/dist/init-TO6MUXO4.js +26 -0
  67. package/dist/{operations-QDJAFZUN.js → operations-O4FORFIH.js} +15 -15
  68. package/dist/{permissions-XVXXENVP.js → permissions-G4XCAESF.js} +4 -4
  69. package/dist/plan-OXAT344Q.js +34 -0
  70. package/dist/{policy-6WQZB6B2.js → policy-U5NBFAO5.js} +14 -14
  71. package/dist/pr-UZHNKKZC.js +39 -0
  72. package/dist/pr-review-Q4ACAWDM.js +32 -0
  73. package/dist/prd-6CYEMLDY.js +33 -0
  74. package/dist/{ps-CX7756QG.js → ps-76L6ZAZL.js} +12 -12
  75. package/dist/{recorder-RK6XZYF3.js → recorder-2BAKPBRA.js} +7 -7
  76. package/dist/{registry-POSB35Q4.js → registry-XLHHYLTR.js} +5 -5
  77. package/dist/{resume-OQJZV3JH.js → resume-URCU6CIJ.js} +39 -38
  78. package/dist/{resume-OQJZV3JH.js.map → resume-URCU6CIJ.js.map} +1 -1
  79. package/dist/review-LVZT2TMW.js +35 -0
  80. package/dist/routing-EK6RBZM4.js +33 -0
  81. package/dist/run-2RXJCJKT.js +56 -0
  82. package/dist/{session-publisher-VVXOCJ2S.js → session-publisher-KAJQRHNZ.js} +3 -2
  83. package/dist/{state-manager-TIC73GQY.js → state-manager-UPHO2EA2.js} +4 -4
  84. package/dist/state-manager-UPHO2EA2.js.map +1 -0
  85. package/dist/{usage-WDDNSIHP.js → usage-KTMYXAPF.js} +12 -12
  86. package/dist/{web-IPGY52AK.js → web-B5UPHHR5.js} +20 -18
  87. package/dist/{web-IPGY52AK.js.map → web-B5UPHHR5.js.map} +1 -1
  88. package/package.json +6 -5
  89. package/web/AGENTS.md +125 -18
  90. package/web/public/app.css +420 -234
  91. package/web/public/app.js +371 -80
  92. package/web/public/index.html +106 -78
  93. package/dist/agent-PMWCDWOW.js +0 -30
  94. package/dist/chunk-73TS2H42.js.map +0 -1
  95. package/dist/chunk-7Z4Y3VKM.js +0 -26
  96. package/dist/chunk-7Z4Y3VKM.js.map +0 -1
  97. package/dist/chunk-AOAQU7PD.js +0 -180
  98. package/dist/chunk-AOAQU7PD.js.map +0 -1
  99. package/dist/chunk-J2LJB2OH.js.map +0 -1
  100. package/dist/chunk-KV2K7MK2.js.map +0 -1
  101. package/dist/chunk-OLUOZLU5.js.map +0 -1
  102. package/dist/chunk-PGN2VX4Y.js.map +0 -1
  103. package/dist/chunk-QVLIIGBU.js.map +0 -1
  104. package/dist/chunk-QZOBR6YF.js.map +0 -1
  105. package/dist/chunk-ROIIEVZH.js.map +0 -1
  106. package/dist/chunk-X6GY3CM2.js.map +0 -1
  107. package/dist/chunk-YA6FWFYW.js.map +0 -1
  108. package/dist/execute-QYLJ5L4T.js +0 -36
  109. package/dist/init-XBERAZ4O.js +0 -24
  110. package/dist/plan-RXOW32KY.js +0 -34
  111. package/dist/pr-3WFYAVA7.js +0 -39
  112. package/dist/pr-review-RK63ZEMM.js +0 -32
  113. package/dist/prd-LRV6IW3E.js +0 -33
  114. package/dist/review-AEFISJZD.js +0 -35
  115. package/dist/routing-EA5NJGNU.js +0 -94
  116. package/dist/routing-EA5NJGNU.js.map +0 -1
  117. package/dist/run-HSC7R33Y.js +0 -55
  118. /package/dist/{agent-PMWCDWOW.js.map → agent-HMZTXCRT.js.map} +0 -0
  119. /package/dist/{analyze-556KCJKZ.js.map → analyze-Q4ONIWRZ.js.map} +0 -0
  120. /package/dist/{apply-WVV7G7WN.js.map → apply-EEFPY2W4.js.map} +0 -0
  121. /package/dist/{bench-UBFGKUHR.js.map → bench-WWWXLTFH.js.map} +0 -0
  122. /package/dist/{chunk-GV2DABNZ.js.map → chunk-34OCSKOB.js.map} +0 -0
  123. /package/dist/{chunk-H3EYBJZU.js.map → chunk-62GVVZQO.js.map} +0 -0
  124. /package/dist/{chunk-OGVWJO4S.js.map → chunk-7F7LGMVO.js.map} +0 -0
  125. /package/dist/{chunk-MXCOSPLJ.js.map → chunk-DGRTJD5R.js.map} +0 -0
  126. /package/dist/{chunk-BSBJXPLC.js.map → chunk-E4I6MMHD.js.map} +0 -0
  127. /package/dist/{chunk-EPFC4LHT.js.map → chunk-EG2MGDP5.js.map} +0 -0
  128. /package/dist/{chunk-4FUWWBTP.js.map → chunk-KMCS76ZW.js.map} +0 -0
  129. /package/dist/{chunk-SW2MF47D.js.map → chunk-KRAGAUKD.js.map} +0 -0
  130. /package/dist/{chunk-OOX3RMD3.js.map → chunk-LGHND47K.js.map} +0 -0
  131. /package/dist/{chunk-VTF4RWS5.js.map → chunk-LI35PIIS.js.map} +0 -0
  132. /package/dist/{chunk-Q2TZA6AC.js.map → chunk-LTH6XYZ3.js.map} +0 -0
  133. /package/dist/{chunk-2H43OVTU.js.map → chunk-OODXFCQV.js.map} +0 -0
  134. /package/dist/{chunk-R42YHLDV.js.map → chunk-PPZ3K4YM.js.map} +0 -0
  135. /package/dist/{chunk-VK65RNFA.js.map → chunk-QJ44VG5G.js.map} +0 -0
  136. /package/dist/{chunk-FKWYD44M.js.map → chunk-QPGEFLMY.js.map} +0 -0
  137. /package/dist/{chunk-NQCR3HSU.js.map → chunk-RNFUVKC3.js.map} +0 -0
  138. /package/dist/{chunk-G5LACAXO.js.map → chunk-RYOUZ6EK.js.map} +0 -0
  139. /package/dist/{chunk-MCLPSL6B.js.map → chunk-SA6HXL4Y.js.map} +0 -0
  140. /package/dist/{chunk-GVOZ6NDO.js.map → chunk-SOM4QA6C.js.map} +0 -0
  141. /package/dist/{chunk-DBEMD34J.js.map → chunk-V7QOIQYC.js.map} +0 -0
  142. /package/dist/{chunk-IAMIBZRF.js.map → chunk-WCCZJL7W.js.map} +0 -0
  143. /package/dist/{chunk-OGN2NX57.js.map → chunk-XUEMATVY.js.map} +0 -0
  144. /package/dist/{chunk-SVDEWOUD.js.map → chunk-XZUEFTUP.js.map} +0 -0
  145. /package/dist/{chunk-WLJVL25O.js.map → chunk-YUNBOUQH.js.map} +0 -0
  146. /package/dist/{chunk-WNROH2YE.js.map → chunk-YVPZUN6X.js.map} +0 -0
  147. /package/dist/{config-UE7IP36J.js.map → config-LEBZZCJP.js.map} +0 -0
  148. /package/dist/{conventions-Z3QC2NSG.js.map → conventions-XOT6YW5L.js.map} +0 -0
  149. /package/dist/{diagnostics-2Z5HFQOO.js.map → diagnostics-HTCWF7F4.js.map} +0 -0
  150. /package/dist/{execute-QYLJ5L4T.js.map → execute-LELOSR5T.js.map} +0 -0
  151. /package/dist/{generate-PB4L7V5N.js.map → generate-JGW5JSKB.js.map} +0 -0
  152. /package/dist/{git-7MUOGVRG.js.map → git-A2IP32PQ.js.map} +0 -0
  153. /package/dist/{init-XBERAZ4O.js.map → init-TO6MUXO4.js.map} +0 -0
  154. /package/dist/{operations-QDJAFZUN.js.map → operations-O4FORFIH.js.map} +0 -0
  155. /package/dist/{permissions-XVXXENVP.js.map → permissions-G4XCAESF.js.map} +0 -0
  156. /package/dist/{plan-RXOW32KY.js.map → plan-OXAT344Q.js.map} +0 -0
  157. /package/dist/{policy-6WQZB6B2.js.map → policy-U5NBFAO5.js.map} +0 -0
  158. /package/dist/{pr-3WFYAVA7.js.map → pr-UZHNKKZC.js.map} +0 -0
  159. /package/dist/{pr-review-RK63ZEMM.js.map → pr-review-Q4ACAWDM.js.map} +0 -0
  160. /package/dist/{prd-LRV6IW3E.js.map → prd-6CYEMLDY.js.map} +0 -0
  161. /package/dist/{ps-CX7756QG.js.map → ps-76L6ZAZL.js.map} +0 -0
  162. /package/dist/{recorder-RK6XZYF3.js.map → recorder-2BAKPBRA.js.map} +0 -0
  163. /package/dist/{registry-POSB35Q4.js.map → registry-XLHHYLTR.js.map} +0 -0
  164. /package/dist/{review-AEFISJZD.js.map → review-LVZT2TMW.js.map} +0 -0
  165. /package/dist/{run-HSC7R33Y.js.map → routing-EK6RBZM4.js.map} +0 -0
  166. /package/dist/{session-publisher-VVXOCJ2S.js.map → run-2RXJCJKT.js.map} +0 -0
  167. /package/dist/{state-manager-TIC73GQY.js.map → session-publisher-KAJQRHNZ.js.map} +0 -0
  168. /package/dist/{usage-WDDNSIHP.js.map → usage-KTMYXAPF.js.map} +0 -0
@@ -3,35 +3,35 @@ import {
3
3
  isTransientFailure,
4
4
  readFileWithGrace,
5
5
  runPhaseWithRetry
6
- } from "./chunk-DBEMD34J.js";
6
+ } from "./chunk-V7QOIQYC.js";
7
7
  import {
8
8
  issuePlaceholders,
9
9
  resolveCommandIssue
10
- } from "./chunk-MCLPSL6B.js";
10
+ } from "./chunk-SA6HXL4Y.js";
11
11
  import {
12
12
  publishPhaseMetrics,
13
13
  resolvePolicyPlaceholders
14
- } from "./chunk-4FUWWBTP.js";
14
+ } from "./chunk-KMCS76ZW.js";
15
15
  import {
16
16
  applyPlaceholders,
17
17
  loadPrompt
18
- } from "./chunk-OGVWJO4S.js";
18
+ } from "./chunk-7F7LGMVO.js";
19
19
  import {
20
20
  DEFAULT_HEADLESS_TIMEOUT_MS,
21
21
  runHeadless
22
- } from "./chunk-73TS2H42.js";
22
+ } from "./chunk-TZYINKCC.js";
23
23
  import {
24
24
  resolveIssuePaths
25
- } from "./chunk-VTF4RWS5.js";
25
+ } from "./chunk-LI35PIIS.js";
26
26
  import {
27
27
  getGlobalTimeout,
28
28
  printError,
29
29
  printSuccess
30
- } from "./chunk-SVDEWOUD.js";
30
+ } from "./chunk-XZUEFTUP.js";
31
31
  import {
32
32
  loadTaskPlan,
33
33
  saveTaskPlan
34
- } from "./chunk-GVOZ6NDO.js";
34
+ } from "./chunk-SOM4QA6C.js";
35
35
 
36
36
  // src/commands/prd.ts
37
37
  import { mkdir } from "fs/promises";
@@ -114,4 +114,4 @@ async function runPrd(issue, resolvedIssue) {
114
114
  export {
115
115
  runPrd
116
116
  };
117
- //# sourceMappingURL=chunk-OGN2NX57.js.map
117
+ //# sourceMappingURL=chunk-XUEMATVY.js.map
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- getSessionPublisher
4
- } from "./chunk-ROIIEVZH.js";
5
2
  import {
6
3
  writeDiagnostic
7
- } from "./chunk-FKWYD44M.js";
4
+ } from "./chunk-QPGEFLMY.js";
5
+ import {
6
+ getSessionPublisher
7
+ } from "./chunk-DUS5ZNKL.js";
8
8
  import {
9
9
  isoNow
10
- } from "./chunk-GVOZ6NDO.js";
10
+ } from "./chunk-SOM4QA6C.js";
11
11
 
12
12
  // src/core/verbose.ts
13
13
  var _verbose = false;
@@ -240,4 +240,4 @@ export {
240
240
  formatDuration,
241
241
  ElapsedTimer
242
242
  };
243
- //# sourceMappingURL=chunk-SVDEWOUD.js.map
243
+ //# sourceMappingURL=chunk-XZUEFTUP.js.map
@@ -1,7 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- NullPublisher
4
- } from "./chunk-ROIIEVZH.js";
5
2
  import {
6
3
  getBaseBranch,
7
4
  getCommitsSince,
@@ -12,10 +9,13 @@ import {
12
9
  normalizeRemoteUrl,
13
10
  run,
14
11
  stripRemoteUrlCredentials
15
- } from "./chunk-WNROH2YE.js";
12
+ } from "./chunk-YVPZUN6X.js";
13
+ import {
14
+ NullPublisher
15
+ } from "./chunk-DUS5ZNKL.js";
16
16
  import {
17
17
  isoNow
18
- } from "./chunk-GVOZ6NDO.js";
18
+ } from "./chunk-SOM4QA6C.js";
19
19
 
20
20
  // src/core/session-git.ts
21
21
  async function listPullRequests(branch, options = {}) {
@@ -112,4 +112,4 @@ export {
112
112
  listPullRequests,
113
113
  publishGitState
114
114
  };
115
- //# sourceMappingURL=chunk-WLJVL25O.js.map
115
+ //# sourceMappingURL=chunk-YUNBOUQH.js.map
@@ -201,7 +201,7 @@ function inferSource(command) {
201
201
  }
202
202
  function diagnoseCommandFailure(command, args, result) {
203
203
  if (result.exitCode === 0) return;
204
- void import("./diagnostics-2Z5HFQOO.js").then(({ writeDiagnostic }) => {
204
+ void import("./diagnostics-HTCWF7F4.js").then(({ writeDiagnostic }) => {
205
205
  writeDiagnostic({
206
206
  level: "warning",
207
207
  message: `Command failed: ${basename(command)}`,
@@ -622,4 +622,4 @@ export {
622
622
  committedStoryIds,
623
623
  isWorkingTreeClean
624
624
  };
625
- //# sourceMappingURL=chunk-WNROH2YE.js.map
625
+ //# sourceMappingURL=chunk-YVPZUN6X.js.map
@@ -0,0 +1,415 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ANTIGRAVITY_CAPABILITIES,
4
+ CLAUDE_CAPABILITIES,
5
+ CODEX_CAPABILITIES,
6
+ CURSOR_CAPABILITIES
7
+ } from "./chunk-ICM463EO.js";
8
+
9
+ // src/routing/models.ts
10
+ var MODEL_CATALOG_VERSION = "1";
11
+ var MODEL_CATALOG = {
12
+ "claude-code": [
13
+ { id: "haiku", tier: "fast", relativeCost: 1, relativeLatency: 1 },
14
+ { id: "sonnet", tier: "mid", relativeCost: 3.5, relativeLatency: 1.5 },
15
+ { id: "opus", tier: "strong", relativeCost: 8, relativeLatency: 2.2 }
16
+ ],
17
+ "codex-cli": [
18
+ { id: "gpt-5.6-luna", tier: "fast", relativeCost: 1, relativeLatency: 1 },
19
+ { id: "gpt-5.6-terra", tier: "mid", relativeCost: 3, relativeLatency: 1.45 },
20
+ { id: "gpt-5.6-sol", tier: "strong", relativeCost: 7, relativeLatency: 2.1 }
21
+ ],
22
+ "cursor-cli": [
23
+ { id: "auto-fast", tier: "fast", relativeCost: 1, relativeLatency: 1 },
24
+ { id: "auto", tier: "mid", relativeCost: 3, relativeLatency: 1.5 },
25
+ { id: "auto-strong", tier: "strong", relativeCost: 7, relativeLatency: 2.1 }
26
+ ],
27
+ "antigravity-cli": [
28
+ { id: "gemini-3.5-flash-low", tier: "fast", relativeCost: 1, relativeLatency: 1 },
29
+ { id: "gemini-3.5-flash-medium", tier: "mid", relativeCost: 2.5, relativeLatency: 1.4 },
30
+ { id: "gemini-3.5-pro-high", tier: "strong", relativeCost: 6, relativeLatency: 2 }
31
+ ]
32
+ };
33
+ var DEFAULT_ONLY = [
34
+ { id: null, tier: "mid", relativeCost: 1, relativeLatency: 1 }
35
+ ];
36
+ function modelsFor(harness, capabilities) {
37
+ if (!capabilities.modelSelection) return DEFAULT_ONLY;
38
+ return MODEL_CATALOG[harness] ?? DEFAULT_ONLY;
39
+ }
40
+ function modelForTier(harness, tier) {
41
+ return MODEL_CATALOG[harness]?.find((entry) => entry.tier === tier) ?? null;
42
+ }
43
+
44
+ // src/routing/policy.ts
45
+ var RECOMMENDED_POLICY_VERSION = "2";
46
+ var RECOMMENDED_POLICY = {
47
+ analyze: {
48
+ preferredTier: "fast",
49
+ optimizeFor: "cost-speed",
50
+ affinityHarness: "codex-cli"
51
+ },
52
+ generate: {
53
+ preferredTier: "mid",
54
+ optimizeFor: "balanced",
55
+ affinityHarness: "claude-code"
56
+ },
57
+ prd: {
58
+ preferredTier: "mid",
59
+ optimizeFor: "balanced",
60
+ affinityHarness: "claude-code"
61
+ },
62
+ plan: {
63
+ preferredTier: "fast",
64
+ optimizeFor: "cost-speed",
65
+ affinityHarness: "codex-cli"
66
+ },
67
+ execute: {
68
+ preferredTier: "mid",
69
+ escalateTo: "strong",
70
+ optimizeFor: "time-to-correct",
71
+ affinityHarness: "claude-code"
72
+ },
73
+ review: {
74
+ preferredTier: "strong",
75
+ optimizeFor: "quality",
76
+ independentFrom: "execute",
77
+ affinityHarness: "codex-cli"
78
+ },
79
+ pr: {
80
+ preferredTier: "fast",
81
+ optimizeFor: "cost-speed",
82
+ affinityHarness: "codex-cli"
83
+ },
84
+ "pr-review": {
85
+ preferredTier: "strong",
86
+ optimizeFor: "quality",
87
+ affinityHarness: "codex-cli"
88
+ }
89
+ };
90
+ var PROVIDERS = {
91
+ "claude-code": "claude",
92
+ "codex-cli": "codex",
93
+ "cursor-cli": "cursor",
94
+ "antigravity-cli": "antigravity"
95
+ };
96
+ function recommendedFor(phase) {
97
+ return RECOMMENDED_POLICY[phase];
98
+ }
99
+ function recommendedTarget(phase) {
100
+ const entry = recommendedFor(phase);
101
+ const harness = entry.affinityHarness;
102
+ if (harness === void 0) return null;
103
+ const model = modelForTier(harness, entry.preferredTier);
104
+ const provider = PROVIDERS[harness];
105
+ if (model === null || provider === void 0) return null;
106
+ return { harness, provider, model: model.id, tier: entry.preferredTier };
107
+ }
108
+
109
+ // src/routing/priors.ts
110
+ var PRIORS_VERSION = "2";
111
+ function tiers(mid) {
112
+ return { fast: Math.max(0, mid - 0.25), mid, strong: Math.min(1, mid + 0.12) };
113
+ }
114
+ function harnesses(values) {
115
+ return Object.fromEntries(Object.entries(values).map(([harness, mid]) => [harness, tiers(mid)]));
116
+ }
117
+ var PRIORS = {
118
+ bugfix: harnesses({
119
+ "claude-code": 0.7,
120
+ "codex-cli": 0.95,
121
+ "cursor-cli": 0.65,
122
+ "antigravity-cli": 0.6
123
+ }),
124
+ feature: harnesses({
125
+ "claude-code": 0.85,
126
+ "codex-cli": 0.8,
127
+ "cursor-cli": 0.7,
128
+ "antigravity-cli": 0.65
129
+ }),
130
+ refactor: harnesses({
131
+ "claude-code": 0.75,
132
+ "codex-cli": 0.9,
133
+ "cursor-cli": 0.65,
134
+ "antigravity-cli": 0.6
135
+ }),
136
+ docs: harnesses({
137
+ "claude-code": 0.8,
138
+ "codex-cli": 0.7,
139
+ "cursor-cli": 0.75,
140
+ "antigravity-cli": 0.7
141
+ }),
142
+ test: harnesses({
143
+ "claude-code": 0.7,
144
+ "codex-cli": 0.9,
145
+ "cursor-cli": 0.65,
146
+ "antigravity-cli": 0.6
147
+ }),
148
+ infra: harnesses({
149
+ "claude-code": 0.8,
150
+ "codex-cli": 0.75,
151
+ "cursor-cli": 0.6,
152
+ "antigravity-cli": 0.55
153
+ }),
154
+ analysis: harnesses({
155
+ "claude-code": 0.95,
156
+ "codex-cli": 0.6,
157
+ "cursor-cli": 0.7,
158
+ "antigravity-cli": 0.65
159
+ })
160
+ };
161
+ function priorFor(taskClass, harness, tier) {
162
+ return PRIORS[taskClass][harness]?.[tier] ?? 0.5;
163
+ }
164
+
165
+ // src/routing/analyze.ts
166
+ var RISK_PATHS = [/auth/i, /migrat/i, /infra/i, /\.github\//i, /permission/i, /secret/i];
167
+ function analyzeTask(signals = {}) {
168
+ const hay = [
169
+ signals.title ?? "",
170
+ signals.body ?? "",
171
+ ...signals.labels ?? [],
172
+ ...signals.paths ?? []
173
+ ].join(" ").toLowerCase();
174
+ const taskClass = classify(hay, signals);
175
+ const risk = RISK_PATHS.some(
176
+ (pattern) => (signals.paths ?? []).some((path) => pattern.test(path))
177
+ ) ? "high" : /security|auth|migrat/.test(hay) ? "high" : /refactor|large|epic/.test(hay) ? "medium" : "low";
178
+ return { taskClass, risk };
179
+ }
180
+ function classify(hay, signals) {
181
+ if (/\bdocs?\b|readme|changelog/.test(hay)) return "docs";
182
+ if (/\btest|spec|coverage/.test(hay)) return "test";
183
+ if (/\bcie?|deploy|infra|workflow|docker/.test(hay)) return "infra";
184
+ if (/\banaly[sz]e|investigat|research/.test(hay)) return "analysis";
185
+ if (/\bbug|fix|regres+ion|crash/.test(hay)) return "bugfix";
186
+ if (/\brefactor|cleanup|extract/.test(hay)) return "refactor";
187
+ if (/\bfeat|feature|add |implement/.test(hay)) return "feature";
188
+ if ((signals.labels ?? []).some((label) => /bug/i.test(label))) return "bugfix";
189
+ if ((signals.labels ?? []).some((label) => /enhancement|feature/i.test(label))) return "feature";
190
+ return "feature";
191
+ }
192
+
193
+ // src/routing/capabilities.ts
194
+ function filterEligible(input) {
195
+ const reasons = [];
196
+ let eligible = true;
197
+ if (input.requiresExtraDirectories && input.capabilities.extraDirectories === "none") {
198
+ reasons.push("MISSING_CAPABILITY:extraDirectories");
199
+ reasons.push("CAPABILITY_MISMATCH");
200
+ eligible = false;
201
+ }
202
+ const readiness = input.readiness;
203
+ if (readiness !== void 0 && readiness !== null) {
204
+ if (!readiness.installed) {
205
+ reasons.push("PROVIDER_NOT_INSTALLED");
206
+ eligible = false;
207
+ } else if (readiness.cooldownUntil !== null && Date.parse(readiness.cooldownUntil) > Date.parse(readiness.observedAt)) {
208
+ reasons.push("PROVIDER_COOLDOWN");
209
+ eligible = false;
210
+ } else if (readiness.authentication === "failed") {
211
+ reasons.push("AUTHENTICATION_FAILED");
212
+ reasons.push("PROVIDER_UNAVAILABLE");
213
+ eligible = false;
214
+ } else if (readiness.state === "unavailable") {
215
+ reasons.push("PROVIDER_UNAVAILABLE");
216
+ eligible = false;
217
+ } else if (readiness.authentication === "unverified" || readiness.state === "conditional") {
218
+ reasons.push("AUTHENTICATION_UNVERIFIED");
219
+ reasons.push("READINESS_CONDITIONAL");
220
+ if (input.allowConditional === false) {
221
+ reasons.push("PROVIDER_UNAVAILABLE");
222
+ eligible = false;
223
+ }
224
+ } else {
225
+ reasons.push("READINESS_CONFIRMED");
226
+ }
227
+ const modelAccess = readiness.models[0]?.access;
228
+ if (modelAccess === "denied") {
229
+ reasons.push("MODEL_NOT_ACCESSIBLE");
230
+ eligible = false;
231
+ } else if (modelAccess === "unverified") {
232
+ reasons.push("MODEL_ACCESS_UNVERIFIED");
233
+ }
234
+ }
235
+ return { eligible, reasonCodes: reasons };
236
+ }
237
+
238
+ // src/routing/score.ts
239
+ var DELTA = 0.2;
240
+ var MIN_SAMPLE_SIZE = 8;
241
+ var PROFILE_WEIGHTS = {
242
+ economy: { quality: 0.5, cost: 0.4, latency: 0.1 },
243
+ balanced: { quality: 0.6, cost: 0.25, latency: 0.15 },
244
+ quality: { quality: 0.85, cost: 0.05, latency: 0.1 },
245
+ speed: { quality: 0.45, cost: 0.1, latency: 0.45 }
246
+ };
247
+ function clampLearned(value) {
248
+ return Math.max(-DELTA, Math.min(DELTA, value));
249
+ }
250
+ function readinessMultiplier(state) {
251
+ if (state === "ready") return 1;
252
+ if (state === "conditional") return 0.72;
253
+ if (state === "unavailable") return 0;
254
+ return 1;
255
+ }
256
+ function scoreCandidates(inputs) {
257
+ const profile = inputs[0]?.profile ?? "balanced";
258
+ const scored = inputs.map((input) => {
259
+ const prior = priorFor(input.taskClass, input.harness, input.tier);
260
+ const samples = input.samples ?? 0;
261
+ const rawLearned = samples >= MIN_SAMPLE_SIZE ? input.learned ?? 0 : 0;
262
+ const learned = clampLearned(rawLearned);
263
+ const weights = PROFILE_WEIGHTS[profile];
264
+ const costScore = 1 / input.relativeCost;
265
+ const latencyScore = 1 / input.relativeLatency;
266
+ const preferenceBonus = (input.preferredTierMatch === true ? 0.12 : 0) + (input.affinityMatch === true ? 0.08 : 0);
267
+ const score = input.eligible ? ((prior + learned) * weights.quality + costScore * weights.cost + latencyScore * weights.latency + preferenceBonus) * readinessMultiplier(input.readinessState) : 0;
268
+ const reasonCodes = [...input.reasonCodes];
269
+ if (input.eligible && samples === 0) reasonCodes.push("COLD_START");
270
+ if (input.eligible && learned > 0) reasonCodes.push("HIGH_HISTORICAL_SUCCESS");
271
+ return {
272
+ harness: input.harness,
273
+ provider: input.provider,
274
+ model: input.model ?? null,
275
+ tier: input.tier,
276
+ relativeCost: input.relativeCost,
277
+ relativeLatency: input.relativeLatency,
278
+ eligible: input.eligible,
279
+ prior,
280
+ learned,
281
+ samples,
282
+ score,
283
+ reasonCodes
284
+ };
285
+ });
286
+ return scored.sort((a, b) => {
287
+ if (b.score !== a.score) return b.score - a.score;
288
+ return a.harness.localeCompare(b.harness);
289
+ });
290
+ }
291
+ function pickSelected(candidates) {
292
+ const eligible = candidates.filter((candidate) => candidate.eligible);
293
+ if (eligible.length === 0) {
294
+ throw new Error(
295
+ `No eligible routing candidate: ${candidates.map((c) => `${c.harness} (${c.reasonCodes.join(",")})`).join("; ")}`
296
+ );
297
+ }
298
+ return eligible[0];
299
+ }
300
+
301
+ // src/routing/decide.ts
302
+ var CAPS = {
303
+ "claude-code": CLAUDE_CAPABILITIES,
304
+ "codex-cli": CODEX_CAPABILITIES,
305
+ "cursor-cli": CURSOR_CAPABILITIES,
306
+ "antigravity-cli": ANTIGRAVITY_CAPABILITIES
307
+ };
308
+ var PROVIDER = {
309
+ "claude-code": "claude",
310
+ "codex-cli": "codex",
311
+ "cursor-cli": "cursor",
312
+ "antigravity-cli": "antigravity"
313
+ };
314
+ function decideRouting(input) {
315
+ if (input.mode === "off") return null;
316
+ const analyzed = analyzeTask(input.signals ?? {});
317
+ const profile = input.profile ?? "balanced";
318
+ const policyVersion = `${PRIORS_VERSION}:${MODEL_CATALOG_VERSION}:${input.policy === "recommended" ? RECOMMENDED_POLICY_VERSION : "adaptive"}`;
319
+ if (input.skipScore) {
320
+ return {
321
+ policyVersion,
322
+ profile,
323
+ taskClass: analyzed.taskClass,
324
+ risk: analyzed.risk,
325
+ mode: input.mode,
326
+ candidates: [],
327
+ selected: {
328
+ harness: input.actualHarness,
329
+ provider: input.actualProvider ?? PROVIDER[input.actualHarness] ?? input.actualHarness,
330
+ model: input.actualModel ?? null
331
+ },
332
+ actual: {
333
+ harness: input.actualHarness,
334
+ provider: input.actualProvider ?? PROVIDER[input.actualHarness] ?? input.actualHarness,
335
+ model: input.actualModel ?? null
336
+ },
337
+ reasonCodes: ["EXPLICIT_CONFIG"]
338
+ };
339
+ }
340
+ const recommendation = input.policy === "recommended" ? recommendedFor(input.phase) : null;
341
+ const allowConditional = recommendation?.allowConditional !== false;
342
+ const scored = scoreCandidates(
343
+ Object.keys(CAPS).flatMap((harness) => {
344
+ const providerId = PROVIDER[harness];
345
+ const readiness = input.readiness === void 0 || input.readiness === null ? null : input.readiness.providers[providerId] ?? null;
346
+ const eligibility = filterEligible({
347
+ harness,
348
+ capabilities: CAPS[harness],
349
+ phase: input.phase,
350
+ requiresExtraDirectories: input.requiresExtraDirectories === true,
351
+ readiness,
352
+ allowConditional
353
+ });
354
+ return modelsFor(harness, CAPS[harness]).map((model) => {
355
+ const reasonCodes = [...eligibility.reasonCodes];
356
+ const preferredTierMatch = recommendation !== null && model.tier === recommendation.preferredTier;
357
+ const affinityMatch = recommendation !== null && recommendation.affinityHarness === harness;
358
+ if (preferredTierMatch) reasonCodes.push("RECOMMENDED_POLICY");
359
+ if (affinityMatch) reasonCodes.push("HARNESS_AFFINITY");
360
+ if (model.tier === "fast" && analyzed.risk !== "high") {
361
+ reasonCodes.push("CHEAPER_TIER_SUFFICIENT");
362
+ }
363
+ if (model.tier === "strong" && (analyzed.risk === "high" || profile === "quality")) {
364
+ reasonCodes.push("STRONGER_TIER_FOR_RISK");
365
+ }
366
+ return {
367
+ harness,
368
+ provider: providerId,
369
+ model: model.id,
370
+ tier: model.tier,
371
+ relativeCost: model.relativeCost,
372
+ relativeLatency: model.relativeLatency,
373
+ eligible: eligibility.eligible,
374
+ reasonCodes,
375
+ taskClass: analyzed.taskClass,
376
+ profile,
377
+ readinessState: readiness?.state ?? null,
378
+ preferredTierMatch,
379
+ affinityMatch
380
+ };
381
+ });
382
+ })
383
+ );
384
+ const selected = pickSelected(scored);
385
+ return {
386
+ policyVersion,
387
+ profile,
388
+ taskClass: analyzed.taskClass,
389
+ risk: analyzed.risk,
390
+ mode: input.mode,
391
+ candidates: scored,
392
+ selected: {
393
+ harness: selected.harness,
394
+ provider: selected.provider,
395
+ model: selected.model ?? null,
396
+ tier: selected.tier
397
+ },
398
+ actual: {
399
+ harness: input.actualHarness,
400
+ provider: input.actualProvider ?? PROVIDER[input.actualHarness] ?? input.actualHarness,
401
+ model: input.actualModel ?? null
402
+ },
403
+ reasonCodes: selected.reasonCodes.includes("COLD_START") ? ["HIGH_PRIOR", ...selected.reasonCodes] : selected.reasonCodes
404
+ };
405
+ }
406
+
407
+ export {
408
+ MODEL_CATALOG_VERSION,
409
+ MODEL_CATALOG,
410
+ RECOMMENDED_POLICY_VERSION,
411
+ recommendedTarget,
412
+ PRIORS_VERSION,
413
+ decideRouting
414
+ };
415
+ //# sourceMappingURL=chunk-ZVZMWNCG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/routing/models.ts","../src/routing/policy.ts","../src/routing/priors.ts","../src/routing/analyze.ts","../src/routing/capabilities.ts","../src/routing/score.ts","../src/routing/decide.ts"],"sourcesContent":["import type { AgentCapabilities } from '../agents/types.js';\n\nexport const MODEL_CATALOG_VERSION = '1';\n\nexport type ModelTier = 'fast' | 'mid' | 'strong';\n\nexport interface ModelEntry {\n id: string | null;\n tier: ModelTier;\n relativeCost: number;\n relativeLatency: number;\n}\n\n/**\n * Deliberately hand-maintained. Harnesses do not expose a stable price/tier API,\n * so relative values are more durable than USD prices and keep the router pure.\n */\nexport const MODEL_CATALOG: Record<string, readonly ModelEntry[]> = {\n 'claude-code': [\n { id: 'haiku', tier: 'fast', relativeCost: 1, relativeLatency: 1 },\n { id: 'sonnet', tier: 'mid', relativeCost: 3.5, relativeLatency: 1.5 },\n { id: 'opus', tier: 'strong', relativeCost: 8, relativeLatency: 2.2 },\n ],\n 'codex-cli': [\n { id: 'gpt-5.6-luna', tier: 'fast', relativeCost: 1, relativeLatency: 1 },\n { id: 'gpt-5.6-terra', tier: 'mid', relativeCost: 3, relativeLatency: 1.45 },\n { id: 'gpt-5.6-sol', tier: 'strong', relativeCost: 7, relativeLatency: 2.1 },\n ],\n 'cursor-cli': [\n { id: 'auto-fast', tier: 'fast', relativeCost: 1, relativeLatency: 1 },\n { id: 'auto', tier: 'mid', relativeCost: 3, relativeLatency: 1.5 },\n { id: 'auto-strong', tier: 'strong', relativeCost: 7, relativeLatency: 2.1 },\n ],\n 'antigravity-cli': [\n { id: 'gemini-3.5-flash-low', tier: 'fast', relativeCost: 1, relativeLatency: 1 },\n { id: 'gemini-3.5-flash-medium', tier: 'mid', relativeCost: 2.5, relativeLatency: 1.4 },\n { id: 'gemini-3.5-pro-high', tier: 'strong', relativeCost: 6, relativeLatency: 2 },\n ],\n};\n\nconst DEFAULT_ONLY: readonly ModelEntry[] = [\n { id: null, tier: 'mid', relativeCost: 1, relativeLatency: 1 },\n];\n\nexport function modelsFor(harness: string, capabilities: AgentCapabilities): readonly ModelEntry[] {\n if (!capabilities.modelSelection) return DEFAULT_ONLY;\n return MODEL_CATALOG[harness] ?? DEFAULT_ONLY;\n}\n\nexport function modelForTier(harness: string, tier: ModelTier): ModelEntry | null {\n return MODEL_CATALOG[harness]?.find((entry) => entry.tier === tier) ?? null;\n}\n","import type { AgentPhase, AgentProviderId } from '../agents/types.js';\nimport { type ModelTier, modelForTier } from './models.js';\nimport type { ExecutionTarget } from './types.js';\n\nexport const RECOMMENDED_POLICY_VERSION = '2';\n\nexport type OptimizeFor = 'cost-speed' | 'time-to-correct' | 'quality' | 'balanced';\n\n/**\n * Phase objectives for the opinionated policy. Affinity is a soft prior /\n * tie-break — never an eligibility filter that eliminates other harnesses.\n */\nexport interface RecommendedPolicyEntry {\n preferredTier: ModelTier;\n optimizeFor: OptimizeFor;\n escalateTo?: ModelTier;\n independentFrom?: AgentPhase;\n /** When true (default), conditional providers may win if no ready peer exists. */\n allowConditional?: boolean;\n /** Soft harness affinity for scoring — not a hard pin. */\n affinityHarness?: string;\n}\n\n/** The token-economy guidance from docs/agents.md, made executable and reviewable. */\nexport const RECOMMENDED_POLICY: Record<AgentPhase, RecommendedPolicyEntry> = {\n analyze: {\n preferredTier: 'fast',\n optimizeFor: 'cost-speed',\n affinityHarness: 'codex-cli',\n },\n generate: {\n preferredTier: 'mid',\n optimizeFor: 'balanced',\n affinityHarness: 'claude-code',\n },\n prd: {\n preferredTier: 'mid',\n optimizeFor: 'balanced',\n affinityHarness: 'claude-code',\n },\n plan: {\n preferredTier: 'fast',\n optimizeFor: 'cost-speed',\n affinityHarness: 'codex-cli',\n },\n execute: {\n preferredTier: 'mid',\n escalateTo: 'strong',\n optimizeFor: 'time-to-correct',\n affinityHarness: 'claude-code',\n },\n review: {\n preferredTier: 'strong',\n optimizeFor: 'quality',\n independentFrom: 'execute',\n affinityHarness: 'codex-cli',\n },\n pr: {\n preferredTier: 'fast',\n optimizeFor: 'cost-speed',\n affinityHarness: 'codex-cli',\n },\n 'pr-review': {\n preferredTier: 'strong',\n optimizeFor: 'quality',\n affinityHarness: 'codex-cli',\n },\n};\n\nconst PROVIDERS: Record<string, AgentProviderId> = {\n 'claude-code': 'claude',\n 'codex-cli': 'codex',\n 'cursor-cli': 'cursor',\n 'antigravity-cli': 'antigravity',\n};\n\nexport function recommendedFor(phase: AgentPhase): RecommendedPolicyEntry {\n return RECOMMENDED_POLICY[phase];\n}\n\n/**\n * Illustrative affinity target for `routing explain`. The live decision may\n * pick a different harness when readiness or score says so.\n */\nexport function recommendedTarget(phase: AgentPhase): ExecutionTarget | null {\n const entry = recommendedFor(phase);\n const harness = entry.affinityHarness;\n if (harness === undefined) return null;\n const model = modelForTier(harness, entry.preferredTier);\n const provider = PROVIDERS[harness];\n if (model === null || provider === undefined) return null;\n return { harness, provider, model: model.id, tier: entry.preferredTier };\n}\n","import type { ModelTier } from './models.js';\nimport type { TaskClass } from './types.js';\n\n/** Bump when a cell's provenance changes. */\nexport const PRIORS_VERSION = '2';\n\n/**\n * Cold-start priors. Provenance: author judgement on 2026-08-30 from the\n * #79 baseline and the #76 capability matrix — not measured affinity.\n */\ntype HarnessPriors = Record<string, Record<ModelTier, number>>;\n\nfunction tiers(mid: number): Record<ModelTier, number> {\n return { fast: Math.max(0, mid - 0.25), mid, strong: Math.min(1, mid + 0.12) };\n}\n\nfunction harnesses(values: Record<string, number>): HarnessPriors {\n return Object.fromEntries(Object.entries(values).map(([harness, mid]) => [harness, tiers(mid)]));\n}\n\nexport const PRIORS: Record<TaskClass, HarnessPriors> = {\n bugfix: harnesses({\n 'claude-code': 0.7,\n 'codex-cli': 0.95,\n 'cursor-cli': 0.65,\n 'antigravity-cli': 0.6,\n }),\n feature: harnesses({\n 'claude-code': 0.85,\n 'codex-cli': 0.8,\n 'cursor-cli': 0.7,\n 'antigravity-cli': 0.65,\n }),\n refactor: harnesses({\n 'claude-code': 0.75,\n 'codex-cli': 0.9,\n 'cursor-cli': 0.65,\n 'antigravity-cli': 0.6,\n }),\n docs: harnesses({\n 'claude-code': 0.8,\n 'codex-cli': 0.7,\n 'cursor-cli': 0.75,\n 'antigravity-cli': 0.7,\n }),\n test: harnesses({\n 'claude-code': 0.7,\n 'codex-cli': 0.9,\n 'cursor-cli': 0.65,\n 'antigravity-cli': 0.6,\n }),\n infra: harnesses({\n 'claude-code': 0.8,\n 'codex-cli': 0.75,\n 'cursor-cli': 0.6,\n 'antigravity-cli': 0.55,\n }),\n analysis: harnesses({\n 'claude-code': 0.95,\n 'codex-cli': 0.6,\n 'cursor-cli': 0.7,\n 'antigravity-cli': 0.65,\n }),\n};\n\nexport function priorFor(taskClass: TaskClass, harness: string, tier: ModelTier): number {\n return PRIORS[taskClass][harness]?.[tier] ?? 0.5;\n}\n","import type { RiskLevel, TaskClass, TaskSignals } from './types.js';\n\nconst RISK_PATHS = [/auth/i, /migrat/i, /infra/i, /\\.github\\//i, /permission/i, /secret/i];\n\nexport interface AnalyzedTask {\n taskClass: TaskClass;\n risk: RiskLevel;\n}\n\n/** Deterministic. No model, no I/O. Every class is reachable. */\nexport function analyzeTask(signals: TaskSignals = {}): AnalyzedTask {\n const hay = [\n signals.title ?? '',\n signals.body ?? '',\n ...(signals.labels ?? []),\n ...(signals.paths ?? []),\n ]\n .join(' ')\n .toLowerCase();\n\n const taskClass = classify(hay, signals);\n const risk = RISK_PATHS.some((pattern) =>\n (signals.paths ?? []).some((path) => pattern.test(path)),\n )\n ? 'high'\n : /security|auth|migrat/.test(hay)\n ? 'high'\n : /refactor|large|epic/.test(hay)\n ? 'medium'\n : 'low';\n\n return { taskClass, risk };\n}\n\nfunction classify(hay: string, signals: TaskSignals): TaskClass {\n if (/\\bdocs?\\b|readme|changelog/.test(hay)) return 'docs';\n if (/\\btest|spec|coverage/.test(hay)) return 'test';\n if (/\\bcie?|deploy|infra|workflow|docker/.test(hay)) return 'infra';\n if (/\\banaly[sz]e|investigat|research/.test(hay)) return 'analysis';\n if (/\\bbug|fix|regres+ion|crash/.test(hay)) return 'bugfix';\n if (/\\brefactor|cleanup|extract/.test(hay)) return 'refactor';\n if (/\\bfeat|feature|add |implement/.test(hay)) return 'feature';\n if ((signals.labels ?? []).some((label) => /bug/i.test(label))) return 'bugfix';\n if ((signals.labels ?? []).some((label) => /enhancement|feature/i.test(label))) return 'feature';\n return 'feature';\n}\n","import type { ProviderReadiness } from '../agents/availability.js';\nimport type { AgentCapabilities, AgentPhase } from '../agents/types.js';\n\nexport interface EligibilityInput {\n harness: string;\n capabilities: AgentCapabilities;\n phase: AgentPhase;\n requiresExtraDirectories: boolean;\n readiness?: ProviderReadiness | null;\n /** Default true. When false, conditional/unverified providers are ineligible. */\n allowConditional?: boolean;\n}\n\nexport interface Eligibility {\n eligible: boolean;\n reasonCodes: string[];\n}\n\n/**\n * Restriction missing (`toolAllowlist`) is ignored. Enablement missing\n * (`extraDirectories`) is ineligible when the phase needs addDirs.\n * Readiness is injected by the caller — this module stays pure.\n */\nexport function filterEligible(input: EligibilityInput): Eligibility {\n const reasons: string[] = [];\n let eligible = true;\n\n if (input.requiresExtraDirectories && input.capabilities.extraDirectories === 'none') {\n reasons.push('MISSING_CAPABILITY:extraDirectories');\n reasons.push('CAPABILITY_MISMATCH');\n eligible = false;\n }\n\n const readiness = input.readiness;\n if (readiness !== undefined && readiness !== null) {\n if (!readiness.installed) {\n reasons.push('PROVIDER_NOT_INSTALLED');\n eligible = false;\n } else if (\n readiness.cooldownUntil !== null &&\n Date.parse(readiness.cooldownUntil) > Date.parse(readiness.observedAt)\n ) {\n reasons.push('PROVIDER_COOLDOWN');\n eligible = false;\n } else if (readiness.authentication === 'failed') {\n reasons.push('AUTHENTICATION_FAILED');\n reasons.push('PROVIDER_UNAVAILABLE');\n eligible = false;\n } else if (readiness.state === 'unavailable') {\n reasons.push('PROVIDER_UNAVAILABLE');\n eligible = false;\n } else if (readiness.authentication === 'unverified' || readiness.state === 'conditional') {\n reasons.push('AUTHENTICATION_UNVERIFIED');\n reasons.push('READINESS_CONDITIONAL');\n if (input.allowConditional === false) {\n reasons.push('PROVIDER_UNAVAILABLE');\n eligible = false;\n }\n } else {\n reasons.push('READINESS_CONFIRMED');\n }\n\n const modelAccess = readiness.models[0]?.access;\n if (modelAccess === 'denied') {\n reasons.push('MODEL_NOT_ACCESSIBLE');\n eligible = false;\n } else if (modelAccess === 'unverified') {\n reasons.push('MODEL_ACCESS_UNVERIFIED');\n }\n }\n\n return { eligible, reasonCodes: reasons };\n}\n","import type { ModelTier } from './models.js';\nimport { priorFor } from './priors.js';\nimport type { Candidate, RoutingProfile, TaskClass } from './types.js';\n\nexport const DELTA = 0.2;\nexport const MIN_SAMPLE_SIZE = 8;\n\nexport const PROFILE_WEIGHTS: Record<\n RoutingProfile,\n { quality: number; cost: number; latency: number }\n> = {\n economy: { quality: 0.5, cost: 0.4, latency: 0.1 },\n balanced: { quality: 0.6, cost: 0.25, latency: 0.15 },\n quality: { quality: 0.85, cost: 0.05, latency: 0.1 },\n speed: { quality: 0.45, cost: 0.1, latency: 0.45 },\n};\n\nexport interface ScoreInput {\n harness: string;\n provider: string;\n model?: string | null;\n tier: ModelTier;\n relativeCost: number;\n relativeLatency: number;\n eligible: boolean;\n reasonCodes: string[];\n taskClass: TaskClass;\n learned?: number;\n samples?: number;\n profile?: RoutingProfile;\n /** Observed cost status from #78; catalog-relative cost is always available. */\n costStatus?: 'reported' | 'estimated' | 'unknown';\n readinessState?: 'ready' | 'conditional' | 'unavailable' | null;\n preferredTierMatch?: boolean;\n affinityMatch?: boolean;\n}\n\nexport function clampLearned(value: number): number {\n return Math.max(-DELTA, Math.min(DELTA, value));\n}\n\nfunction readinessMultiplier(state: ScoreInput['readinessState']): number {\n if (state === 'ready') return 1;\n if (state === 'conditional') return 0.72;\n if (state === 'unavailable') return 0;\n return 1;\n}\n\nexport function scoreCandidates(inputs: readonly ScoreInput[]): Candidate[] {\n const profile = inputs[0]?.profile ?? 'balanced';\n const scored: Candidate[] = inputs.map((input) => {\n const prior = priorFor(input.taskClass, input.harness, input.tier);\n const samples = input.samples ?? 0;\n const rawLearned = samples >= MIN_SAMPLE_SIZE ? (input.learned ?? 0) : 0;\n const learned = clampLearned(rawLearned);\n const weights = PROFILE_WEIGHTS[profile];\n // This is catalog-relative ordering, not observed USD. An unknown reported\n // cost still contributes no measured-cost signal; the declared tier order\n // remains available to economy/balanced profiles.\n const costScore = 1 / input.relativeCost;\n const latencyScore = 1 / input.relativeLatency;\n const preferenceBonus =\n (input.preferredTierMatch === true ? 0.12 : 0) + (input.affinityMatch === true ? 0.08 : 0);\n const score = input.eligible\n ? ((prior + learned) * weights.quality +\n costScore * weights.cost +\n latencyScore * weights.latency +\n preferenceBonus) *\n readinessMultiplier(input.readinessState)\n : 0;\n const reasonCodes = [...input.reasonCodes];\n if (input.eligible && samples === 0) reasonCodes.push('COLD_START');\n if (input.eligible && learned > 0) reasonCodes.push('HIGH_HISTORICAL_SUCCESS');\n return {\n harness: input.harness,\n provider: input.provider,\n model: input.model ?? null,\n tier: input.tier,\n relativeCost: input.relativeCost,\n relativeLatency: input.relativeLatency,\n eligible: input.eligible,\n prior,\n learned,\n samples,\n score,\n reasonCodes,\n };\n });\n\n return scored.sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n return a.harness.localeCompare(b.harness);\n });\n}\n\nexport function pickSelected(candidates: readonly Candidate[]): Candidate {\n const eligible = candidates.filter((candidate) => candidate.eligible);\n if (eligible.length === 0) {\n throw new Error(\n `No eligible routing candidate: ${candidates.map((c) => `${c.harness} (${c.reasonCodes.join(',')})`).join('; ')}`,\n );\n }\n return eligible[0] as Candidate;\n}\n","import type { ReadinessSnapshot } from '../agents/availability.js';\nimport type { AgentPhase } from '../agents/types.js';\nimport {\n ANTIGRAVITY_CAPABILITIES,\n CLAUDE_CAPABILITIES,\n CODEX_CAPABILITIES,\n CURSOR_CAPABILITIES,\n} from '../agents/types.js';\nimport { analyzeTask } from './analyze.js';\nimport { filterEligible } from './capabilities.js';\nimport { MODEL_CATALOG_VERSION, modelsFor } from './models.js';\nimport { RECOMMENDED_POLICY_VERSION, recommendedFor } from './policy.js';\nimport { PRIORS_VERSION } from './priors.js';\nimport { pickSelected, scoreCandidates } from './score.js';\nimport type { RoutingDecision, RoutingMode, RoutingProfile, TaskSignals } from './types.js';\n\nconst CAPS = {\n 'claude-code': CLAUDE_CAPABILITIES,\n 'codex-cli': CODEX_CAPABILITIES,\n 'cursor-cli': CURSOR_CAPABILITIES,\n 'antigravity-cli': ANTIGRAVITY_CAPABILITIES,\n} as const;\n\nconst PROVIDER: Record<string, string> = {\n 'claude-code': 'claude',\n 'codex-cli': 'codex',\n 'cursor-cli': 'cursor',\n 'antigravity-cli': 'antigravity',\n};\n\nexport function decideRouting(input: {\n signals?: TaskSignals;\n phase: AgentPhase;\n actualHarness: string;\n actualProvider?: string;\n actualModel?: string | null;\n mode: RoutingMode;\n profile?: RoutingProfile;\n requiresExtraDirectories?: boolean;\n skipScore?: boolean;\n policy?: 'recommended';\n /** Injected inventory — router stays pure (no probes). */\n readiness?: ReadinessSnapshot | null;\n}): RoutingDecision | null {\n if (input.mode === 'off') return null;\n const analyzed = analyzeTask(input.signals ?? {});\n const profile = input.profile ?? 'balanced';\n const policyVersion = `${PRIORS_VERSION}:${MODEL_CATALOG_VERSION}:${input.policy === 'recommended' ? RECOMMENDED_POLICY_VERSION : 'adaptive'}`;\n\n if (input.skipScore) {\n return {\n policyVersion,\n profile,\n taskClass: analyzed.taskClass,\n risk: analyzed.risk,\n mode: input.mode,\n candidates: [],\n selected: {\n harness: input.actualHarness,\n provider: input.actualProvider ?? PROVIDER[input.actualHarness] ?? input.actualHarness,\n model: input.actualModel ?? null,\n },\n actual: {\n harness: input.actualHarness,\n provider: input.actualProvider ?? PROVIDER[input.actualHarness] ?? input.actualHarness,\n model: input.actualModel ?? null,\n },\n reasonCodes: ['EXPLICIT_CONFIG'],\n };\n }\n\n const recommendation = input.policy === 'recommended' ? recommendedFor(input.phase) : null;\n const allowConditional = recommendation?.allowConditional !== false;\n\n const scored = scoreCandidates(\n (Object.keys(CAPS) as (keyof typeof CAPS)[]).flatMap((harness) => {\n const providerId = PROVIDER[harness] as 'claude' | 'codex' | 'cursor' | 'antigravity';\n const readiness =\n input.readiness === undefined || input.readiness === null\n ? null\n : (input.readiness.providers[providerId] ?? null);\n const eligibility = filterEligible({\n harness,\n capabilities: CAPS[harness],\n phase: input.phase,\n requiresExtraDirectories: input.requiresExtraDirectories === true,\n readiness,\n allowConditional,\n });\n return modelsFor(harness, CAPS[harness]).map((model) => {\n const reasonCodes = [...eligibility.reasonCodes];\n const preferredTierMatch =\n recommendation !== null && model.tier === recommendation.preferredTier;\n const affinityMatch = recommendation !== null && recommendation.affinityHarness === harness;\n if (preferredTierMatch) reasonCodes.push('RECOMMENDED_POLICY');\n if (affinityMatch) reasonCodes.push('HARNESS_AFFINITY');\n if (model.tier === 'fast' && analyzed.risk !== 'high') {\n reasonCodes.push('CHEAPER_TIER_SUFFICIENT');\n }\n if (model.tier === 'strong' && (analyzed.risk === 'high' || profile === 'quality')) {\n reasonCodes.push('STRONGER_TIER_FOR_RISK');\n }\n return {\n harness,\n provider: providerId,\n model: model.id,\n tier: model.tier,\n relativeCost: model.relativeCost,\n relativeLatency: model.relativeLatency,\n eligible: eligibility.eligible,\n reasonCodes,\n taskClass: analyzed.taskClass,\n profile,\n readinessState: readiness?.state ?? null,\n preferredTierMatch,\n affinityMatch,\n };\n });\n }),\n );\n const selected = pickSelected(scored);\n return {\n policyVersion,\n profile,\n taskClass: analyzed.taskClass,\n risk: analyzed.risk,\n mode: input.mode,\n candidates: scored,\n selected: {\n harness: selected.harness,\n provider: selected.provider,\n model: selected.model ?? null,\n tier: selected.tier,\n },\n actual: {\n harness: input.actualHarness,\n provider: input.actualProvider ?? PROVIDER[input.actualHarness] ?? input.actualHarness,\n model: input.actualModel ?? null,\n },\n reasonCodes: selected.reasonCodes.includes('COLD_START')\n ? ['HIGH_PRIOR', ...selected.reasonCodes]\n : selected.reasonCodes,\n };\n}\n"],"mappings":"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","names":[]}