issue-flow 0.12.0 → 0.14.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 (197) hide show
  1. package/README.md +79 -274
  2. package/dist/agent-OX3KPHE4.js +30 -0
  3. package/dist/{analyze-OEET7KGE.js → analyze-WIND2SEB.js} +31 -16
  4. package/dist/analyze-WIND2SEB.js.map +1 -0
  5. package/dist/{apply-ZIA3C52S.js → apply-JNOI2LR4.js} +18 -7
  6. package/dist/{apply-ZIA3C52S.js.map → apply-JNOI2LR4.js.map} +1 -1
  7. package/dist/bench-B4VZON7E.js +910 -0
  8. package/dist/bench-B4VZON7E.js.map +1 -0
  9. package/dist/{chunk-FADTCQGM.js → chunk-2IQ6M4ZE.js} +94 -32
  10. package/dist/chunk-2IQ6M4ZE.js.map +1 -0
  11. package/dist/chunk-3BWZO4YI.js +141 -0
  12. package/dist/chunk-3BWZO4YI.js.map +1 -0
  13. package/dist/chunk-3WFZETIM.js +163 -0
  14. package/dist/chunk-3WFZETIM.js.map +1 -0
  15. package/dist/chunk-67YIU2VB.js +362 -0
  16. package/dist/chunk-67YIU2VB.js.map +1 -0
  17. package/dist/{chunk-QCPGHBSZ.js → chunk-6BENHR2I.js} +63 -21
  18. package/dist/chunk-6BENHR2I.js.map +1 -0
  19. package/dist/{chunk-BYZDPR7N.js → chunk-6QYMSNVA.js} +194 -235
  20. package/dist/chunk-6QYMSNVA.js.map +1 -0
  21. package/dist/{chunk-Y5ZDJ4PJ.js → chunk-76MMPJ53.js} +20 -10
  22. package/dist/chunk-76MMPJ53.js.map +1 -0
  23. package/dist/chunk-7Z4Y3VKM.js +26 -0
  24. package/dist/chunk-7Z4Y3VKM.js.map +1 -0
  25. package/dist/{chunk-3QHK4YQA.js → chunk-B72RQZBV.js} +346 -119
  26. package/dist/chunk-B72RQZBV.js.map +1 -0
  27. package/dist/chunk-BEZ5BA5U.js +625 -0
  28. package/dist/chunk-BEZ5BA5U.js.map +1 -0
  29. package/dist/chunk-BRCNQXYQ.js +74 -0
  30. package/dist/chunk-BRCNQXYQ.js.map +1 -0
  31. package/dist/chunk-CGKLE6WR.js +1203 -0
  32. package/dist/chunk-CGKLE6WR.js.map +1 -0
  33. package/dist/chunk-CRGIQFUQ.js +83 -0
  34. package/dist/chunk-CRGIQFUQ.js.map +1 -0
  35. package/dist/{chunk-NS6R37II.js → chunk-F6TOYSYY.js} +141 -12
  36. package/dist/chunk-F6TOYSYY.js.map +1 -0
  37. package/dist/chunk-G5EK2XRN.js +25 -0
  38. package/dist/chunk-G5EK2XRN.js.map +1 -0
  39. package/dist/chunk-HAKDLR6N.js +134 -0
  40. package/dist/chunk-HAKDLR6N.js.map +1 -0
  41. package/dist/chunk-J3SOTUVI.js +298 -0
  42. package/dist/chunk-J3SOTUVI.js.map +1 -0
  43. package/dist/chunk-JN6D3MY6.js +30 -0
  44. package/dist/chunk-JN6D3MY6.js.map +1 -0
  45. package/dist/{chunk-LAFNLLQP.js → chunk-KMRFRXIT.js} +5 -5
  46. package/dist/chunk-KT7JKOXB.js +72 -0
  47. package/dist/chunk-KT7JKOXB.js.map +1 -0
  48. package/dist/chunk-L6HSKTQE.js +77 -0
  49. package/dist/chunk-L6HSKTQE.js.map +1 -0
  50. package/dist/chunk-LBGHI4S2.js +1264 -0
  51. package/dist/chunk-LBGHI4S2.js.map +1 -0
  52. package/dist/chunk-LEW4QM74.js +180 -0
  53. package/dist/chunk-LEW4QM74.js.map +1 -0
  54. package/dist/{chunk-FJP3UQGD.js → chunk-LFEQIZLB.js} +115 -20
  55. package/dist/chunk-LFEQIZLB.js.map +1 -0
  56. package/dist/chunk-OOVG2KBY.js +77 -0
  57. package/dist/chunk-OOVG2KBY.js.map +1 -0
  58. package/dist/{chunk-56KS3TFQ.js → chunk-OR43364P.js} +115 -160
  59. package/dist/chunk-OR43364P.js.map +1 -0
  60. package/dist/chunk-P3LRUNC6.js +16 -0
  61. package/dist/chunk-P3LRUNC6.js.map +1 -0
  62. package/dist/{chunk-TSOLWK7Y.js → chunk-PBTA3QQX.js} +8 -7
  63. package/dist/{chunk-TSOLWK7Y.js.map → chunk-PBTA3QQX.js.map} +1 -1
  64. package/dist/{chunk-MJULIKQU.js → chunk-PHW2YV6N.js} +23 -47
  65. package/dist/chunk-PHW2YV6N.js.map +1 -0
  66. package/dist/{chunk-73ATPIYX.js → chunk-PZTWU277.js} +36 -71
  67. package/dist/chunk-PZTWU277.js.map +1 -0
  68. package/dist/{chunk-M5UCXTIT.js → chunk-QD4VOILZ.js} +22 -18
  69. package/dist/chunk-QD4VOILZ.js.map +1 -0
  70. package/dist/chunk-QJ5UZAH5.js +2718 -0
  71. package/dist/chunk-QJ5UZAH5.js.map +1 -0
  72. package/dist/chunk-QK7WUO7A.js +283 -0
  73. package/dist/chunk-QK7WUO7A.js.map +1 -0
  74. package/dist/{chunk-A4SLHOW7.js → chunk-QZVKRDJY.js} +27 -19
  75. package/dist/chunk-QZVKRDJY.js.map +1 -0
  76. package/dist/chunk-REO3PXXO.js +71 -0
  77. package/dist/chunk-REO3PXXO.js.map +1 -0
  78. package/dist/{chunk-EZATO3DW.js → chunk-RVO7L4FX.js} +594 -17
  79. package/dist/chunk-RVO7L4FX.js.map +1 -0
  80. package/dist/{chunk-XQUSIEKA.js → chunk-SZMHCEYV.js} +63 -14
  81. package/dist/chunk-SZMHCEYV.js.map +1 -0
  82. package/dist/chunk-TYRNTSPJ.js +243 -0
  83. package/dist/chunk-TYRNTSPJ.js.map +1 -0
  84. package/dist/chunk-UJ3L2MS7.js +238 -0
  85. package/dist/chunk-UJ3L2MS7.js.map +1 -0
  86. package/dist/chunk-V7MO5EDS.js +120 -0
  87. package/dist/chunk-V7MO5EDS.js.map +1 -0
  88. package/dist/chunk-WB2X37MO.js +415 -0
  89. package/dist/chunk-WB2X37MO.js.map +1 -0
  90. package/dist/{chunk-NTMMF5UD.js → chunk-X44FKNKP.js} +525 -252
  91. package/dist/chunk-X44FKNKP.js.map +1 -0
  92. package/dist/chunk-XEYH6ZZI.js +289 -0
  93. package/dist/chunk-XEYH6ZZI.js.map +1 -0
  94. package/dist/cli.js +267 -44
  95. package/dist/cli.js.map +1 -1
  96. package/dist/{config-PRJGWW7J.js → config-HMFMCY2M.js} +31 -5
  97. package/dist/contract-JH2WBIO6.js +8 -0
  98. package/dist/conventions-NJF2OPVQ.js +146 -0
  99. package/dist/conventions-NJF2OPVQ.js.map +1 -0
  100. package/dist/diagnostics-THH42ZMP.js +23 -0
  101. package/dist/execute-KFNNZZHI.js +35 -0
  102. package/dist/{generate-EGB4KV2B.js → generate-FW5C6NP7.js} +37 -20
  103. package/dist/{generate-EGB4KV2B.js.map → generate-FW5C6NP7.js.map} +1 -1
  104. package/dist/git-W72QQ6GT.js +33 -0
  105. package/dist/init-HTN4V67Q.js +24 -0
  106. package/dist/{operations-BYT626KQ.js → operations-BCFOBH42.js} +27 -15
  107. package/dist/{operations-BYT626KQ.js.map → operations-BCFOBH42.js.map} +1 -1
  108. package/dist/permissions-4AKNQZHK.js +18 -0
  109. package/dist/plan-SIZLGA4V.js +34 -0
  110. package/dist/{policy-6S4GFC76.js → policy-DT6Q6ZVM.js} +20 -6
  111. package/dist/policy-DT6Q6ZVM.js.map +1 -0
  112. package/dist/pr-OMWCGUOW.js +39 -0
  113. package/dist/pr-review-N24CZPKR.js +32 -0
  114. package/dist/pr-review-N24CZPKR.js.map +1 -0
  115. package/dist/prd-5OFTZAHJ.js +33 -0
  116. package/dist/prd-5OFTZAHJ.js.map +1 -0
  117. package/dist/ps-RFORTCUD.js +93 -0
  118. package/dist/ps-RFORTCUD.js.map +1 -0
  119. package/dist/recorder-KCCPMKQG.js +32 -0
  120. package/dist/recorder-KCCPMKQG.js.map +1 -0
  121. package/dist/registry-GLPXOMFG.js +15 -0
  122. package/dist/registry-GLPXOMFG.js.map +1 -0
  123. package/dist/{resume-PPCNQVVV.js → resume-M5RLKP4I.js} +55 -34
  124. package/dist/{resume-PPCNQVVV.js.map → resume-M5RLKP4I.js.map} +1 -1
  125. package/dist/review-YM4JAABY.js +35 -0
  126. package/dist/review-YM4JAABY.js.map +1 -0
  127. package/dist/routing-NNT5WKGX.js +94 -0
  128. package/dist/routing-NNT5WKGX.js.map +1 -0
  129. package/dist/run-PZUKHPQK.js +54 -0
  130. package/dist/run-PZUKHPQK.js.map +1 -0
  131. package/dist/session-publisher-T7EI3CIP.js +11 -0
  132. package/dist/session-publisher-T7EI3CIP.js.map +1 -0
  133. package/dist/{state-manager-2EDVDBAR.js → state-manager-GQH32C44.js} +4 -2
  134. package/dist/state-manager-GQH32C44.js.map +1 -0
  135. package/dist/usage-V2CHE5PY.js +177 -0
  136. package/dist/usage-V2CHE5PY.js.map +1 -0
  137. package/dist/{web-EF5WIIGG.js → web-EA3KGNFN.js} +45 -30
  138. package/dist/web-EA3KGNFN.js.map +1 -0
  139. package/package.json +6 -2
  140. package/prompts/execute.md +7 -8
  141. package/prompts/plan.md +4 -5
  142. package/prompts/pr.md +2 -2
  143. package/web/AGENTS.md +152 -13
  144. package/web/public/app.css +380 -109
  145. package/web/public/app.js +525 -25
  146. package/web/public/index.html +68 -1
  147. package/dist/analyze-OEET7KGE.js.map +0 -1
  148. package/dist/chunk-3QHK4YQA.js.map +0 -1
  149. package/dist/chunk-42PJFMAR.js +0 -605
  150. package/dist/chunk-42PJFMAR.js.map +0 -1
  151. package/dist/chunk-4JSOYE4G.js +0 -368
  152. package/dist/chunk-4JSOYE4G.js.map +0 -1
  153. package/dist/chunk-56KS3TFQ.js.map +0 -1
  154. package/dist/chunk-73ATPIYX.js.map +0 -1
  155. package/dist/chunk-A4SLHOW7.js.map +0 -1
  156. package/dist/chunk-BAUPQXPE.js +0 -173
  157. package/dist/chunk-BAUPQXPE.js.map +0 -1
  158. package/dist/chunk-BYZDPR7N.js.map +0 -1
  159. package/dist/chunk-CD5ULRVC.js +0 -615
  160. package/dist/chunk-CD5ULRVC.js.map +0 -1
  161. package/dist/chunk-DIDUVL6O.js +0 -1365
  162. package/dist/chunk-DIDUVL6O.js.map +0 -1
  163. package/dist/chunk-EZATO3DW.js.map +0 -1
  164. package/dist/chunk-FADTCQGM.js.map +0 -1
  165. package/dist/chunk-FJP3UQGD.js.map +0 -1
  166. package/dist/chunk-LWRSMTTZ.js +0 -18
  167. package/dist/chunk-LWRSMTTZ.js.map +0 -1
  168. package/dist/chunk-M5UCXTIT.js.map +0 -1
  169. package/dist/chunk-M66SJHQQ.js +0 -206
  170. package/dist/chunk-M66SJHQQ.js.map +0 -1
  171. package/dist/chunk-MJULIKQU.js.map +0 -1
  172. package/dist/chunk-NS6R37II.js.map +0 -1
  173. package/dist/chunk-NTMMF5UD.js.map +0 -1
  174. package/dist/chunk-QCPGHBSZ.js.map +0 -1
  175. package/dist/chunk-XQUSIEKA.js.map +0 -1
  176. package/dist/chunk-Y5ZDJ4PJ.js.map +0 -1
  177. package/dist/execute-XBNVL753.js +0 -18
  178. package/dist/init-AJHCXJBP.js +0 -10
  179. package/dist/plan-QOZ3RIO6.js +0 -21
  180. package/dist/policy-6S4GFC76.js.map +0 -1
  181. package/dist/pr-EBBHD2ZX.js +0 -26
  182. package/dist/pr-review-VVMW5PO4.js +0 -20
  183. package/dist/prd-JQSZF7PR.js +0 -21
  184. package/dist/review-3F6MARWH.js +0 -19
  185. package/dist/run-RXE5GDQO.js +0 -36
  186. package/dist/web-EF5WIIGG.js.map +0 -1
  187. /package/dist/{config-PRJGWW7J.js.map → agent-OX3KPHE4.js.map} +0 -0
  188. /package/dist/{chunk-LAFNLLQP.js.map → chunk-KMRFRXIT.js.map} +0 -0
  189. /package/dist/{execute-XBNVL753.js.map → config-HMFMCY2M.js.map} +0 -0
  190. /package/dist/{init-AJHCXJBP.js.map → contract-JH2WBIO6.js.map} +0 -0
  191. /package/dist/{plan-QOZ3RIO6.js.map → diagnostics-THH42ZMP.js.map} +0 -0
  192. /package/dist/{pr-EBBHD2ZX.js.map → execute-KFNNZZHI.js.map} +0 -0
  193. /package/dist/{pr-review-VVMW5PO4.js.map → git-W72QQ6GT.js.map} +0 -0
  194. /package/dist/{prd-JQSZF7PR.js.map → init-HTN4V67Q.js.map} +0 -0
  195. /package/dist/{review-3F6MARWH.js.map → permissions-4AKNQZHK.js.map} +0 -0
  196. /package/dist/{run-RXE5GDQO.js.map → plan-SIZLGA4V.js.map} +0 -0
  197. /package/dist/{state-manager-2EDVDBAR.js.map → pr-OMWCGUOW.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/routing/budget.ts","../src/agents/health.ts","../src/agents/select.ts","../src/agents/invoke.ts","../src/core/decompose.ts","../src/core/headless.ts"],"sourcesContent":["import type { CostRecord, StopReason } from '../telemetry/types.js';\n\nexport interface RoutingCeilings {\n maxCostUsdPerIssue: number | null;\n maxDurationMsPerIssue: number | null;\n maxExecutionsPerIssue: number | null;\n onCeiling: 'block';\n}\n\nexport const DEFAULT_CEILINGS: RoutingCeilings = {\n maxCostUsdPerIssue: null,\n maxDurationMsPerIssue: null,\n maxExecutionsPerIssue: null,\n onCeiling: 'block',\n};\n\nexport interface SpentSnapshot {\n /** Observed reported USD only. `unknown` / `estimated` do not fill this. */\n reportedUsd: number;\n costStatus: CostRecord['status'];\n durationMs: number;\n executions: number;\n}\n\nexport type CeilingBinding = 'cost' | 'duration' | 'executions';\n\nexport type CeilingVerdict =\n | { ok: true; binding: null }\n | {\n ok: false;\n stopReason: Extract<StopReason, 'max_cost' | 'max_duration' | 'max_attempts'>;\n binding: CeilingBinding;\n onCeiling: 'block';\n numbers: { spent: number; ceiling: number };\n /** Which ceiling is actually in force when cost is unknown. */\n enforced: CeilingBinding[];\n };\n\n/**\n * Single choke point. A harness flag is never a substitute: a runner that\n * ignores `--max-budget-usd` still stops here.\n */\nexport function evaluateCeilings(input: {\n ceilings?: Partial<RoutingCeilings> | undefined;\n spent: SpentSnapshot;\n}): CeilingVerdict {\n const ceilings = { ...DEFAULT_CEILINGS, ...input.ceilings };\n const enforced: CeilingBinding[] = [];\n if (ceilings.maxCostUsdPerIssue !== null && input.spent.costStatus === 'reported') {\n enforced.push('cost');\n }\n if (ceilings.maxDurationMsPerIssue !== null) enforced.push('duration');\n if (ceilings.maxExecutionsPerIssue !== null) enforced.push('executions');\n\n if (\n ceilings.maxCostUsdPerIssue !== null &&\n input.spent.costStatus === 'reported' &&\n input.spent.reportedUsd >= ceilings.maxCostUsdPerIssue\n ) {\n return {\n ok: false,\n stopReason: 'max_cost',\n binding: 'cost',\n onCeiling: 'block',\n numbers: { spent: input.spent.reportedUsd, ceiling: ceilings.maxCostUsdPerIssue },\n enforced,\n };\n }\n\n if (\n ceilings.maxDurationMsPerIssue !== null &&\n input.spent.durationMs >= ceilings.maxDurationMsPerIssue\n ) {\n return {\n ok: false,\n stopReason: 'max_duration',\n binding: 'duration',\n onCeiling: 'block',\n numbers: { spent: input.spent.durationMs, ceiling: ceilings.maxDurationMsPerIssue },\n enforced,\n };\n }\n\n if (\n ceilings.maxExecutionsPerIssue !== null &&\n input.spent.executions >= ceilings.maxExecutionsPerIssue\n ) {\n return {\n ok: false,\n stopReason: 'max_attempts',\n binding: 'executions',\n onCeiling: 'block',\n numbers: { spent: input.spent.executions, ceiling: ceilings.maxExecutionsPerIssue },\n enforced,\n };\n }\n\n return { ok: true, binding: null };\n}\n\nexport function spendFromCost(cost: CostRecord): Pick<SpentSnapshot, 'reportedUsd' | 'costStatus'> {\n if (cost.status === 'reported') {\n return { reportedUsd: cost.amount, costStatus: 'reported' };\n }\n return { reportedUsd: 0, costStatus: cost.status };\n}\n\n/** `blocked` is only left by a human — the machine never unblocks a ceiling. */\nexport function canLeaveBlocked(actor: string): boolean {\n return actor === 'human';\n}\n","import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport type { ClassifiedFailure, FailureKind } from '../resilience/errors.js';\nimport {\n type ProviderHealthRecord,\n type ProvidersHealth,\n providersHealthSchema,\n type ResilienceProvidersConfig,\n} from '../storage/schemas.js';\n\nexport const DEFAULT_PROVIDER_COOLDOWN_MS = 60_000;\nexport const DEFAULT_PROVIDER_MAX_COOLDOWN_MS = 30 * 60_000;\nexport const DEFAULT_PROVIDER_FAILURE_WINDOW_MS = 5 * 60_000;\nexport const DEFAULT_PROVIDER_FAILURES_TO_TRIP = 3;\n\nexport interface ProviderHealthOptions {\n now?: () => number;\n config?: ResilienceProvidersConfig;\n}\n\nexport interface ResolvedProviderHealthConfig {\n cooldownMs: number;\n maxCooldownMs: number;\n failureWindowMs: number;\n failuresToTrip: number;\n}\n\nexport function resolveProviderHealthConfig(\n config: ResilienceProvidersConfig = {},\n): ResolvedProviderHealthConfig {\n return {\n cooldownMs: Math.max(0, config.cooldownMs ?? DEFAULT_PROVIDER_COOLDOWN_MS),\n maxCooldownMs: Math.max(\n config.cooldownMs ?? DEFAULT_PROVIDER_COOLDOWN_MS,\n config.maxCooldownMs ?? DEFAULT_PROVIDER_MAX_COOLDOWN_MS,\n ),\n failureWindowMs: Math.max(1, config.failureWindowMs ?? DEFAULT_PROVIDER_FAILURE_WINDOW_MS),\n failuresToTrip: Math.max(\n 1,\n Math.trunc(config.failuresToTrip ?? DEFAULT_PROVIDER_FAILURES_TO_TRIP),\n ),\n };\n}\n\nfunction emptyHealth(): ProvidersHealth {\n return providersHealthSchema.parse({});\n}\n\nfunction emptyRecord(): ProviderHealthRecord {\n return providersHealthSchema.parse({ providers: { provider: {} } }).providers.provider;\n}\n\nexport async function readProvidersHealth(filePath: string): Promise<ProvidersHealth> {\n try {\n return providersHealthSchema.parse(JSON.parse(await readFile(filePath, 'utf-8')));\n } catch {\n return emptyHealth();\n }\n}\n\nasync function writeProvidersHealth(filePath: string, value: ProvidersHealth): Promise<void> {\n await mkdir(dirname(filePath), { recursive: true });\n const tmp = `${filePath}.tmp-${process.pid}`;\n await writeFile(tmp, `${JSON.stringify(value, null, 2)}\\n`, 'utf-8');\n await rename(tmp, filePath);\n}\n\nasync function updateRecord(\n filePath: string,\n provider: string,\n update: (record: ProviderHealthRecord) => ProviderHealthRecord,\n): Promise<ProviderHealthRecord> {\n const health = await readProvidersHealth(filePath);\n const next = update(health.providers[provider] ?? emptyRecord());\n await writeProvidersHealth(filePath, {\n ...health,\n providers: { ...health.providers, [provider]: next },\n });\n return next;\n}\n\nfunction cooldownDelay(level: number, config: ResolvedProviderHealthConfig): number {\n return Math.min(config.maxCooldownMs, config.cooldownMs * 2 ** Math.max(0, level));\n}\n\nconst BREAKER_KINDS = new Set<FailureKind>([\n 'timeout',\n 'stalled',\n 'provider_down',\n 'provider_crash',\n]);\n\nexport async function recordProviderFailure(\n filePath: string,\n provider: string,\n failure: ClassifiedFailure,\n options: ProviderHealthOptions = {},\n): Promise<ProviderHealthRecord> {\n const nowMs = options.now?.() ?? Date.now();\n const at = new Date(nowMs).toISOString();\n const config = resolveProviderHealthConfig(options.config);\n\n return updateRecord(filePath, provider, (record) => {\n const failures = [\n ...record.failures.filter((entry) => {\n const timestamp = Date.parse(entry.at);\n return Number.isFinite(timestamp) && nowMs - timestamp <= config.failureWindowMs;\n }),\n { at, kind: failure.kind },\n ];\n const consecutiveFailures = record.consecutiveFailures + 1;\n\n if (failure.kind === 'authentication') {\n return {\n ...record,\n status: 'auth_failed',\n failures,\n consecutiveFailures,\n cooldownUntil: null,\n lastFailureKind: failure.kind,\n lastFailureAt: at,\n probeInFlight: false,\n probeStartedAt: null,\n };\n }\n\n if (failure.kind === 'rate_limit') {\n const delay = failure.retryAfterMs ?? cooldownDelay(record.cooldownLevel, config);\n return {\n ...record,\n status: 'rate_limited',\n failures,\n consecutiveFailures,\n cooldownLevel:\n failure.retryAfterMs === undefined ? record.cooldownLevel + 1 : record.cooldownLevel,\n cooldownUntil: new Date(nowMs + delay).toISOString(),\n lastFailureKind: failure.kind,\n lastFailureAt: at,\n probeInFlight: false,\n probeStartedAt: null,\n };\n }\n\n if (BREAKER_KINDS.has(failure.kind)) {\n const recentProviderFailures = failures.filter((entry) =>\n BREAKER_KINDS.has(entry.kind),\n ).length;\n const unavailable =\n record.status === 'half_open' || recentProviderFailures >= config.failuresToTrip;\n const delay = unavailable ? cooldownDelay(record.cooldownLevel, config) : 0;\n return {\n ...record,\n status: unavailable ? 'unavailable' : 'degraded',\n failures,\n consecutiveFailures,\n cooldownLevel: unavailable ? record.cooldownLevel + 1 : record.cooldownLevel,\n cooldownUntil: unavailable ? new Date(nowMs + delay).toISOString() : null,\n lastFailureKind: failure.kind,\n lastFailureAt: at,\n probeInFlight: false,\n probeStartedAt: null,\n };\n }\n\n // Network and task/repository/configuration failures do not describe the\n // provider's health. Keep the breaker state, but retain the diagnosis for\n // audit and dashboard surfaces.\n return {\n ...record,\n lastFailureKind: failure.kind,\n lastFailureAt: at,\n probeInFlight: false,\n probeStartedAt: null,\n };\n });\n}\n\nexport async function recordProviderSuccess(\n filePath: string,\n provider: string,\n options: Pick<ProviderHealthOptions, 'now'> = {},\n): Promise<ProviderHealthRecord> {\n const at = new Date(options.now?.() ?? Date.now()).toISOString();\n return updateRecord(filePath, provider, (record) => ({\n ...record,\n status: 'healthy',\n failures: [],\n consecutiveFailures: 0,\n cooldownLevel: 0,\n cooldownUntil: null,\n lastFailureKind: null,\n lastSuccessAt: at,\n probeInFlight: false,\n probeStartedAt: null,\n }));\n}\n\n/** Open the circuit when retry policy asks for failover before the trip count. */\nexport async function openProviderCircuit(\n filePath: string,\n provider: string,\n options: ProviderHealthOptions = {},\n): Promise<ProviderHealthRecord> {\n const nowMs = options.now?.() ?? Date.now();\n const config = resolveProviderHealthConfig(options.config);\n return updateRecord(filePath, provider, (record) => {\n if (record.status === 'unavailable' || record.status === 'rate_limited') return record;\n const delay = cooldownDelay(record.cooldownLevel, config);\n return {\n ...record,\n status: 'unavailable',\n cooldownLevel: record.cooldownLevel + 1,\n cooldownUntil: new Date(nowMs + delay).toISOString(),\n probeInFlight: false,\n probeStartedAt: null,\n };\n });\n}\n\nexport interface HalfOpenResult {\n acquired: boolean;\n record: ProviderHealthRecord;\n}\n\n/** Atomically enough for the project-level single-run lock: one half-open probe per provider. */\nexport async function acquireHalfOpenProbe(\n filePath: string,\n provider: string,\n options: ProviderHealthOptions = {},\n): Promise<HalfOpenResult> {\n const nowMs = options.now?.() ?? Date.now();\n const at = new Date(nowMs).toISOString();\n const config = resolveProviderHealthConfig(options.config);\n let acquired = false;\n const record = await updateRecord(filePath, provider, (current) => {\n const cooldownUntil = current.cooldownUntil === null ? 0 : Date.parse(current.cooldownUntil);\n if (Number.isFinite(cooldownUntil) && cooldownUntil > nowMs) return current;\n\n const probeStarted = current.probeStartedAt === null ? 0 : Date.parse(current.probeStartedAt);\n const probeIsFresh =\n current.probeInFlight &&\n Number.isFinite(probeStarted) &&\n nowMs - probeStarted < config.cooldownMs;\n if (probeIsFresh) return current;\n\n acquired = true;\n return {\n ...current,\n status: 'half_open',\n cooldownUntil: null,\n probeInFlight: true,\n probeStartedAt: at,\n };\n });\n return { acquired, record };\n}\n","import { getActiveResilienceConfig } from '../config.js';\nimport { getShutdownSignal } from '../core/shutdown.js';\nimport type { FailureKind } from '../resilience/errors.js';\nimport { abortableDelay, resolvePolicy, shouldFailover } from '../resilience/policy.js';\nimport { resolveProjectPaths } from '../storage/resolve.js';\nimport type { ProviderHealthRecord, ResilienceConfig } from '../storage/schemas.js';\nimport {\n acquireHalfOpenProbe,\n openProviderCircuit,\n readProvidersHealth,\n resolveProviderHealthConfig,\n} from './health.js';\nimport { ensureRunnersRegistered, getRegisteredProviders } from './registry.js';\nimport { resolveAgentFor } from './resolve.js';\nimport {\n type AgentPhase,\n type AgentProviderId,\n isAgentProviderId,\n type ResolvedAgentSettings,\n} from './types.js';\n\nexport interface AgentSelection {\n primary: AgentProviderId;\n provider: AgentProviderId;\n settings: ResolvedAgentSettings;\n healthFile: string | null;\n failover: boolean;\n reason: FailureKind | null;\n cooldownUntil: string | null;\n}\n\nexport class AgentSelectionBlockedError extends Error {\n readonly provider: AgentProviderId;\n readonly kind: FailureKind;\n\n constructor(provider: AgentProviderId, kind: FailureKind) {\n super(\n `Authentication failed for agent provider '${provider}' (${kind}); the run is blocked. Authenticate or repair that provider before resuming.`,\n );\n this.name = 'AgentSelectionBlockedError';\n this.provider = provider;\n this.kind = kind;\n }\n}\n\ninterface CandidateVerdict {\n available: boolean;\n waitMs: number | null;\n cooldownUntil: string | null;\n reason: FailureKind | null;\n blocked: boolean;\n}\n\nfunction remainingMs(until: string | null, nowMs: number): number | null {\n if (until === null) return null;\n const parsed = Date.parse(until);\n return Number.isFinite(parsed) ? Math.max(0, parsed - nowMs) : null;\n}\n\nfunction failoverIsDue(\n record: ProviderHealthRecord | undefined,\n config: ResilienceConfig,\n): boolean {\n if (record?.lastFailureKind == null) return false;\n return shouldFailover(resolvePolicy(record.lastFailureKind, config), record.consecutiveFailures);\n}\n\nasync function verdictFor(\n provider: AgentProviderId,\n record: ProviderHealthRecord | undefined,\n options: {\n healthFile: string;\n config: ResilienceConfig;\n primary: boolean;\n nowMs: number;\n },\n): Promise<CandidateVerdict> {\n if (record === undefined || record.status === 'healthy') {\n return { available: true, waitMs: null, cooldownUntil: null, reason: null, blocked: false };\n }\n\n const reason = record.lastFailureKind;\n if (record.status === 'auth_failed') {\n const mayFailover = reason !== null && failoverIsDue(record, options.config);\n return {\n available: false,\n waitMs: null,\n cooldownUntil: null,\n reason,\n blocked: options.primary && !mayFailover,\n };\n }\n\n if (record.status === 'degraded') {\n const due = failoverIsDue(record, options.config);\n const opened = due\n ? await openProviderCircuit(options.healthFile, provider, {\n now: () => options.nowMs,\n config: options.config.providers,\n })\n : record;\n return {\n available: !due,\n waitMs: due ? remainingMs(opened.cooldownUntil, options.nowMs) : null,\n cooldownUntil: opened.cooldownUntil,\n reason,\n blocked: false,\n };\n }\n\n // `half_open` joins the two closed states on purpose: `acquireHalfOpenProbe`\n // is the only place that knows a probe went stale, and a record left\n // `probeInFlight` by a SIGKILLed run is otherwise never reclaimed — the next\n // run just waits on a cooldown that never ends.\n if (\n record.status === 'unavailable' ||\n record.status === 'rate_limited' ||\n record.status === 'half_open'\n ) {\n const waitMs = remainingMs(record.cooldownUntil, options.nowMs);\n if (waitMs !== null && waitMs > 0) {\n return {\n available: false,\n waitMs,\n cooldownUntil: record.cooldownUntil,\n reason,\n blocked: false,\n };\n }\n const probe = await acquireHalfOpenProbe(options.healthFile, provider, {\n now: () => options.nowMs,\n config: options.config.providers,\n });\n return {\n available: probe.acquired,\n waitMs: probe.acquired\n ? null\n : resolveProviderHealthConfig(options.config.providers).cooldownMs,\n cooldownUntil: probe.record.cooldownUntil,\n reason,\n blocked: false,\n };\n }\n\n return { available: true, waitMs: null, cooldownUntil: null, reason, blocked: false };\n}\n\nfunction providerOrder(primary: AgentProviderId, config: ResilienceConfig): AgentProviderId[] {\n ensureRunnersRegistered();\n const registered = getRegisteredProviders();\n const configured = (config.providers?.chain ?? []).filter(isAgentProviderId);\n return [...new Set([primary, ...configured, ...registered])];\n}\n\nfunction settingsFor(\n base: ResolvedAgentSettings,\n provider: AgentProviderId,\n): ResolvedAgentSettings {\n if (provider === base.provider) return base;\n return {\n ...base,\n provider,\n // A model name belongs to the configured primary unless the selected\n // provider is that primary. Passing a Claude alias to Codex (or vice\n // versa) is less useful than letting the fallback use its own default.\n model: null,\n };\n}\n\n/**\n * Select one provider. When every provider is cooling down, wait for the\n * earliest circuit instead of turning a temporary absence into a failed run.\n */\nexport async function selectAgentForInvocation(\n phase: AgentPhase,\n options: {\n config?: ResilienceConfig;\n now?: () => number;\n delay?: (ms: number, options: { signal?: AbortSignal }) => Promise<boolean>;\n } = {},\n): Promise<AgentSelection> {\n const config = options.config ?? getActiveResilienceConfig();\n const base = await resolveAgentFor(phase);\n const failover = config.providers?.failover === true;\n if (!failover) {\n return {\n primary: base.provider,\n provider: base.provider,\n settings: base,\n healthFile: null,\n failover: false,\n reason: null,\n cooldownUntil: null,\n };\n }\n\n let healthFile: string;\n try {\n healthFile = (await resolveProjectPaths()).providersHealthFile;\n } catch {\n return {\n primary: base.provider,\n provider: base.provider,\n settings: base,\n healthFile: null,\n failover: true,\n reason: null,\n cooldownUntil: null,\n };\n }\n\n const delay = options.delay ?? abortableDelay;\n selection: for (;;) {\n const nowMs = options.now?.() ?? Date.now();\n const health = await readProvidersHealth(healthFile);\n const waits: number[] = [];\n let primaryReason: FailureKind | null = null;\n let primaryCooldown: string | null = null;\n\n for (const provider of providerOrder(base.provider, config)) {\n const verdict = await verdictFor(provider, health.providers[provider], {\n healthFile,\n config,\n primary: provider === base.provider,\n nowMs,\n });\n if (provider === base.provider) {\n primaryReason = verdict.reason;\n primaryCooldown = verdict.cooldownUntil;\n }\n if (verdict.blocked && verdict.reason !== null) {\n throw new AgentSelectionBlockedError(provider, verdict.reason);\n }\n if (\n provider === base.provider &&\n !verdict.available &&\n verdict.waitMs !== null &&\n !failoverIsDue(health.providers[provider], config)\n ) {\n if (!(await delay(Math.max(1, verdict.waitMs), { signal: getShutdownSignal() }))) {\n throw new Error('Agent provider selection was interrupted while waiting for cooldown.');\n }\n continue selection;\n }\n if (verdict.available) {\n return {\n primary: base.provider,\n provider,\n settings: settingsFor(base, provider),\n healthFile,\n failover: provider !== base.provider,\n reason: provider === base.provider ? null : primaryReason,\n cooldownUntil: primaryCooldown,\n };\n }\n if (verdict.waitMs !== null) waits.push(verdict.waitMs);\n }\n\n const waitMs = waits.length > 0 ? Math.max(1, Math.min(...waits)) : null;\n if (waitMs === null) {\n throw new Error(\n 'No healthy agent provider is available and none has a cooldown to wait for.',\n );\n }\n if (!(await delay(waitMs, { signal: getShutdownSignal() }))) {\n throw new Error('Agent provider selection was interrupted while waiting for cooldown.');\n }\n }\n}\n","import {\n getActiveResilienceConfig,\n getAgentCliOverrides,\n loadAgentConfig,\n loadRoutingConfig,\n} from '../config.js';\nimport { getSessionPublisher } from '../core/session-publisher.js';\nimport { isoNow } from '../core/state-manager.js';\nimport { type ClassifiedFailure, classify, type FailureKind } from '../resilience/errors.js';\nimport { evaluateCeilings } from '../routing/budget.js';\nimport { decideRouting } from '../routing/decide.js';\nimport { bindDiagnosticContext, writeDiagnostic } from '../storage/diagnostics.js';\nimport type { ProviderHealthRecord } from '../storage/schemas.js';\nimport { beginExecution, endExecution } from '../telemetry/recorder.js';\nimport { redactSecrets } from '../telemetry/redact.js';\nimport type { ExecutionPurpose, ExecutionRecord, ExecutionTrigger } from '../telemetry/types.js';\nimport { resolveAntigravityTimeoutMs } from './antigravity.js';\nimport { peekHarnessVersion } from './claude.js';\nimport { recordProviderFailure, recordProviderSuccess } from './health.js';\nimport { ensureCursorStorageGrant } from './permissions.js';\nimport { runnerFor } from './registry.js';\nimport { hasExplicitAgentSelection, resolveAgentFor } from './resolve.js';\nimport { type AgentSelection, selectAgentForInvocation } from './select.js';\nimport type { AgentInvocation, AgentProviderId, AgentRunResult } from './types.js';\n\nasync function selectionForForced(invocation: AgentInvocation): Promise<AgentSelection> {\n const settings = await resolveAgentFor(invocation.phase, {\n cli: { forceProvider: invocation.forceProvider },\n });\n return {\n primary: settings.provider,\n provider: settings.provider,\n settings,\n healthFile: null,\n failover: false,\n reason: null,\n cooldownUntil: null,\n };\n}\n\nconst attempts = new Map<string, number>();\nconst lastFailure = new Map<string, FailureKind>();\nconst issueSpend = {\n reportedUsd: 0,\n durationMs: 0,\n executions: 0,\n sawReported: false,\n};\n\n/** Declared identity of a runner — never inferred from argv or logs. */\nexport function declaredAgentIdentity(provider: AgentProviderId): {\n harness: string;\n vendor: string;\n} {\n switch (provider) {\n case 'claude':\n return { harness: 'claude-code', vendor: 'anthropic' };\n case 'codex':\n return { harness: 'codex-cli', vendor: 'openai' };\n case 'cursor':\n return { harness: 'cursor-cli', vendor: 'cursor' };\n case 'antigravity':\n return { harness: 'antigravity-cli', vendor: 'google' };\n default: {\n const _exhaustive: never = provider;\n return _exhaustive;\n }\n }\n}\n\nfunction triggerOf(\n selection: AgentSelection,\n attempt: number,\n correctionCycle = 0,\n): ExecutionTrigger {\n if (selection.failover) return 'fallback';\n if (attempt > 1) return 'retry';\n if (correctionCycle > 0) return 'correction';\n return 'initial';\n}\n\nexport interface SelectedAgentRun {\n run: AgentRunResult;\n failure: ClassifiedFailure | null;\n selection: AgentSelection;\n attempt: number;\n health: ProviderHealthRecord | null;\n blocked?: { stopReason: string; detail: string; actor: 'human' };\n}\n\nfunction nextAttempt(phase: string): number {\n const attempt = (attempts.get(phase) ?? 0) + 1;\n attempts.set(phase, attempt);\n return attempt;\n}\n\nexport function resetAgentInvocationState(): void {\n attempts.clear();\n lastFailure.clear();\n issueSpend.reportedUsd = 0;\n issueSpend.durationMs = 0;\n issueSpend.executions = 0;\n issueSpend.sawReported = false;\n}\n\n/** One invocation, including provider selection, health persistence and audit events. */\nexport async function invokeSelectedAgent(invocation: AgentInvocation): Promise<SelectedAgentRun> {\n const config = getActiveResilienceConfig();\n const selection =\n invocation.forceProvider === undefined\n ? await selectAgentForInvocation(invocation.phase, { config })\n : await selectionForForced(invocation);\n const attempt = nextAttempt(invocation.phase);\n const publisher = getSessionPublisher();\n publisher.publish({\n type: 'agent:attempt',\n at: isoNow(),\n attempt,\n provider: selection.provider,\n model: selection.settings.model,\n primaryProvider: selection.primary,\n });\n if (selection.failover) {\n publisher.publish({\n type: 'failover',\n at: isoNow(),\n from: selection.primary,\n to: selection.provider,\n reason: selection.reason,\n cooldownUntil: selection.cooldownUntil,\n });\n writeDiagnostic({\n level: 'warning',\n message: `Agent failover from ${selection.primary} to ${selection.provider}`,\n context: { reason: selection.reason, cooldownUntil: selection.cooldownUntil },\n fields: {\n phase: invocation.phase,\n harness: selection.provider,\n model: selection.settings.model,\n },\n });\n }\n\n const identity = declaredAgentIdentity(selection.provider);\n const requested = selection.settings.model;\n const routingCfg = await loadRoutingConfig();\n const agentCfg = await loadAgentConfig();\n const routingDecision = decideRouting({\n phase: invocation.phase,\n actualHarness: identity.harness,\n mode: routingCfg.mode,\n profile: routingCfg.profile,\n skipScore: hasExplicitAgentSelection(agentCfg, getAgentCliOverrides()),\n requiresExtraDirectories: (invocation.addDirs?.length ?? 0) > 0,\n });\n const executionId = await beginExecution({\n purpose: (invocation.purpose ?? invocation.phase) as ExecutionPurpose,\n attempt,\n trigger: triggerOf(selection, attempt, invocation.correctionCycle),\n triggerReason: selection.failover\n ? selection.reason\n : attempt > 1\n ? (lastFailure.get(invocation.phase) ?? null)\n : null,\n harness: identity.harness,\n provider: identity.vendor,\n harnessVersion: peekHarnessVersion(selection.provider) ?? null,\n modelRequested: requested,\n modelResolved: null,\n modelSource: requested ? 'config' : 'unavailable',\n ...(invocation.iteration === undefined ? {} : { iteration: invocation.iteration }),\n ...(invocation.correctionCycle === undefined\n ? {}\n : { correctionCycle: invocation.correctionCycle }),\n ...(invocation.storyIds === undefined ? {} : { storyIds: invocation.storyIds }),\n ...(routingDecision === null\n ? {}\n : { routingDecision: routingDecision as unknown as ExecutionRecord['routingDecision'] }),\n });\n bindDiagnosticContext({\n executionId,\n phase: invocation.phase,\n harness: identity.harness,\n model: requested,\n story: invocation.storyIds?.join(',') ?? null,\n });\n\n const runner = runnerFor(selection.provider);\n const ceiling = evaluateCeilings({\n ceilings: routingCfg.ceilings,\n spent: {\n reportedUsd: issueSpend.reportedUsd,\n costStatus: issueSpend.sawReported ? 'reported' : 'unknown',\n durationMs: issueSpend.durationMs,\n executions: issueSpend.executions,\n },\n });\n if (!ceiling.ok) {\n const detail = `blocked by ${ceiling.binding} ceiling (${ceiling.numbers.spent} ≥ ${ceiling.numbers.ceiling}). Enforced by Issue Flow, not by a harness flag.`;\n const run = {\n success: false,\n result: '',\n rawOutput: detail,\n exitCode: 1,\n usage: null,\n error: detail,\n agent: { provider: selection.provider, model: selection.settings.model },\n harnessVersion: peekHarnessVersion(selection.provider),\n };\n if (executionId !== null) {\n await endExecution({\n id: executionId,\n status: 'failed',\n error: detail,\n exitCode: 1,\n stopReason: ceiling.stopReason,\n });\n }\n return {\n run,\n failure: null,\n selection,\n attempt,\n health: null,\n blocked: { stopReason: ceiling.stopReason, detail, actor: 'human' },\n };\n }\n if (\n runner.capabilities.nativeTimeout &&\n invocation.timeout === 0 &&\n resolveAntigravityTimeoutMs(invocation, selection.settings) === null\n ) {\n const run = {\n success: false,\n result: '',\n rawOutput:\n 'configuration: provider has nativeTimeout and received timeout: 0 without a ceiling.',\n exitCode: 1,\n usage: null,\n error:\n 'configuration: provider has nativeTimeout and received timeout: 0 without a ceiling. Set agent.antigravity.executeTimeout.',\n agent: { provider: selection.provider, model: selection.settings.model },\n harnessVersion: peekHarnessVersion(selection.provider),\n };\n if (executionId !== null) {\n await endExecution({\n id: executionId,\n status: 'failed',\n error: run.error,\n exitCode: 1,\n });\n }\n const failure = classify({ source: 'agent', exitCode: 1, stdout: run.error });\n return { run, failure, selection, attempt, health: null };\n }\n if (\n (invocation.addDirs?.length ?? 0) > 0 &&\n runner.capabilities.extraDirectories === 'permission-file'\n ) {\n const grant =\n selection.settings.cursor.permissionsFile === 'none'\n ? { skipped: true as const, reason: 'none' as const }\n : await ensureCursorStorageGrant({\n mode: selection.settings.cursor.permissionsFile ?? 'global',\n });\n if ('skipped' in grant && selection.settings.cursor.permissionsFile !== 'none') {\n throw new Error(\n `Phase '${invocation.phase}' needs extraDirectories on '${selection.provider}', which only grants them via a permission file. Run \\`issue-flow agent use cursor\\` or set agent.cursor.permissionsFile.`,\n );\n }\n } else if (\n (invocation.addDirs?.length ?? 0) > 0 &&\n runner.capabilities.extraDirectories === 'none'\n ) {\n throw new Error(\n `Phase '${invocation.phase}' needs extraDirectories, but '${selection.provider}' cannot grant them.`,\n );\n }\n\n let run: AgentRunResult;\n const startedMs = Date.now();\n try {\n run = await runner.run(\n {\n ...invocation,\n onLine: (line) => {\n const sanitized = redactSecrets(line).slice(0, 4_000);\n publisher.publish({\n type: 'agent:activity',\n at: isoNow(),\n provider: selection.provider,\n });\n if (sanitized.trim() !== '') {\n publisher.publish({\n type: 'process:output',\n at: isoNow(),\n phase: invocation.phase,\n executionId,\n provider: selection.provider,\n stream: 'combined',\n message: sanitized,\n });\n writeDiagnostic({\n level: 'debug',\n message: sanitized,\n fields: {\n executionId,\n phase: invocation.phase,\n harness: identity.harness,\n model: selection.settings.model,\n },\n });\n }\n invocation.onLine?.(line);\n },\n },\n selection.settings,\n );\n } catch (err) {\n writeDiagnostic({\n level: 'error',\n message: `Agent invocation threw before producing a result: ${\n err instanceof Error ? err.message : String(err)\n }`,\n exception: err,\n fields: {\n executionId,\n phase: invocation.phase,\n harness: identity.harness,\n model: selection.settings.model,\n },\n });\n if (executionId !== null) {\n await endExecution({\n id: executionId,\n status: 'failed',\n error: err instanceof Error ? err.message : String(err),\n });\n }\n throw err;\n }\n issueSpend.executions += 1;\n issueSpend.durationMs += Math.max(0, Date.now() - startedMs);\n if (run.usage?.costUsd !== undefined) {\n issueSpend.reportedUsd += run.usage.costUsd;\n issueSpend.sawReported = true;\n }\n\n const failure =\n run.success && run.exitCode === 0\n ? null\n : classify({\n source: 'agent',\n exitCode: run.exitCode,\n stdout: run.rawOutput || run.error || '',\n });\n writeDiagnostic({\n level: failure === null ? 'info' : 'error',\n message:\n failure === null\n ? `Agent invocation completed with ${selection.provider}`\n : `Agent invocation failed with ${selection.provider}: ${failure.message}`,\n context: {\n attempt,\n exitCode: run.exitCode,\n failureKind: failure?.kind ?? null,\n trigger: triggerOf(selection, attempt, invocation.correctionCycle),\n },\n fields: {\n executionId,\n phase: invocation.phase,\n harness: identity.harness,\n model: run.agent.model,\n },\n });\n\n if (executionId !== null) {\n await endExecution({\n id: executionId,\n status: failure === null ? 'completed' : failure.kind === 'timeout' ? 'timeout' : 'failed',\n usage: run.usage,\n error: failure === null ? null : (run.error ?? run.rawOutput),\n exitCode: run.exitCode,\n modelResolved: run.agent.model,\n modelSource: run.agent.model\n ? requested\n ? 'config'\n : 'provider'\n : requested\n ? 'config'\n : 'unavailable',\n harnessVersion: run.harnessVersion ?? peekHarnessVersion(selection.provider) ?? null,\n providerSessionId: run.sessionId ?? null,\n storyIds: invocation.storyIds,\n });\n }\n\n if (failure === null) lastFailure.delete(invocation.phase);\n else lastFailure.set(invocation.phase, failure.kind);\n\n let health: ProviderHealthRecord | null = null;\n if (selection.healthFile !== null) {\n health =\n failure === null\n ? await recordProviderSuccess(selection.healthFile, selection.provider)\n : await recordProviderFailure(selection.healthFile, selection.provider, failure, {\n config: config.providers,\n });\n }\n\n publisher.publish({\n type: 'agent:result',\n at: isoNow(),\n provider: selection.provider,\n success: failure === null,\n ...(failure === null ? {} : { failureKind: failure.kind }),\n cooldownUntil: health?.cooldownUntil ?? null,\n });\n\n if (failure === null) attempts.delete(invocation.phase);\n return { run, failure, selection, attempt, health };\n}\n","import type { TaskPlan, UserStory } from '../types.js';\nimport { parseJournal } from './journal.js';\n\n/**\n * \"This issue is too large\" — detected, reported, and left to a person.\n *\n * A phase that keeps timing out, a plan with thirty stories, five iterations in\n * a row that finish nothing: each of those is ambiguous on its own, and any one\n * of them can also be a slow afternoon. Together they are the same thing said\n * three ways, and what they are saying is that the demand was never one issue.\n *\n * The tool's job here stops at saying so. **Splitting an issue is a product\n * decision**, and the default is a report plus `blocked`, not an act — which is\n * also why a failure that is merely *infrastructural* must never reach this\n * code path: an issue whose run died because the network went down is not too\n * large, and breaking it up would be the worst possible response.\n */\n\n/** The thresholds, in one place, because every one of them is a judgement. */\nexport const DECOMPOSITION_THRESHOLDS = {\n /** Timeouts on the same phase. Two is already a pattern, not bad luck. */\n timeoutsPerPhase: 2,\n /** Stories in the plan. Past this, the plan is a backlog. */\n stories: 15,\n /** Iterations in a row that completed no story. */\n barrenIterations: 5,\n /** Files touched on the branch. */\n filesTouched: 40,\n /** Characters in the issue body. */\n issueBodyChars: 20_000,\n} as const;\n\n/** How many signals have to agree before the report is written. */\nexport const DECOMPOSITION_MIN_SIGNALS = 2;\n\nexport interface DecompositionInput {\n /** Contents of `events.jsonl` (both generations), oldest first. */\n journal?: string;\n plan?: TaskPlan | null;\n /** Body of the issue as the provider resolved it. */\n issueBody?: string;\n /** Files changed on the branch, from `git diff --name-only`. */\n filesTouched?: number;\n /** Whether the execute loop stopped because it ran out of iterations. */\n hitMaxIterations?: boolean;\n}\n\nexport interface DecompositionSignal {\n id: string;\n /** One line a person can act on, naming the number that crossed the line. */\n detail: string;\n}\n\nexport interface DecompositionAssessment {\n signals: DecompositionSignal[];\n /** Two or more signals agreeing. */\n oversized: boolean;\n}\n\n/* ── the signals ────────────────────────────────────────────────────────── */\n\n/** Timeouts per phase, read off the journal. Shared with timeout escalation. */\nexport function timeoutsByPhase(journal: string): Map<string, number> {\n const counts = new Map<string, number>();\n let phase = '(unknown)';\n\n for (const { event } of parseJournal(journal)) {\n if (event.type === 'phase:start') {\n phase = event.phase;\n continue;\n }\n if (event.type !== 'retry') continue;\n const kind = (event as { kind?: string }).kind;\n const reason = (event as { reason?: string }).reason ?? '';\n const timedOut = kind === 'timeout' || kind === 'stalled' || /timed out|stalled/i.test(reason);\n if (!timedOut) continue;\n counts.set(phase, (counts.get(phase) ?? 0) + 1);\n }\n return counts;\n}\n\n/**\n * The longest run of iterations that completed no story.\n *\n * An iteration that finishes nothing is not a failure — the agent may be\n * halfway through a story — but five of them in a row means the unit of work is\n * bigger than the loop was designed for.\n */\nfunction longestBarrenRun(journal: string): number {\n let passing = 0;\n let current = 0;\n let longest = 0;\n\n for (const { event } of parseJournal(journal)) {\n if (event.type === 'iteration:start') {\n current++;\n longest = Math.max(longest, current);\n continue;\n }\n if (event.type !== 'stories:update') continue;\n const nowPassing = event.stories.filter((story) => story.passes).length;\n if (nowPassing > passing) current = 0;\n passing = Math.max(passing, nowPassing);\n }\n return longest;\n}\n\n/**\n * Weigh the evidence.\n *\n * Every signal is a number crossing a documented line, and the report quotes\n * that number: \"this is too big\" is not an argument, and \"the `prd` phase timed\n * out three times\" is.\n */\nexport function assessDecomposition(input: DecompositionInput): DecompositionAssessment {\n const signals: DecompositionSignal[] = [];\n const journal = input.journal ?? '';\n\n for (const [phase, count] of timeoutsByPhase(journal)) {\n if (count >= DECOMPOSITION_THRESHOLDS.timeoutsPerPhase) {\n signals.push({\n id: 'repeated-timeouts',\n detail: `The '${phase}' phase timed out ${count} times (threshold: ${DECOMPOSITION_THRESHOLDS.timeoutsPerPhase}).`,\n });\n }\n }\n\n const stories = input.plan?.userStories.length ?? 0;\n if (stories > DECOMPOSITION_THRESHOLDS.stories) {\n signals.push({\n id: 'story-count',\n detail: `The plan has ${stories} user stories (threshold: ${DECOMPOSITION_THRESHOLDS.stories}).`,\n });\n }\n\n const barren = longestBarrenRun(journal);\n if (barren >= DECOMPOSITION_THRESHOLDS.barrenIterations) {\n signals.push({\n id: 'barren-iterations',\n detail: `${barren} iterations in a row completed no story (threshold: ${DECOMPOSITION_THRESHOLDS.barrenIterations}).`,\n });\n }\n\n const files = input.filesTouched ?? 0;\n if (files > DECOMPOSITION_THRESHOLDS.filesTouched) {\n signals.push({\n id: 'files-touched',\n detail: `${files} files were touched on this branch (threshold: ${DECOMPOSITION_THRESHOLDS.filesTouched}).`,\n });\n }\n\n const body = input.issueBody?.length ?? 0;\n if (body > DECOMPOSITION_THRESHOLDS.issueBodyChars) {\n signals.push({\n id: 'issue-size',\n detail: `The issue body is ${body} characters (threshold: ${DECOMPOSITION_THRESHOLDS.issueBodyChars}).`,\n });\n }\n\n if (input.hitMaxIterations === true) {\n signals.push({\n id: 'max-iterations',\n detail: 'The execute loop stopped because it ran out of iterations, not because it finished.',\n });\n }\n\n return { signals, oversized: signals.length >= DECOMPOSITION_MIN_SIGNALS };\n}\n\n/* ── the report ─────────────────────────────────────────────────────────── */\n\n/** Stories per proposed sub-issue. Small enough to finish in one run. */\nconst STORIES_PER_SUBISSUE = 5;\n\nexport interface ProposedSubIssue {\n title: string;\n stories: UserStory[];\n /** Titles of the sub-issues this one has to wait for. */\n dependsOn: string[];\n}\n\n/**\n * Cut the remaining work into pieces, in priority order.\n *\n * Priority order matters twice: it is the order the execute loop already works\n * in, and it makes each piece depend only on the one before it — which is the\n * only dependency shape that can be derived without understanding the code.\n * Anything cleverer would be a guess dressed as a plan.\n */\nexport function proposeSubIssues(plan: TaskPlan | null | undefined): ProposedSubIssue[] {\n const pending = [...(plan?.userStories ?? [])]\n .filter((story) => !story.passes)\n .sort((a, b) => a.priority - b.priority);\n if (pending.length === 0) return [];\n\n const chunks: ProposedSubIssue[] = [];\n for (let index = 0; index < pending.length; index += STORIES_PER_SUBISSUE) {\n const stories = pending.slice(index, index + STORIES_PER_SUBISSUE);\n const first = stories[0];\n const last = stories[stories.length - 1];\n const range =\n first === undefined || last === undefined || first.id === last.id\n ? (first?.id ?? '')\n : `${first.id}–${last.id}`;\n chunks.push({\n title: `${plan?.description ?? 'Issue'} — part ${chunks.length + 1} (${range})`,\n stories,\n dependsOn: chunks.length === 0 ? [] : [chunks[chunks.length - 1]?.title ?? ''],\n });\n }\n return chunks;\n}\n\nexport interface DecompositionReportInput {\n issueNumber: string;\n assessment: DecompositionAssessment;\n plan: TaskPlan | null | undefined;\n at: string;\n}\n\n/**\n * The report itself: what was detected, what is proposed, and what to do.\n *\n * Written for a person to disagree with. It states each signal with its number,\n * proposes a cut it can justify, and stops — the decision is not the tool's.\n */\nexport function buildDecompositionReport(input: DecompositionReportInput): string {\n const { issueNumber, assessment, plan, at } = input;\n const proposals = proposeSubIssues(plan);\n const lines: string[] = [];\n\n lines.push(`# Issue #${issueNumber} looks larger than one run`, '');\n lines.push(`Detected at ${at}.`, '');\n lines.push(\n 'This is a report, not an action. Nothing has been split, and nothing will be',\n 'without you asking for it.',\n '',\n );\n\n lines.push('## What was detected', '');\n for (const signal of assessment.signals) {\n lines.push(`- **${signal.id}** — ${signal.detail}`);\n }\n lines.push('');\n\n if (proposals.length === 0) {\n lines.push('## Proposed split', '');\n lines.push(\n 'No pending user stories were found, so there is nothing to cut here.',\n 'The signals above are about the run rather than about the plan.',\n '',\n );\n return `${lines.join('\\n')}\\n`;\n }\n\n lines.push('## Proposed split', '');\n lines.push(\n `The ${proposals.reduce((total, proposal) => total + proposal.stories.length, 0)} pending` +\n ` stories, in priority order, cut into ${proposals.length} sub-issues of at most` +\n ` ${STORIES_PER_SUBISSUE}. Each depends on the one before it, which is the only`,\n 'dependency shape that can be derived from the plan alone — read it as a starting',\n 'point, not as an answer.',\n '',\n );\n\n for (const proposal of proposals) {\n lines.push(`### ${proposal.title}`, '');\n if (proposal.dependsOn.length > 0) {\n lines.push(`Depends on: ${proposal.dependsOn.join(', ')}`, '');\n }\n for (const story of proposal.stories) {\n lines.push(`- \\`${story.id}\\` ${story.title}`);\n }\n lines.push('');\n }\n\n lines.push('## What to do next', '');\n lines.push(\n '- Adjust the cut above until it matches how you would actually split the work;',\n '- create the sub-issues (`issue-flow generate \"…\"`) and run them as a queue;',\n '- or decide the issue is fine as it is and re-run it — nothing here blocks that,',\n ' beyond the report you are reading.',\n '',\n );\n\n return `${lines.join('\\n')}\\n`;\n}\n","import { readFile } from 'node:fs/promises';\nimport chalk from 'chalk';\nimport { invokeSelectedAgent } from '../agents/invoke.js';\nimport { resolveAgentFor } from '../agents/resolve.js';\nimport type {\n AgentEvent,\n AgentInvocation,\n AgentPermission,\n AgentPhase,\n AgentProviderId,\n AgentRunResult,\n} from '../agents/types.js';\nimport { getActiveResilienceConfig } from '../config.js';\nimport { resolvePolicy } from '../resilience/policy.js';\nimport { withRetry } from '../resilience/retry.js';\nimport { writeDiagnostic } from '../storage/diagnostics.js';\nimport { createSpinner, ElapsedTimer, formatDuration, getIcons, useColor } from '../ui/logger.js';\nimport { DECOMPOSITION_THRESHOLDS, timeoutsByPhase } from './decompose.js';\nimport { type ClaudeUsage, sumUsage } from './metrics.js';\nimport { getSessionPublisher } from './session-publisher.js';\nimport { getShutdownSignal } from './shutdown.js';\nimport { isoNow } from './state-manager.js';\nimport {\n getActivityCallback,\n getInactivityTimeout,\n getOutputCallback,\n isVerbose,\n} from './verbose.js';\n\nexport interface HeadlessOptions {\n prompt: string;\n maxTurns?: number;\n timeout?: number;\n outputFormat?: 'json' | 'text' | 'stream-json';\n allowedTools?: string[];\n /**\n * Extra directories the headless session may read from and write to, passed\n * through as `--add-dir`. Required whenever a prompt points at a path outside\n * the working tree (e.g. the global issue storage under `~/.issue-flow`).\n */\n addDirs?: string[];\n /** Status message displayed as spinner (non-verbose) or header (verbose). */\n statusMessage?: string;\n /** Optional callback for routing verbose output (e.g., through listr2 task.output). */\n onOutput?: (line: string) => void;\n /** Journal-backed identity used to apply the one-time 2× timeout escalation. */\n timeoutHistory?: {\n phase: string;\n journalFiles: string[];\n };\n /** The invoking phase. Defaults to `analyze` only for resolution; argv is unchanged. */\n phase?: AgentPhase;\n /**\n * Semantic permission. Absent means `workspace`, which is the historical\n * `runHeadless` argv (no `--permission-mode`, no `--dangerously-skip-permissions`).\n */\n permission?: AgentPermission;\n /** Pin this invocation to a provider (L2 reviewer). */\n forceProvider?: AgentProviderId;\n /** Telemetry purpose when it is not the phase name (`verify`). */\n purpose?: 'verify';\n correctionCycle?: number;\n storyIds?: string[];\n}\n\nexport type HeadlessCost = ClaudeUsage;\n\nexport interface HeadlessResult {\n success: boolean;\n result: string;\n cost: HeadlessCost | null;\n error: string | null;\n agent?: { provider: AgentProviderId; model: string | null };\n /** The resilience budget was spent inside the facade; an outer artifact retry must not repeat it. */\n retryExhausted?: boolean;\n}\n\nexport const DEFAULT_HEADLESS_TIMEOUT_MS = 900_000;\n\nasync function escalatedTimeout(\n timeoutMs: number,\n history: HeadlessOptions['timeoutHistory'],\n): Promise<number> {\n if (timeoutMs === 0 || history === undefined) return timeoutMs;\n\n const journal = (\n await Promise.all(\n history.journalFiles.map(async (file) => {\n try {\n return await readFile(file, 'utf-8');\n } catch {\n return '';\n }\n }),\n )\n ).join('');\n const timeouts = timeoutsByPhase(journal).get(history.phase) ?? 0;\n if (timeouts < DECOMPOSITION_THRESHOLDS.timeoutsPerPhase) return timeoutMs;\n return Math.min(timeoutMs * 2, Number.MAX_SAFE_INTEGER);\n}\n\nfunction printAgentEvent(event: AgentEvent, onOutput?: (line: string) => void): void {\n const icons = getIcons();\n const colored = useColor();\n const emit = onOutput ?? ((msg: string) => process.stdout.write(`${msg}\\n`));\n\n if (event.kind === 'text') {\n const lines = event.text.split('\\n');\n for (const textLine of lines) {\n if (!textLine.trim()) continue;\n const prefix = colored ? chalk.dim(` ${icons.connector} `) : ` ${icons.connector} `;\n const text = colored ? chalk.dim(textLine) : textLine;\n emit(`${prefix}${text}`);\n }\n return;\n }\n\n getSessionPublisher().publish({\n type: 'activity',\n at: isoNow(),\n tool: event.name,\n detail: event.detail,\n });\n const toolName = event.name.padEnd(12);\n const prefix = colored ? chalk.dim(` ${icons.connector} `) : ` ${icons.connector} `;\n const toolIcon = colored ? chalk.cyan(icons.tool) : icons.tool;\n const toolLabel = colored ? chalk.cyan(toolName) : toolName;\n const contextText = event.detail ? (colored ? chalk.dim(event.detail) : event.detail) : '';\n emit(`${prefix}${toolIcon} ${toolLabel} ${contextText}`);\n}\n\nasync function invokeHeadlessAgent(\n invocation: AgentInvocation,\n): Promise<{ run: AgentRunResult; retryExhausted: boolean }> {\n const config = getActiveResilienceConfig();\n if (config.providers?.failover !== true) {\n return { run: (await invokeSelectedAgent(invocation)).run, retryExhausted: false };\n }\n\n let usage: ClaudeUsage | null = null;\n const outcome = await withRetry(() => invokeSelectedAgent(invocation), {\n policy: (failure) => resolvePolicy(failure.kind, config),\n signal: getShutdownSignal(),\n evaluate: (selected) => selected.failure,\n onAttempt: ({ value, failure, willRetry, delayMs, attempt }) => {\n if (value.run.usage !== null) usage = sumUsage(usage, value.run.usage);\n if (failure === null || !willRetry) return;\n getSessionPublisher().publish({\n type: 'retry',\n at: isoNow(),\n attempt,\n delaySeconds: delayMs / 1000,\n reason: failure.message,\n kind: failure.kind,\n });\n writeDiagnostic({\n level: 'warning',\n message: `Retrying ${invocation.phase} after ${failure.kind}`,\n context: { attempt, delayMs, reason: failure.message },\n fields: { phase: invocation.phase },\n });\n },\n });\n\n return {\n run: usage === null ? outcome.value.run : { ...outcome.value.run, usage },\n retryExhausted: outcome.exhausted,\n };\n}\n\n/**\n * Invoke the resolved agent in headless mode.\n *\n * Each invocation is an isolated session. UI (spinner, verbose header, activity)\n * stays here; argv and stream parsing belong to the runner.\n */\nexport async function runHeadless(options: HeadlessOptions): Promise<HeadlessResult> {\n const {\n prompt,\n maxTurns = 10,\n timeout: configuredTimeout = DEFAULT_HEADLESS_TIMEOUT_MS,\n outputFormat = 'json',\n allowedTools,\n addDirs,\n statusMessage,\n onOutput,\n phase = 'analyze',\n permission = 'workspace',\n forceProvider,\n purpose,\n correctionCycle,\n storyIds,\n } = options;\n const timeout = await escalatedTimeout(configuredTimeout, options.timeoutHistory);\n const settings = await resolveAgentFor(phase);\n\n const verbose = isVerbose();\n const effectiveOnOutput = onOutput ?? getOutputCallback();\n\n if (verbose) {\n const icons = getIcons();\n const colored = useColor();\n const emit = effectiveOnOutput ?? ((msg: string) => process.stdout.write(`${msg}\\n`));\n if (statusMessage) {\n const msg = colored\n ? chalk.blue(`${icons.start} ${statusMessage}`)\n : `${icons.start} ${statusMessage}`;\n emit(msg);\n }\n const connectorLine = colored ? chalk.dim(` ${icons.connector}`) : ` ${icons.connector}`;\n emit(connectorLine);\n\n const startTime = Date.now();\n const { run, retryExhausted } = await invokeHeadlessAgent({\n prompt,\n phase,\n addDirs,\n timeout,\n permission,\n maxTurns,\n allowedTools,\n ...(forceProvider === undefined ? {} : { forceProvider }),\n ...(purpose === undefined ? {} : { purpose }),\n ...(correctionCycle === undefined ? {} : { correctionCycle }),\n ...(storyIds === undefined ? {} : { storyIds }),\n onEvent: (event) => printAgentEvent(event, effectiveOnOutput),\n });\n\n const elapsedSec = Math.floor((Date.now() - startTime) / 1000);\n const durationStr = formatDuration(elapsedSec);\n const doneLine = colored\n ? chalk.dim(` ${icons.connector} ${chalk.italic(`Done in ${durationStr}`)}`)\n : ` ${icons.connector} Done in ${durationStr}`;\n emit(doneLine);\n emit(connectorLine);\n\n return mapHeadlessResult(run, outputFormat, retryExhausted);\n }\n\n const spinner = statusMessage ? createSpinner(statusMessage).start() : null;\n let timer: ElapsedTimer | null = null;\n if (spinner) {\n timer = new ElapsedTimer((elapsed) => {\n spinner.suffixText = useColor() ? chalk.dim(`(${elapsed})`) : `(${elapsed})`;\n }).start();\n }\n\n try {\n const { run, retryExhausted } = await invokeHeadlessAgent({\n prompt,\n phase,\n addDirs,\n timeout,\n permission,\n maxTurns,\n allowedTools,\n inactivityTimeoutMs: getInactivityTimeout(),\n ...(forceProvider === undefined ? {} : { forceProvider }),\n ...(purpose === undefined ? {} : { purpose }),\n ...(correctionCycle === undefined ? {} : { correctionCycle }),\n ...(storyIds === undefined ? {} : { storyIds }),\n onEvent: (event) => {\n if (event.kind === 'text') return;\n getSessionPublisher().publish({\n type: 'activity',\n at: isoNow(),\n tool: event.name,\n detail: event.detail,\n });\n getActivityCallback()?.({ tool: event.name, detail: event.detail });\n },\n });\n\n const elapsed = timer?.stop() ?? 0;\n const dur = useColor()\n ? chalk.dim(` (${formatDuration(elapsed)})`)\n : ` (${formatDuration(elapsed)})`;\n\n if (!run.success) {\n spinner?.fail(`${statusMessage}${dur}`);\n return mapHeadlessResult(run, outputFormat, retryExhausted);\n }\n\n spinner?.succeed(`${statusMessage}${dur}`);\n return mapHeadlessResult(run, outputFormat, retryExhausted);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const catchElapsed = timer?.stop() ?? 0;\n const catchDur = useColor()\n ? chalk.dim(` (${formatDuration(catchElapsed)})`)\n : ` (${formatDuration(catchElapsed)})`;\n spinner?.fail(`${statusMessage}${catchDur}`);\n return {\n success: false,\n result: '',\n cost: null,\n error: message,\n agent: { provider: settings.provider, model: settings.model },\n };\n }\n}\n\nfunction mapHeadlessResult(\n run: {\n success: boolean;\n result: string;\n rawOutput: string;\n usage: ClaudeUsage | null;\n error: string | null;\n agent: { provider: AgentProviderId; model: string | null };\n },\n outputFormat: 'json' | 'text' | 'stream-json',\n retryExhausted = false,\n): HeadlessResult {\n if (outputFormat === 'text') {\n return {\n success: run.success,\n result: run.success ? run.rawOutput || run.result : '',\n cost: null,\n error: run.error,\n agent: run.agent,\n ...(retryExhausted ? { retryExhausted: true } : {}),\n };\n }\n if (!run.success) {\n return {\n success: false,\n result: '',\n cost: null,\n error: run.error,\n agent: run.agent,\n ...(retryExhausted ? { retryExhausted: true } : {}),\n };\n }\n return {\n success: true,\n result: run.result,\n cost: run.usage,\n error: null,\n agent: run.agent,\n ...(retryExhausted ? { retryExhausted: true } : {}),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASO,IAAM,mBAAoC;AAAA,EAC/C,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,WAAW;AACb;AA4BO,SAAS,iBAAiB,OAGd;AACjB,QAAM,WAAW,EAAE,GAAG,kBAAkB,GAAG,MAAM,SAAS;AAC1D,QAAM,WAA6B,CAAC;AACpC,MAAI,SAAS,uBAAuB,QAAQ,MAAM,MAAM,eAAe,YAAY;AACjF,aAAS,KAAK,MAAM;AAAA,EACtB;AACA,MAAI,SAAS,0BAA0B,KAAM,UAAS,KAAK,UAAU;AACrE,MAAI,SAAS,0BAA0B,KAAM,UAAS,KAAK,YAAY;AAEvE,MACE,SAAS,uBAAuB,QAChC,MAAM,MAAM,eAAe,cAC3B,MAAM,MAAM,eAAe,SAAS,oBACpC;AACA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,WAAW;AAAA,MACX,SAAS,EAAE,OAAO,MAAM,MAAM,aAAa,SAAS,SAAS,mBAAmB;AAAA,MAChF;AAAA,IACF;AAAA,EACF;AAEA,MACE,SAAS,0BAA0B,QACnC,MAAM,MAAM,cAAc,SAAS,uBACnC;AACA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,WAAW;AAAA,MACX,SAAS,EAAE,OAAO,MAAM,MAAM,YAAY,SAAS,SAAS,sBAAsB;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,MACE,SAAS,0BAA0B,QACnC,MAAM,MAAM,cAAc,SAAS,uBACnC;AACA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,WAAW;AAAA,MACX,SAAS,EAAE,OAAO,MAAM,MAAM,YAAY,SAAS,SAAS,sBAAsB;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,MAAM,SAAS,KAAK;AACnC;AAEO,SAAS,cAAc,MAAqE;AACjG,MAAI,KAAK,WAAW,YAAY;AAC9B,WAAO,EAAE,aAAa,KAAK,QAAQ,YAAY,WAAW;AAAA,EAC5D;AACA,SAAO,EAAE,aAAa,GAAG,YAAY,KAAK,OAAO;AACnD;;;ACzGA,SAAS,OAAO,UAAU,QAAQ,iBAAiB;AACnD,SAAS,eAAe;AASjB,IAAM,+BAA+B;AACrC,IAAM,mCAAmC,KAAK;AAC9C,IAAM,qCAAqC,IAAI;AAC/C,IAAM,oCAAoC;AAc1C,SAAS,4BACd,SAAoC,CAAC,GACP;AAC9B,SAAO;AAAA,IACL,YAAY,KAAK,IAAI,GAAG,OAAO,cAAc,4BAA4B;AAAA,IACzE,eAAe,KAAK;AAAA,MAClB,OAAO,cAAc;AAAA,MACrB,OAAO,iBAAiB;AAAA,IAC1B;AAAA,IACA,iBAAiB,KAAK,IAAI,GAAG,OAAO,mBAAmB,kCAAkC;AAAA,IACzF,gBAAgB,KAAK;AAAA,MACnB;AAAA,MACA,KAAK,MAAM,OAAO,kBAAkB,iCAAiC;AAAA,IACvE;AAAA,EACF;AACF;AAEA,SAAS,cAA+B;AACtC,SAAO,sBAAsB,MAAM,CAAC,CAAC;AACvC;AAEA,SAAS,cAAoC;AAC3C,SAAO,sBAAsB,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,EAAE,UAAU;AAChF;AAEA,eAAsB,oBAAoB,UAA4C;AACpF,MAAI;AACF,WAAO,sBAAsB,MAAM,KAAK,MAAM,MAAM,SAAS,UAAU,OAAO,CAAC,CAAC;AAAA,EAClF,QAAQ;AACN,WAAO,YAAY;AAAA,EACrB;AACF;AAEA,eAAe,qBAAqB,UAAkB,OAAuC;AAC3F,QAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,QAAM,MAAM,GAAG,QAAQ,QAAQ,QAAQ,GAAG;AAC1C,QAAM,UAAU,KAAK,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,GAAM,OAAO;AACnE,QAAM,OAAO,KAAK,QAAQ;AAC5B;AAEA,eAAe,aACb,UACA,UACA,QAC+B;AAC/B,QAAM,SAAS,MAAM,oBAAoB,QAAQ;AACjD,QAAM,OAAO,OAAO,OAAO,UAAU,QAAQ,KAAK,YAAY,CAAC;AAC/D,QAAM,qBAAqB,UAAU;AAAA,IACnC,GAAG;AAAA,IACH,WAAW,EAAE,GAAG,OAAO,WAAW,CAAC,QAAQ,GAAG,KAAK;AAAA,EACrD,CAAC;AACD,SAAO;AACT;AAEA,SAAS,cAAc,OAAe,QAA8C;AAClF,SAAO,KAAK,IAAI,OAAO,eAAe,OAAO,aAAa,KAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AACnF;AAEA,IAAM,gBAAgB,oBAAI,IAAiB;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,eAAsB,sBACpB,UACA,UACA,SACA,UAAiC,CAAC,GACH;AAC/B,QAAM,QAAQ,QAAQ,MAAM,KAAK,KAAK,IAAI;AAC1C,QAAM,KAAK,IAAI,KAAK,KAAK,EAAE,YAAY;AACvC,QAAM,SAAS,4BAA4B,QAAQ,MAAM;AAEzD,SAAO,aAAa,UAAU,UAAU,CAAC,WAAW;AAClD,UAAM,WAAW;AAAA,MACf,GAAG,OAAO,SAAS,OAAO,CAAC,UAAU;AACnC,cAAM,YAAY,KAAK,MAAM,MAAM,EAAE;AACrC,eAAO,OAAO,SAAS,SAAS,KAAK,QAAQ,aAAa,OAAO;AAAA,MACnE,CAAC;AAAA,MACD,EAAE,IAAI,MAAM,QAAQ,KAAK;AAAA,IAC3B;AACA,UAAM,sBAAsB,OAAO,sBAAsB;AAEzD,QAAI,QAAQ,SAAS,kBAAkB;AACrC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,eAAe;AAAA,QACf,iBAAiB,QAAQ;AAAA,QACzB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,gBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS,cAAc;AACjC,YAAM,QAAQ,QAAQ,gBAAgB,cAAc,OAAO,eAAe,MAAM;AAChF,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,eACE,QAAQ,iBAAiB,SAAY,OAAO,gBAAgB,IAAI,OAAO;AAAA,QACzE,eAAe,IAAI,KAAK,QAAQ,KAAK,EAAE,YAAY;AAAA,QACnD,iBAAiB,QAAQ;AAAA,QACzB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,gBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,QAAI,cAAc,IAAI,QAAQ,IAAI,GAAG;AACnC,YAAM,yBAAyB,SAAS;AAAA,QAAO,CAAC,UAC9C,cAAc,IAAI,MAAM,IAAI;AAAA,MAC9B,EAAE;AACF,YAAM,cACJ,OAAO,WAAW,eAAe,0BAA0B,OAAO;AACpE,YAAM,QAAQ,cAAc,cAAc,OAAO,eAAe,MAAM,IAAI;AAC1E,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ,cAAc,gBAAgB;AAAA,QACtC;AAAA,QACA;AAAA,QACA,eAAe,cAAc,OAAO,gBAAgB,IAAI,OAAO;AAAA,QAC/D,eAAe,cAAc,IAAI,KAAK,QAAQ,KAAK,EAAE,YAAY,IAAI;AAAA,QACrE,iBAAiB,QAAQ;AAAA,QACzB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,gBAAgB;AAAA,MAClB;AAAA,IACF;AAKA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,iBAAiB,QAAQ;AAAA,MACzB,eAAe;AAAA,MACf,eAAe;AAAA,MACf,gBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,sBACpB,UACA,UACA,UAA8C,CAAC,GAChB;AAC/B,QAAM,KAAK,IAAI,KAAK,QAAQ,MAAM,KAAK,KAAK,IAAI,CAAC,EAAE,YAAY;AAC/D,SAAO,aAAa,UAAU,UAAU,CAAC,YAAY;AAAA,IACnD,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,UAAU,CAAC;AAAA,IACX,qBAAqB;AAAA,IACrB,eAAe;AAAA,IACf,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,eAAe;AAAA,IACf,gBAAgB;AAAA,EAClB,EAAE;AACJ;AAGA,eAAsB,oBACpB,UACA,UACA,UAAiC,CAAC,GACH;AAC/B,QAAM,QAAQ,QAAQ,MAAM,KAAK,KAAK,IAAI;AAC1C,QAAM,SAAS,4BAA4B,QAAQ,MAAM;AACzD,SAAO,aAAa,UAAU,UAAU,CAAC,WAAW;AAClD,QAAI,OAAO,WAAW,iBAAiB,OAAO,WAAW,eAAgB,QAAO;AAChF,UAAM,QAAQ,cAAc,OAAO,eAAe,MAAM;AACxD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,eAAe,OAAO,gBAAgB;AAAA,MACtC,eAAe,IAAI,KAAK,QAAQ,KAAK,EAAE,YAAY;AAAA,MACnD,eAAe;AAAA,MACf,gBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AACH;AAQA,eAAsB,qBACpB,UACA,UACA,UAAiC,CAAC,GACT;AACzB,QAAM,QAAQ,QAAQ,MAAM,KAAK,KAAK,IAAI;AAC1C,QAAM,KAAK,IAAI,KAAK,KAAK,EAAE,YAAY;AACvC,QAAM,SAAS,4BAA4B,QAAQ,MAAM;AACzD,MAAI,WAAW;AACf,QAAM,SAAS,MAAM,aAAa,UAAU,UAAU,CAAC,YAAY;AACjE,UAAM,gBAAgB,QAAQ,kBAAkB,OAAO,IAAI,KAAK,MAAM,QAAQ,aAAa;AAC3F,QAAI,OAAO,SAAS,aAAa,KAAK,gBAAgB,MAAO,QAAO;AAEpE,UAAM,eAAe,QAAQ,mBAAmB,OAAO,IAAI,KAAK,MAAM,QAAQ,cAAc;AAC5F,UAAM,eACJ,QAAQ,iBACR,OAAO,SAAS,YAAY,KAC5B,QAAQ,eAAe,OAAO;AAChC,QAAI,aAAc,QAAO;AAEzB,eAAW;AACX,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,eAAe;AAAA,MACf,eAAe;AAAA,MACf,gBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AACD,SAAO,EAAE,UAAU,OAAO;AAC5B;;;AChOO,IAAM,6BAAN,cAAyC,MAAM;AAAA,EAC3C;AAAA,EACA;AAAA,EAET,YAAY,UAA2B,MAAmB;AACxD;AAAA,MACE,6CAA6C,QAAQ,MAAM,IAAI;AAAA,IACjE;AACA,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,OAAO;AAAA,EACd;AACF;AAUA,SAAS,YAAY,OAAsB,OAA8B;AACvE,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,SAAO,OAAO,SAAS,MAAM,IAAI,KAAK,IAAI,GAAG,SAAS,KAAK,IAAI;AACjE;AAEA,SAAS,cACP,QACA,QACS;AACT,MAAI,QAAQ,mBAAmB,KAAM,QAAO;AAC5C,SAAO,eAAe,cAAc,OAAO,iBAAiB,MAAM,GAAG,OAAO,mBAAmB;AACjG;AAEA,eAAe,WACb,UACA,QACA,SAM2B;AAC3B,MAAI,WAAW,UAAa,OAAO,WAAW,WAAW;AACvD,WAAO,EAAE,WAAW,MAAM,QAAQ,MAAM,eAAe,MAAM,QAAQ,MAAM,SAAS,MAAM;AAAA,EAC5F;AAEA,QAAM,SAAS,OAAO;AACtB,MAAI,OAAO,WAAW,eAAe;AACnC,UAAM,cAAc,WAAW,QAAQ,cAAc,QAAQ,QAAQ,MAAM;AAC3E,WAAO;AAAA,MACL,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,eAAe;AAAA,MACf;AAAA,MACA,SAAS,QAAQ,WAAW,CAAC;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,YAAY;AAChC,UAAM,MAAM,cAAc,QAAQ,QAAQ,MAAM;AAChD,UAAM,SAAS,MACX,MAAM,oBAAoB,QAAQ,YAAY,UAAU;AAAA,MACtD,KAAK,MAAM,QAAQ;AAAA,MACnB,QAAQ,QAAQ,OAAO;AAAA,IACzB,CAAC,IACD;AACJ,WAAO;AAAA,MACL,WAAW,CAAC;AAAA,MACZ,QAAQ,MAAM,YAAY,OAAO,eAAe,QAAQ,KAAK,IAAI;AAAA,MACjE,eAAe,OAAO;AAAA,MACtB;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AAMA,MACE,OAAO,WAAW,iBAClB,OAAO,WAAW,kBAClB,OAAO,WAAW,aAClB;AACA,UAAM,SAAS,YAAY,OAAO,eAAe,QAAQ,KAAK;AAC9D,QAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,aAAO;AAAA,QACL,WAAW;AAAA,QACX;AAAA,QACA,eAAe,OAAO;AAAA,QACtB;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AACA,UAAM,QAAQ,MAAM,qBAAqB,QAAQ,YAAY,UAAU;AAAA,MACrE,KAAK,MAAM,QAAQ;AAAA,MACnB,QAAQ,QAAQ,OAAO;AAAA,IACzB,CAAC;AACD,WAAO;AAAA,MACL,WAAW,MAAM;AAAA,MACjB,QAAQ,MAAM,WACV,OACA,4BAA4B,QAAQ,OAAO,SAAS,EAAE;AAAA,MAC1D,eAAe,MAAM,OAAO;AAAA,MAC5B;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO,EAAE,WAAW,MAAM,QAAQ,MAAM,eAAe,MAAM,QAAQ,SAAS,MAAM;AACtF;AAEA,SAAS,cAAc,SAA0B,QAA6C;AAC5F,0BAAwB;AACxB,QAAM,aAAa,uBAAuB;AAC1C,QAAM,cAAc,OAAO,WAAW,SAAS,CAAC,GAAG,OAAO,iBAAiB;AAC3E,SAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,SAAS,GAAG,YAAY,GAAG,UAAU,CAAC,CAAC;AAC7D;AAEA,SAAS,YACP,MACA,UACuB;AACvB,MAAI,aAAa,KAAK,SAAU,QAAO;AACvC,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA;AAAA;AAAA;AAAA,IAIA,OAAO;AAAA,EACT;AACF;AAMA,eAAsB,yBACpB,OACA,UAII,CAAC,GACoB;AACzB,QAAM,SAAS,QAAQ,UAAU,0BAA0B;AAC3D,QAAM,OAAO,MAAM,gBAAgB,KAAK;AACxC,QAAM,WAAW,OAAO,WAAW,aAAa;AAChD,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,eAAe;AAAA,IACjB;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,kBAAc,MAAM,oBAAoB,GAAG;AAAA,EAC7C,QAAQ;AACN,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,eAAe;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,QAAQ,QAAQ,SAAS;AAC/B,YAAW,YAAS;AAClB,UAAM,QAAQ,QAAQ,MAAM,KAAK,KAAK,IAAI;AAC1C,UAAM,SAAS,MAAM,oBAAoB,UAAU;AACnD,UAAM,QAAkB,CAAC;AACzB,QAAI,gBAAoC;AACxC,QAAI,kBAAiC;AAErC,eAAW,YAAY,cAAc,KAAK,UAAU,MAAM,GAAG;AAC3D,YAAM,UAAU,MAAM,WAAW,UAAU,OAAO,UAAU,QAAQ,GAAG;AAAA,QACrE;AAAA,QACA;AAAA,QACA,SAAS,aAAa,KAAK;AAAA,QAC3B;AAAA,MACF,CAAC;AACD,UAAI,aAAa,KAAK,UAAU;AAC9B,wBAAgB,QAAQ;AACxB,0BAAkB,QAAQ;AAAA,MAC5B;AACA,UAAI,QAAQ,WAAW,QAAQ,WAAW,MAAM;AAC9C,cAAM,IAAI,2BAA2B,UAAU,QAAQ,MAAM;AAAA,MAC/D;AACA,UACE,aAAa,KAAK,YAClB,CAAC,QAAQ,aACT,QAAQ,WAAW,QACnB,CAAC,cAAc,OAAO,UAAU,QAAQ,GAAG,MAAM,GACjD;AACA,YAAI,CAAE,MAAM,MAAM,KAAK,IAAI,GAAG,QAAQ,MAAM,GAAG,EAAE,QAAQ,kBAAkB,EAAE,CAAC,GAAI;AAChF,gBAAM,IAAI,MAAM,sEAAsE;AAAA,QACxF;AACA,iBAAS;AAAA,MACX;AACA,UAAI,QAAQ,WAAW;AACrB,eAAO;AAAA,UACL,SAAS,KAAK;AAAA,UACd;AAAA,UACA,UAAU,YAAY,MAAM,QAAQ;AAAA,UACpC;AAAA,UACA,UAAU,aAAa,KAAK;AAAA,UAC5B,QAAQ,aAAa,KAAK,WAAW,OAAO;AAAA,UAC5C,eAAe;AAAA,QACjB;AAAA,MACF;AACA,UAAI,QAAQ,WAAW,KAAM,OAAM,KAAK,QAAQ,MAAM;AAAA,IACxD;AAEA,UAAM,SAAS,MAAM,SAAS,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC,IAAI;AACpE,QAAI,WAAW,MAAM;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAE,MAAM,MAAM,QAAQ,EAAE,QAAQ,kBAAkB,EAAE,CAAC,GAAI;AAC3D,YAAM,IAAI,MAAM,sEAAsE;AAAA,IACxF;AAAA,EACF;AACF;;;ACnPA,eAAe,mBAAmB,YAAsD;AACtF,QAAM,WAAW,MAAM,gBAAgB,WAAW,OAAO;AAAA,IACvD,KAAK,EAAE,eAAe,WAAW,cAAc;AAAA,EACjD,CAAC;AACD,SAAO;AAAA,IACL,SAAS,SAAS;AAAA,IAClB,UAAU,SAAS;AAAA,IACnB;AAAA,IACA,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,eAAe;AAAA,EACjB;AACF;AAEA,IAAM,WAAW,oBAAI,IAAoB;AACzC,IAAM,cAAc,oBAAI,IAAyB;AACjD,IAAM,aAAa;AAAA,EACjB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AACf;AAGO,SAAS,sBAAsB,UAGpC;AACA,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,EAAE,SAAS,eAAe,QAAQ,YAAY;AAAA,IACvD,KAAK;AACH,aAAO,EAAE,SAAS,aAAa,QAAQ,SAAS;AAAA,IAClD,KAAK;AACH,aAAO,EAAE,SAAS,cAAc,QAAQ,SAAS;AAAA,IACnD,KAAK;AACH,aAAO,EAAE,SAAS,mBAAmB,QAAQ,SAAS;AAAA,IACxD,SAAS;AACP,YAAM,cAAqB;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,SAAS,UACP,WACA,SACA,kBAAkB,GACA;AAClB,MAAI,UAAU,SAAU,QAAO;AAC/B,MAAI,UAAU,EAAG,QAAO;AACxB,MAAI,kBAAkB,EAAG,QAAO;AAChC,SAAO;AACT;AAWA,SAAS,YAAY,OAAuB;AAC1C,QAAM,WAAW,SAAS,IAAI,KAAK,KAAK,KAAK;AAC7C,WAAS,IAAI,OAAO,OAAO;AAC3B,SAAO;AACT;AAEO,SAAS,4BAAkC;AAChD,WAAS,MAAM;AACf,cAAY,MAAM;AAClB,aAAW,cAAc;AACzB,aAAW,aAAa;AACxB,aAAW,aAAa;AACxB,aAAW,cAAc;AAC3B;AAGA,eAAsB,oBAAoB,YAAwD;AAChG,QAAM,SAAS,0BAA0B;AACzC,QAAM,YACJ,WAAW,kBAAkB,SACzB,MAAM,yBAAyB,WAAW,OAAO,EAAE,OAAO,CAAC,IAC3D,MAAM,mBAAmB,UAAU;AACzC,QAAM,UAAU,YAAY,WAAW,KAAK;AAC5C,QAAM,YAAY,oBAAoB;AACtC,YAAU,QAAQ;AAAA,IAChB,MAAM;AAAA,IACN,IAAI,OAAO;AAAA,IACX;AAAA,IACA,UAAU,UAAU;AAAA,IACpB,OAAO,UAAU,SAAS;AAAA,IAC1B,iBAAiB,UAAU;AAAA,EAC7B,CAAC;AACD,MAAI,UAAU,UAAU;AACtB,cAAU,QAAQ;AAAA,MAChB,MAAM;AAAA,MACN,IAAI,OAAO;AAAA,MACX,MAAM,UAAU;AAAA,MAChB,IAAI,UAAU;AAAA,MACd,QAAQ,UAAU;AAAA,MAClB,eAAe,UAAU;AAAA,IAC3B,CAAC;AACD,oBAAgB;AAAA,MACd,OAAO;AAAA,MACP,SAAS,uBAAuB,UAAU,OAAO,OAAO,UAAU,QAAQ;AAAA,MAC1E,SAAS,EAAE,QAAQ,UAAU,QAAQ,eAAe,UAAU,cAAc;AAAA,MAC5E,QAAQ;AAAA,QACN,OAAO,WAAW;AAAA,QAClB,SAAS,UAAU;AAAA,QACnB,OAAO,UAAU,SAAS;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,sBAAsB,UAAU,QAAQ;AACzD,QAAM,YAAY,UAAU,SAAS;AACrC,QAAM,aAAa,MAAM,kBAAkB;AAC3C,QAAM,WAAW,MAAM,gBAAgB;AACvC,QAAM,kBAAkB,cAAc;AAAA,IACpC,OAAO,WAAW;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,MAAM,WAAW;AAAA,IACjB,SAAS,WAAW;AAAA,IACpB,WAAW,0BAA0B,UAAU,qBAAqB,CAAC;AAAA,IACrE,2BAA2B,WAAW,SAAS,UAAU,KAAK;AAAA,EAChE,CAAC;AACD,QAAM,cAAc,MAAM,eAAe;AAAA,IACvC,SAAU,WAAW,WAAW,WAAW;AAAA,IAC3C;AAAA,IACA,SAAS,UAAU,WAAW,SAAS,WAAW,eAAe;AAAA,IACjE,eAAe,UAAU,WACrB,UAAU,SACV,UAAU,IACP,YAAY,IAAI,WAAW,KAAK,KAAK,OACtC;AAAA,IACN,SAAS,SAAS;AAAA,IAClB,UAAU,SAAS;AAAA,IACnB,gBAAgB,mBAAmB,UAAU,QAAQ,KAAK;AAAA,IAC1D,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,aAAa,YAAY,WAAW;AAAA,IACpC,GAAI,WAAW,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,WAAW,UAAU;AAAA,IAChF,GAAI,WAAW,oBAAoB,SAC/B,CAAC,IACD,EAAE,iBAAiB,WAAW,gBAAgB;AAAA,IAClD,GAAI,WAAW,aAAa,SAAY,CAAC,IAAI,EAAE,UAAU,WAAW,SAAS;AAAA,IAC7E,GAAI,oBAAoB,OACpB,CAAC,IACD,EAAE,gBAAkF;AAAA,EAC1F,CAAC;AACD,wBAAsB;AAAA,IACpB;AAAA,IACA,OAAO,WAAW;AAAA,IAClB,SAAS,SAAS;AAAA,IAClB,OAAO;AAAA,IACP,OAAO,WAAW,UAAU,KAAK,GAAG,KAAK;AAAA,EAC3C,CAAC;AAED,QAAM,SAAS,UAAU,UAAU,QAAQ;AAC3C,QAAM,UAAU,iBAAiB;AAAA,IAC/B,UAAU,WAAW;AAAA,IACrB,OAAO;AAAA,MACL,aAAa,WAAW;AAAA,MACxB,YAAY,WAAW,cAAc,aAAa;AAAA,MAClD,YAAY,WAAW;AAAA,MACvB,YAAY,WAAW;AAAA,IACzB;AAAA,EACF,CAAC;AACD,MAAI,CAAC,QAAQ,IAAI;AACf,UAAM,SAAS,cAAc,QAAQ,OAAO,aAAa,QAAQ,QAAQ,KAAK,WAAM,QAAQ,QAAQ,OAAO;AAC3G,UAAMA,OAAM;AAAA,MACV,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,UAAU,UAAU,OAAO,UAAU,SAAS,MAAM;AAAA,MACvE,gBAAgB,mBAAmB,UAAU,QAAQ;AAAA,IACvD;AACA,QAAI,gBAAgB,MAAM;AACxB,YAAM,aAAa;AAAA,QACjB,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,UAAU;AAAA,QACV,YAAY,QAAQ;AAAA,MACtB,CAAC;AAAA,IACH;AACA,WAAO;AAAA,MACL,KAAAA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR,SAAS,EAAE,YAAY,QAAQ,YAAY,QAAQ,OAAO,QAAQ;AAAA,IACpE;AAAA,EACF;AACA,MACE,OAAO,aAAa,iBACpB,WAAW,YAAY,KACvB,4BAA4B,YAAY,UAAU,QAAQ,MAAM,MAChE;AACA,UAAMA,OAAM;AAAA,MACV,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,WACE;AAAA,MACF,UAAU;AAAA,MACV,OAAO;AAAA,MACP,OACE;AAAA,MACF,OAAO,EAAE,UAAU,UAAU,UAAU,OAAO,UAAU,SAAS,MAAM;AAAA,MACvE,gBAAgB,mBAAmB,UAAU,QAAQ;AAAA,IACvD;AACA,QAAI,gBAAgB,MAAM;AACxB,YAAM,aAAa;AAAA,QACjB,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,OAAOA,KAAI;AAAA,QACX,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AACA,UAAMC,WAAU,SAAS,EAAE,QAAQ,SAAS,UAAU,GAAG,QAAQD,KAAI,MAAM,CAAC;AAC5E,WAAO,EAAE,KAAAA,MAAK,SAAAC,UAAS,WAAW,SAAS,QAAQ,KAAK;AAAA,EAC1D;AACA,OACG,WAAW,SAAS,UAAU,KAAK,KACpC,OAAO,aAAa,qBAAqB,mBACzC;AACA,UAAM,QACJ,UAAU,SAAS,OAAO,oBAAoB,SAC1C,EAAE,SAAS,MAAe,QAAQ,OAAgB,IAClD,MAAM,yBAAyB;AAAA,MAC7B,MAAM,UAAU,SAAS,OAAO,mBAAmB;AAAA,IACrD,CAAC;AACP,QAAI,aAAa,SAAS,UAAU,SAAS,OAAO,oBAAoB,QAAQ;AAC9E,YAAM,IAAI;AAAA,QACR,UAAU,WAAW,KAAK,gCAAgC,UAAU,QAAQ;AAAA,MAC9E;AAAA,IACF;AAAA,EACF,YACG,WAAW,SAAS,UAAU,KAAK,KACpC,OAAO,aAAa,qBAAqB,QACzC;AACA,UAAM,IAAI;AAAA,MACR,UAAU,WAAW,KAAK,kCAAkC,UAAU,QAAQ;AAAA,IAChF;AAAA,EACF;AAEA,MAAI;AACJ,QAAM,YAAY,KAAK,IAAI;AAC3B,MAAI;AACF,UAAM,MAAM,OAAO;AAAA,MACjB;AAAA,QACE,GAAG;AAAA,QACH,QAAQ,CAAC,SAAS;AAChB,gBAAM,YAAY,cAAc,IAAI,EAAE,MAAM,GAAG,GAAK;AACpD,oBAAU,QAAQ;AAAA,YAChB,MAAM;AAAA,YACN,IAAI,OAAO;AAAA,YACX,UAAU,UAAU;AAAA,UACtB,CAAC;AACD,cAAI,UAAU,KAAK,MAAM,IAAI;AAC3B,sBAAU,QAAQ;AAAA,cAChB,MAAM;AAAA,cACN,IAAI,OAAO;AAAA,cACX,OAAO,WAAW;AAAA,cAClB;AAAA,cACA,UAAU,UAAU;AAAA,cACpB,QAAQ;AAAA,cACR,SAAS;AAAA,YACX,CAAC;AACD,4BAAgB;AAAA,cACd,OAAO;AAAA,cACP,SAAS;AAAA,cACT,QAAQ;AAAA,gBACN;AAAA,gBACA,OAAO,WAAW;AAAA,gBAClB,SAAS,SAAS;AAAA,gBAClB,OAAO,UAAU,SAAS;AAAA,cAC5B;AAAA,YACF,CAAC;AAAA,UACH;AACA,qBAAW,SAAS,IAAI;AAAA,QAC1B;AAAA,MACF;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,EACF,SAAS,KAAK;AACZ,oBAAgB;AAAA,MACd,OAAO;AAAA,MACP,SAAS,qDACP,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CACjD;AAAA,MACA,WAAW;AAAA,MACX,QAAQ;AAAA,QACN;AAAA,QACA,OAAO,WAAW;AAAA,QAClB,SAAS,SAAS;AAAA,QAClB,OAAO,UAAU,SAAS;AAAA,MAC5B;AAAA,IACF,CAAC;AACD,QAAI,gBAAgB,MAAM;AACxB,YAAM,aAAa;AAAA,QACjB,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AACA,aAAW,cAAc;AACzB,aAAW,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS;AAC3D,MAAI,IAAI,OAAO,YAAY,QAAW;AACpC,eAAW,eAAe,IAAI,MAAM;AACpC,eAAW,cAAc;AAAA,EAC3B;AAEA,QAAM,UACJ,IAAI,WAAW,IAAI,aAAa,IAC5B,OACA,SAAS;AAAA,IACP,QAAQ;AAAA,IACR,UAAU,IAAI;AAAA,IACd,QAAQ,IAAI,aAAa,IAAI,SAAS;AAAA,EACxC,CAAC;AACP,kBAAgB;AAAA,IACd,OAAO,YAAY,OAAO,SAAS;AAAA,IACnC,SACE,YAAY,OACR,mCAAmC,UAAU,QAAQ,KACrD,gCAAgC,UAAU,QAAQ,KAAK,QAAQ,OAAO;AAAA,IAC5E,SAAS;AAAA,MACP;AAAA,MACA,UAAU,IAAI;AAAA,MACd,aAAa,SAAS,QAAQ;AAAA,MAC9B,SAAS,UAAU,WAAW,SAAS,WAAW,eAAe;AAAA,IACnE;AAAA,IACA,QAAQ;AAAA,MACN;AAAA,MACA,OAAO,WAAW;AAAA,MAClB,SAAS,SAAS;AAAA,MAClB,OAAO,IAAI,MAAM;AAAA,IACnB;AAAA,EACF,CAAC;AAED,MAAI,gBAAgB,MAAM;AACxB,UAAM,aAAa;AAAA,MACjB,IAAI;AAAA,MACJ,QAAQ,YAAY,OAAO,cAAc,QAAQ,SAAS,YAAY,YAAY;AAAA,MAClF,OAAO,IAAI;AAAA,MACX,OAAO,YAAY,OAAO,OAAQ,IAAI,SAAS,IAAI;AAAA,MACnD,UAAU,IAAI;AAAA,MACd,eAAe,IAAI,MAAM;AAAA,MACzB,aAAa,IAAI,MAAM,QACnB,YACE,WACA,aACF,YACE,WACA;AAAA,MACN,gBAAgB,IAAI,kBAAkB,mBAAmB,UAAU,QAAQ,KAAK;AAAA,MAChF,mBAAmB,IAAI,aAAa;AAAA,MACpC,UAAU,WAAW;AAAA,IACvB,CAAC;AAAA,EACH;AAEA,MAAI,YAAY,KAAM,aAAY,OAAO,WAAW,KAAK;AAAA,MACpD,aAAY,IAAI,WAAW,OAAO,QAAQ,IAAI;AAEnD,MAAI,SAAsC;AAC1C,MAAI,UAAU,eAAe,MAAM;AACjC,aACE,YAAY,OACR,MAAM,sBAAsB,UAAU,YAAY,UAAU,QAAQ,IACpE,MAAM,sBAAsB,UAAU,YAAY,UAAU,UAAU,SAAS;AAAA,MAC7E,QAAQ,OAAO;AAAA,IACjB,CAAC;AAAA,EACT;AAEA,YAAU,QAAQ;AAAA,IAChB,MAAM;AAAA,IACN,IAAI,OAAO;AAAA,IACX,UAAU,UAAU;AAAA,IACpB,SAAS,YAAY;AAAA,IACrB,GAAI,YAAY,OAAO,CAAC,IAAI,EAAE,aAAa,QAAQ,KAAK;AAAA,IACxD,eAAe,QAAQ,iBAAiB;AAAA,EAC1C,CAAC;AAED,MAAI,YAAY,KAAM,UAAS,OAAO,WAAW,KAAK;AACtD,SAAO,EAAE,KAAK,SAAS,WAAW,SAAS,OAAO;AACpD;;;AClZO,IAAM,2BAA2B;AAAA;AAAA,EAEtC,kBAAkB;AAAA;AAAA,EAElB,SAAS;AAAA;AAAA,EAET,kBAAkB;AAAA;AAAA,EAElB,cAAc;AAAA;AAAA,EAEd,gBAAgB;AAClB;AAGO,IAAM,4BAA4B;AA6BlC,SAAS,gBAAgB,SAAsC;AACpE,QAAM,SAAS,oBAAI,IAAoB;AACvC,MAAI,QAAQ;AAEZ,aAAW,EAAE,MAAM,KAAK,aAAa,OAAO,GAAG;AAC7C,QAAI,MAAM,SAAS,eAAe;AAChC,cAAQ,MAAM;AACd;AAAA,IACF;AACA,QAAI,MAAM,SAAS,QAAS;AAC5B,UAAM,OAAQ,MAA4B;AAC1C,UAAM,SAAU,MAA8B,UAAU;AACxD,UAAM,WAAW,SAAS,aAAa,SAAS,aAAa,qBAAqB,KAAK,MAAM;AAC7F,QAAI,CAAC,SAAU;AACf,WAAO,IAAI,QAAQ,OAAO,IAAI,KAAK,KAAK,KAAK,CAAC;AAAA,EAChD;AACA,SAAO;AACT;AASA,SAAS,iBAAiB,SAAyB;AACjD,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,UAAU;AAEd,aAAW,EAAE,MAAM,KAAK,aAAa,OAAO,GAAG;AAC7C,QAAI,MAAM,SAAS,mBAAmB;AACpC;AACA,gBAAU,KAAK,IAAI,SAAS,OAAO;AACnC;AAAA,IACF;AACA,QAAI,MAAM,SAAS,iBAAkB;AACrC,UAAM,aAAa,MAAM,QAAQ,OAAO,CAAC,UAAU,MAAM,MAAM,EAAE;AACjE,QAAI,aAAa,QAAS,WAAU;AACpC,cAAU,KAAK,IAAI,SAAS,UAAU;AAAA,EACxC;AACA,SAAO;AACT;AASO,SAAS,oBAAoB,OAAoD;AACtF,QAAM,UAAiC,CAAC;AACxC,QAAM,UAAU,MAAM,WAAW;AAEjC,aAAW,CAAC,OAAO,KAAK,KAAK,gBAAgB,OAAO,GAAG;AACrD,QAAI,SAAS,yBAAyB,kBAAkB;AACtD,cAAQ,KAAK;AAAA,QACX,IAAI;AAAA,QACJ,QAAQ,QAAQ,KAAK,qBAAqB,KAAK,sBAAsB,yBAAyB,gBAAgB;AAAA,MAChH,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,MAAM,YAAY,UAAU;AAClD,MAAI,UAAU,yBAAyB,SAAS;AAC9C,YAAQ,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,QAAQ,gBAAgB,OAAO,6BAA6B,yBAAyB,OAAO;AAAA,IAC9F,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,iBAAiB,OAAO;AACvC,MAAI,UAAU,yBAAyB,kBAAkB;AACvD,YAAQ,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,QAAQ,GAAG,MAAM,uDAAuD,yBAAyB,gBAAgB;AAAA,IACnH,CAAC;AAAA,EACH;AAEA,QAAM,QAAQ,MAAM,gBAAgB;AACpC,MAAI,QAAQ,yBAAyB,cAAc;AACjD,YAAQ,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,QAAQ,GAAG,KAAK,kDAAkD,yBAAyB,YAAY;AAAA,IACzG,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,MAAM,WAAW,UAAU;AACxC,MAAI,OAAO,yBAAyB,gBAAgB;AAClD,YAAQ,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,QAAQ,qBAAqB,IAAI,2BAA2B,yBAAyB,cAAc;AAAA,IACrG,CAAC;AAAA,EACH;AAEA,MAAI,MAAM,qBAAqB,MAAM;AACnC,YAAQ,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,SAAS,WAAW,QAAQ,UAAU,0BAA0B;AAC3E;AAKA,IAAM,uBAAuB;AAiBtB,SAAS,iBAAiB,MAAuD;AACtF,QAAM,UAAU,CAAC,GAAI,MAAM,eAAe,CAAC,CAAE,EAC1C,OAAO,CAAC,UAAU,CAAC,MAAM,MAAM,EAC/B,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AACzC,MAAI,QAAQ,WAAW,EAAG,QAAO,CAAC;AAElC,QAAM,SAA6B,CAAC;AACpC,WAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS,sBAAsB;AACzE,UAAM,UAAU,QAAQ,MAAM,OAAO,QAAQ,oBAAoB;AACjE,UAAM,QAAQ,QAAQ,CAAC;AACvB,UAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACvC,UAAM,QACJ,UAAU,UAAa,SAAS,UAAa,MAAM,OAAO,KAAK,KAC1D,OAAO,MAAM,KACd,GAAG,MAAM,EAAE,SAAI,KAAK,EAAE;AAC5B,WAAO,KAAK;AAAA,MACV,OAAO,GAAG,MAAM,eAAe,OAAO,gBAAW,OAAO,SAAS,CAAC,KAAK,KAAK;AAAA,MAC5E;AAAA,MACA,WAAW,OAAO,WAAW,IAAI,CAAC,IAAI,CAAC,OAAO,OAAO,SAAS,CAAC,GAAG,SAAS,EAAE;AAAA,IAC/E,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAeO,SAAS,yBAAyB,OAAyC;AAChF,QAAM,EAAE,aAAa,YAAY,MAAM,GAAG,IAAI;AAC9C,QAAM,YAAY,iBAAiB,IAAI;AACvC,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,YAAY,WAAW,8BAA8B,EAAE;AAClE,QAAM,KAAK,eAAe,EAAE,KAAK,EAAE;AACnC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,KAAK,wBAAwB,EAAE;AACrC,aAAW,UAAU,WAAW,SAAS;AACvC,UAAM,KAAK,OAAO,OAAO,EAAE,aAAQ,OAAO,MAAM,EAAE;AAAA,EACpD;AACA,QAAM,KAAK,EAAE;AAEb,MAAI,UAAU,WAAW,GAAG;AAC1B,UAAM,KAAK,qBAAqB,EAAE;AAClC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA,EAC5B;AAEA,QAAM,KAAK,qBAAqB,EAAE;AAClC,QAAM;AAAA,IACJ,OAAO,UAAU,OAAO,CAAC,OAAO,aAAa,QAAQ,SAAS,QAAQ,QAAQ,CAAC,CAAC,iDACrC,UAAU,MAAM,0BACrD,oBAAoB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,aAAW,YAAY,WAAW;AAChC,UAAM,KAAK,OAAO,SAAS,KAAK,IAAI,EAAE;AACtC,QAAI,SAAS,UAAU,SAAS,GAAG;AACjC,YAAM,KAAK,eAAe,SAAS,UAAU,KAAK,IAAI,CAAC,IAAI,EAAE;AAAA,IAC/D;AACA,eAAW,SAAS,SAAS,SAAS;AACpC,YAAM,KAAK,OAAO,MAAM,EAAE,MAAM,MAAM,KAAK,EAAE;AAAA,IAC/C;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,sBAAsB,EAAE;AACnC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA;AAC5B;;;AC9RA,SAAS,YAAAC,iBAAgB;AACzB,OAAO,WAAW;AA4EX,IAAM,8BAA8B;AAE3C,eAAe,iBACb,WACA,SACiB;AACjB,MAAI,cAAc,KAAK,YAAY,OAAW,QAAO;AAErD,QAAM,WACJ,MAAM,QAAQ;AAAA,IACZ,QAAQ,aAAa,IAAI,OAAO,SAAS;AACvC,UAAI;AACF,eAAO,MAAMC,UAAS,MAAM,OAAO;AAAA,MACrC,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH,GACA,KAAK,EAAE;AACT,QAAM,WAAW,gBAAgB,OAAO,EAAE,IAAI,QAAQ,KAAK,KAAK;AAChE,MAAI,WAAW,yBAAyB,iBAAkB,QAAO;AACjE,SAAO,KAAK,IAAI,YAAY,GAAG,OAAO,gBAAgB;AACxD;AAEA,SAAS,gBAAgB,OAAmB,UAAyC;AACnF,QAAM,QAAQ,SAAS;AACvB,QAAM,UAAU,SAAS;AACzB,QAAM,OAAO,aAAa,CAAC,QAAgB,QAAQ,OAAO,MAAM,GAAG,GAAG;AAAA,CAAI;AAE1E,MAAI,MAAM,SAAS,QAAQ;AACzB,UAAM,QAAQ,MAAM,KAAK,MAAM,IAAI;AACnC,eAAW,YAAY,OAAO;AAC5B,UAAI,CAAC,SAAS,KAAK,EAAG;AACtB,YAAMC,UAAS,UAAU,MAAM,IAAI,KAAK,MAAM,SAAS,IAAI,IAAI,KAAK,MAAM,SAAS;AACnF,YAAM,OAAO,UAAU,MAAM,IAAI,QAAQ,IAAI;AAC7C,WAAK,GAAGA,OAAM,GAAG,IAAI,EAAE;AAAA,IACzB;AACA;AAAA,EACF;AAEA,sBAAoB,EAAE,QAAQ;AAAA,IAC5B,MAAM;AAAA,IACN,IAAI,OAAO;AAAA,IACX,MAAM,MAAM;AAAA,IACZ,QAAQ,MAAM;AAAA,EAChB,CAAC;AACD,QAAM,WAAW,MAAM,KAAK,OAAO,EAAE;AACrC,QAAM,SAAS,UAAU,MAAM,IAAI,KAAK,MAAM,SAAS,IAAI,IAAI,KAAK,MAAM,SAAS;AACnF,QAAM,WAAW,UAAU,MAAM,KAAK,MAAM,IAAI,IAAI,MAAM;AAC1D,QAAM,YAAY,UAAU,MAAM,KAAK,QAAQ,IAAI;AACnD,QAAM,cAAc,MAAM,SAAU,UAAU,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,SAAU;AACxF,OAAK,GAAG,MAAM,GAAG,QAAQ,IAAI,SAAS,IAAI,WAAW,EAAE;AACzD;AAEA,eAAe,oBACb,YAC2D;AAC3D,QAAM,SAAS,0BAA0B;AACzC,MAAI,OAAO,WAAW,aAAa,MAAM;AACvC,WAAO,EAAE,MAAM,MAAM,oBAAoB,UAAU,GAAG,KAAK,gBAAgB,MAAM;AAAA,EACnF;AAEA,MAAI,QAA4B;AAChC,QAAM,UAAU,MAAM,UAAU,MAAM,oBAAoB,UAAU,GAAG;AAAA,IACrE,QAAQ,CAAC,YAAY,cAAc,QAAQ,MAAM,MAAM;AAAA,IACvD,QAAQ,kBAAkB;AAAA,IAC1B,UAAU,CAAC,aAAa,SAAS;AAAA,IACjC,WAAW,CAAC,EAAE,OAAO,SAAS,WAAW,SAAS,QAAQ,MAAM;AAC9D,UAAI,MAAM,IAAI,UAAU,KAAM,SAAQ,SAAS,OAAO,MAAM,IAAI,KAAK;AACrE,UAAI,YAAY,QAAQ,CAAC,UAAW;AACpC,0BAAoB,EAAE,QAAQ;AAAA,QAC5B,MAAM;AAAA,QACN,IAAI,OAAO;AAAA,QACX;AAAA,QACA,cAAc,UAAU;AAAA,QACxB,QAAQ,QAAQ;AAAA,QAChB,MAAM,QAAQ;AAAA,MAChB,CAAC;AACD,sBAAgB;AAAA,QACd,OAAO;AAAA,QACP,SAAS,YAAY,WAAW,KAAK,UAAU,QAAQ,IAAI;AAAA,QAC3D,SAAS,EAAE,SAAS,SAAS,QAAQ,QAAQ,QAAQ;AAAA,QACrD,QAAQ,EAAE,OAAO,WAAW,MAAM;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,KAAK,UAAU,OAAO,QAAQ,MAAM,MAAM,EAAE,GAAG,QAAQ,MAAM,KAAK,MAAM;AAAA,IACxE,gBAAgB,QAAQ;AAAA,EAC1B;AACF;AAQA,eAAsB,YAAY,SAAmD;AACnF,QAAM;AAAA,IACJ;AAAA,IACA,WAAW;AAAA,IACX,SAAS,oBAAoB;AAAA,IAC7B,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,UAAU,MAAM,iBAAiB,mBAAmB,QAAQ,cAAc;AAChF,QAAM,WAAW,MAAM,gBAAgB,KAAK;AAE5C,QAAM,UAAU,UAAU;AAC1B,QAAM,oBAAoB,YAAY,kBAAkB;AAExD,MAAI,SAAS;AACX,UAAM,QAAQ,SAAS;AACvB,UAAM,UAAU,SAAS;AACzB,UAAM,OAAO,sBAAsB,CAAC,QAAgB,QAAQ,OAAO,MAAM,GAAG,GAAG;AAAA,CAAI;AACnF,QAAI,eAAe;AACjB,YAAM,MAAM,UACR,MAAM,KAAK,GAAG,MAAM,KAAK,IAAI,aAAa,EAAE,IAC5C,GAAG,MAAM,KAAK,IAAI,aAAa;AACnC,WAAK,GAAG;AAAA,IACV;AACA,UAAM,gBAAgB,UAAU,MAAM,IAAI,KAAK,MAAM,SAAS,EAAE,IAAI,KAAK,MAAM,SAAS;AACxF,SAAK,aAAa;AAElB,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,EAAE,KAAK,eAAe,IAAI,MAAM,oBAAoB;AAAA,MACxD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,kBAAkB,SAAY,CAAC,IAAI,EAAE,cAAc;AAAA,MACvD,GAAI,YAAY,SAAY,CAAC,IAAI,EAAE,QAAQ;AAAA,MAC3C,GAAI,oBAAoB,SAAY,CAAC,IAAI,EAAE,gBAAgB;AAAA,MAC3D,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA,MAC7C,SAAS,CAAC,UAAU,gBAAgB,OAAO,iBAAiB;AAAA,IAC9D,CAAC;AAED,UAAM,aAAa,KAAK,OAAO,KAAK,IAAI,IAAI,aAAa,GAAI;AAC7D,UAAM,cAAc,eAAe,UAAU;AAC7C,UAAM,WAAW,UACb,MAAM,IAAI,KAAK,MAAM,SAAS,KAAK,MAAM,OAAO,WAAW,WAAW,EAAE,CAAC,EAAE,IAC3E,KAAK,MAAM,SAAS,aAAa,WAAW;AAChD,SAAK,QAAQ;AACb,SAAK,aAAa;AAElB,WAAO,kBAAkB,KAAK,cAAc,cAAc;AAAA,EAC5D;AAEA,QAAM,UAAU,gBAAgB,cAAc,aAAa,EAAE,MAAM,IAAI;AACvE,MAAI,QAA6B;AACjC,MAAI,SAAS;AACX,YAAQ,IAAI,aAAa,CAAC,YAAY;AACpC,cAAQ,aAAa,SAAS,IAAI,MAAM,IAAI,IAAI,OAAO,GAAG,IAAI,IAAI,OAAO;AAAA,IAC3E,CAAC,EAAE,MAAM;AAAA,EACX;AAEA,MAAI;AACF,UAAM,EAAE,KAAK,eAAe,IAAI,MAAM,oBAAoB;AAAA,MACxD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,qBAAqB,qBAAqB;AAAA,MAC1C,GAAI,kBAAkB,SAAY,CAAC,IAAI,EAAE,cAAc;AAAA,MACvD,GAAI,YAAY,SAAY,CAAC,IAAI,EAAE,QAAQ;AAAA,MAC3C,GAAI,oBAAoB,SAAY,CAAC,IAAI,EAAE,gBAAgB;AAAA,MAC3D,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA,MAC7C,SAAS,CAAC,UAAU;AAClB,YAAI,MAAM,SAAS,OAAQ;AAC3B,4BAAoB,EAAE,QAAQ;AAAA,UAC5B,MAAM;AAAA,UACN,IAAI,OAAO;AAAA,UACX,MAAM,MAAM;AAAA,UACZ,QAAQ,MAAM;AAAA,QAChB,CAAC;AACD,4BAAoB,IAAI,EAAE,MAAM,MAAM,MAAM,QAAQ,MAAM,OAAO,CAAC;AAAA,MACpE;AAAA,IACF,CAAC;AAED,UAAM,UAAU,OAAO,KAAK,KAAK;AACjC,UAAM,MAAM,SAAS,IACjB,MAAM,IAAI,KAAK,eAAe,OAAO,CAAC,GAAG,IACzC,KAAK,eAAe,OAAO,CAAC;AAEhC,QAAI,CAAC,IAAI,SAAS;AAChB,eAAS,KAAK,GAAG,aAAa,GAAG,GAAG,EAAE;AACtC,aAAO,kBAAkB,KAAK,cAAc,cAAc;AAAA,IAC5D;AAEA,aAAS,QAAQ,GAAG,aAAa,GAAG,GAAG,EAAE;AACzC,WAAO,kBAAkB,KAAK,cAAc,cAAc;AAAA,EAC5D,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,eAAe,OAAO,KAAK,KAAK;AACtC,UAAM,WAAW,SAAS,IACtB,MAAM,IAAI,KAAK,eAAe,YAAY,CAAC,GAAG,IAC9C,KAAK,eAAe,YAAY,CAAC;AACrC,aAAS,KAAK,GAAG,aAAa,GAAG,QAAQ,EAAE;AAC3C,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,SAAS,UAAU,OAAO,SAAS,MAAM;AAAA,IAC9D;AAAA,EACF;AACF;AAEA,SAAS,kBACP,KAQA,cACA,iBAAiB,OACD;AAChB,MAAI,iBAAiB,QAAQ;AAC3B,WAAO;AAAA,MACL,SAAS,IAAI;AAAA,MACb,QAAQ,IAAI,UAAU,IAAI,aAAa,IAAI,SAAS;AAAA,MACpD,MAAM;AAAA,MACN,OAAO,IAAI;AAAA,MACX,OAAO,IAAI;AAAA,MACX,GAAI,iBAAiB,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAAA,IACnD;AAAA,EACF;AACA,MAAI,CAAC,IAAI,SAAS;AAChB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,IAAI;AAAA,MACX,OAAO,IAAI;AAAA,MACX,GAAI,iBAAiB,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAAA,IACnD;AAAA,EACF;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ,IAAI;AAAA,IACZ,MAAM,IAAI;AAAA,IACV,OAAO;AAAA,IACP,OAAO,IAAI;AAAA,IACX,GAAI,iBAAiB,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAAA,EACnD;AACF;","names":["run","failure","readFile","readFile","prefix"]}
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/telemetry/aggregate.ts
4
+ function emptySummary(discarded = 0) {
5
+ return {
6
+ count: 0,
7
+ discarded,
8
+ byStatus: {},
9
+ usage: {
10
+ inputTokens: 0,
11
+ outputTokens: 0,
12
+ cacheReadTokens: 0,
13
+ cacheCreationTokens: 0,
14
+ reasoningTokens: 0
15
+ },
16
+ totalCost: { reported: 0, estimated: 0, unknownExecutions: 0 }
17
+ };
18
+ }
19
+ function add(into, record) {
20
+ into.count += 1;
21
+ into.byStatus[record.status] = (into.byStatus[record.status] ?? 0) + 1;
22
+ if (record.usage !== null) {
23
+ into.usage.inputTokens += record.usage.inputTokens ?? 0;
24
+ into.usage.outputTokens += record.usage.outputTokens ?? 0;
25
+ into.usage.cacheReadTokens += record.usage.cacheReadTokens ?? 0;
26
+ into.usage.cacheCreationTokens += record.usage.cacheCreationTokens ?? 0;
27
+ into.usage.reasoningTokens += record.usage.reasoningTokens ?? 0;
28
+ }
29
+ if (record.cost.status === "reported") {
30
+ into.totalCost.reported += record.cost.amount;
31
+ } else if (record.cost.status === "estimated") {
32
+ into.totalCost.estimated += record.cost.amount;
33
+ } else {
34
+ into.totalCost.unknownExecutions += 1;
35
+ }
36
+ }
37
+ function isPlan(value) {
38
+ return !Array.isArray(value) && "userStories" in value;
39
+ }
40
+ function summarize(input, discarded = 0) {
41
+ const records = isPlan(input) ? input.executions ?? [] : input;
42
+ const summary = emptySummary(discarded);
43
+ for (const record of records) add(summary, record);
44
+ return summary;
45
+ }
46
+ function keyOf(record, key) {
47
+ switch (key) {
48
+ case "harness":
49
+ return record.agent.harness;
50
+ case "provider":
51
+ return record.agent.provider ?? "unknown";
52
+ case "model":
53
+ return record.agent.model.resolved ?? record.agent.model.requested ?? "unknown";
54
+ case "purpose":
55
+ return record.purpose;
56
+ case "status":
57
+ return record.status;
58
+ default: {
59
+ const _exhaustive = key;
60
+ return _exhaustive;
61
+ }
62
+ }
63
+ }
64
+ function groupBy(records, key) {
65
+ const groups = /* @__PURE__ */ new Map();
66
+ for (const record of records) {
67
+ const name = keyOf(record, key);
68
+ const bucket = groups.get(name);
69
+ if (bucket === void 0) groups.set(name, [record]);
70
+ else bucket.push(record);
71
+ }
72
+ const result = /* @__PURE__ */ new Map();
73
+ for (const [name, bucket] of groups) {
74
+ result.set(name, summarize(bucket));
75
+ }
76
+ return result;
77
+ }
78
+
79
+ export {
80
+ summarize,
81
+ groupBy
82
+ };
83
+ //# sourceMappingURL=chunk-CRGIQFUQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/telemetry/aggregate.ts"],"sourcesContent":["import type { TaskPlan } from '../types.js';\nimport type { ExecutionRecord, ExecutionStatus, ExecutionSummary } from './types.js';\n\nfunction emptySummary(discarded = 0): ExecutionSummary {\n return {\n count: 0,\n discarded,\n byStatus: {},\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n reasoningTokens: 0,\n },\n totalCost: { reported: 0, estimated: 0, unknownExecutions: 0 },\n };\n}\n\nfunction add(into: ExecutionSummary, record: ExecutionRecord): void {\n into.count += 1;\n into.byStatus[record.status] = (into.byStatus[record.status] ?? 0) + 1;\n if (record.usage !== null) {\n into.usage.inputTokens += record.usage.inputTokens ?? 0;\n into.usage.outputTokens += record.usage.outputTokens ?? 0;\n into.usage.cacheReadTokens += record.usage.cacheReadTokens ?? 0;\n into.usage.cacheCreationTokens += record.usage.cacheCreationTokens ?? 0;\n into.usage.reasoningTokens += record.usage.reasoningTokens ?? 0;\n }\n if (record.cost.status === 'reported') {\n into.totalCost.reported += record.cost.amount;\n } else if (record.cost.status === 'estimated') {\n into.totalCost.estimated += record.cost.amount;\n } else {\n into.totalCost.unknownExecutions += 1;\n }\n}\n\nfunction isPlan(value: TaskPlan | readonly ExecutionRecord[]): value is TaskPlan {\n return !Array.isArray(value) && 'userStories' in value;\n}\n\nexport function summarize(\n input: TaskPlan | readonly ExecutionRecord[],\n discarded = 0,\n): ExecutionSummary {\n const records = isPlan(input) ? (input.executions ?? []) : input;\n const summary = emptySummary(discarded);\n for (const record of records) add(summary, record);\n return summary;\n}\n\nexport type GroupKey = 'harness' | 'provider' | 'model' | 'purpose' | 'status';\n\nfunction keyOf(record: ExecutionRecord, key: GroupKey): string {\n switch (key) {\n case 'harness':\n return record.agent.harness;\n case 'provider':\n return record.agent.provider ?? 'unknown';\n case 'model':\n return record.agent.model.resolved ?? record.agent.model.requested ?? 'unknown';\n case 'purpose':\n return record.purpose;\n case 'status':\n return record.status;\n default: {\n const _exhaustive: never = key;\n return _exhaustive;\n }\n }\n}\n\nexport function groupBy(\n records: readonly ExecutionRecord[],\n key: GroupKey,\n): Map<string, ExecutionSummary> {\n const groups = new Map<string, ExecutionRecord[]>();\n for (const record of records) {\n const name = keyOf(record, key);\n const bucket = groups.get(name);\n if (bucket === undefined) groups.set(name, [record]);\n else bucket.push(record);\n }\n const result = new Map<string, ExecutionSummary>();\n for (const [name, bucket] of groups) {\n result.set(name, summarize(bucket));\n }\n return result;\n}\n\nexport type { ExecutionStatus };\n"],"mappings":";;;AAGA,SAAS,aAAa,YAAY,GAAqB;AACrD,SAAO;AAAA,IACL,OAAO;AAAA,IACP;AAAA,IACA,UAAU,CAAC;AAAA,IACX,OAAO;AAAA,MACL,aAAa;AAAA,MACb,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,qBAAqB;AAAA,MACrB,iBAAiB;AAAA,IACnB;AAAA,IACA,WAAW,EAAE,UAAU,GAAG,WAAW,GAAG,mBAAmB,EAAE;AAAA,EAC/D;AACF;AAEA,SAAS,IAAI,MAAwB,QAA+B;AAClE,OAAK,SAAS;AACd,OAAK,SAAS,OAAO,MAAM,KAAK,KAAK,SAAS,OAAO,MAAM,KAAK,KAAK;AACrE,MAAI,OAAO,UAAU,MAAM;AACzB,SAAK,MAAM,eAAe,OAAO,MAAM,eAAe;AACtD,SAAK,MAAM,gBAAgB,OAAO,MAAM,gBAAgB;AACxD,SAAK,MAAM,mBAAmB,OAAO,MAAM,mBAAmB;AAC9D,SAAK,MAAM,uBAAuB,OAAO,MAAM,uBAAuB;AACtE,SAAK,MAAM,mBAAmB,OAAO,MAAM,mBAAmB;AAAA,EAChE;AACA,MAAI,OAAO,KAAK,WAAW,YAAY;AACrC,SAAK,UAAU,YAAY,OAAO,KAAK;AAAA,EACzC,WAAW,OAAO,KAAK,WAAW,aAAa;AAC7C,SAAK,UAAU,aAAa,OAAO,KAAK;AAAA,EAC1C,OAAO;AACL,SAAK,UAAU,qBAAqB;AAAA,EACtC;AACF;AAEA,SAAS,OAAO,OAAiE;AAC/E,SAAO,CAAC,MAAM,QAAQ,KAAK,KAAK,iBAAiB;AACnD;AAEO,SAAS,UACd,OACA,YAAY,GACM;AAClB,QAAM,UAAU,OAAO,KAAK,IAAK,MAAM,cAAc,CAAC,IAAK;AAC3D,QAAM,UAAU,aAAa,SAAS;AACtC,aAAW,UAAU,QAAS,KAAI,SAAS,MAAM;AACjD,SAAO;AACT;AAIA,SAAS,MAAM,QAAyB,KAAuB;AAC7D,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,OAAO,MAAM;AAAA,IACtB,KAAK;AACH,aAAO,OAAO,MAAM,YAAY;AAAA,IAClC,KAAK;AACH,aAAO,OAAO,MAAM,MAAM,YAAY,OAAO,MAAM,MAAM,aAAa;AAAA,IACxE,KAAK;AACH,aAAO,OAAO;AAAA,IAChB,KAAK;AACH,aAAO,OAAO;AAAA,IAChB,SAAS;AACP,YAAM,cAAqB;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEO,SAAS,QACd,SACA,KAC+B;AAC/B,QAAM,SAAS,oBAAI,IAA+B;AAClD,aAAW,UAAU,SAAS;AAC5B,UAAM,OAAO,MAAM,QAAQ,GAAG;AAC9B,UAAM,SAAS,OAAO,IAAI,IAAI;AAC9B,QAAI,WAAW,OAAW,QAAO,IAAI,MAAM,CAAC,MAAM,CAAC;AAAA,QAC9C,QAAO,KAAK,MAAM;AAAA,EACzB;AACA,QAAM,SAAS,oBAAI,IAA8B;AACjD,aAAW,CAAC,MAAM,MAAM,KAAK,QAAQ;AACnC,WAAO,IAAI,MAAM,UAAU,MAAM,CAAC;AAAA,EACpC;AACA,SAAO;AACT;","names":[]}
@@ -1,12 +1,23 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ getAgentCliOverrides,
4
+ hasExplicitAgentSelection,
5
+ loadAgentConfig
6
+ } from "./chunk-QJ5UZAH5.js";
2
7
  import {
3
8
  printError,
4
9
  printInfo,
5
10
  printSuccess,
6
11
  printWarning
7
- } from "./chunk-BYZDPR7N.js";
12
+ } from "./chunk-TYRNTSPJ.js";
13
+ import {
14
+ AGENT_PHASES
15
+ } from "./chunk-LBGHI4S2.js";
8
16
 
9
17
  // src/commands/init.ts
18
+ import { readFile } from "fs/promises";
19
+ import { homedir } from "os";
20
+ import { join } from "path";
10
21
  import { execa } from "execa";
11
22
  async function checkClaude() {
12
23
  try {
@@ -66,6 +77,40 @@ async function checkGh() {
66
77
  };
67
78
  }
68
79
  }
80
+ async function checkCodex() {
81
+ try {
82
+ const proc = await execa("codex", ["--version"], { reject: false, timeout: 1e4 });
83
+ if (proc.exitCode !== 0) {
84
+ return {
85
+ key: "codex",
86
+ name: "codex CLI",
87
+ passed: false,
88
+ detail: "codex command failed",
89
+ hint: "Install Codex CLI: https://developers.openai.com/codex/noninteractive"
90
+ };
91
+ }
92
+ const version = proc.stdout?.toString().trim() ?? "unknown";
93
+ const auth = await execa("codex", ["login", "status"], { reject: false, timeout: 1e4 });
94
+ if (auth.exitCode !== 0) {
95
+ return {
96
+ key: "codex",
97
+ name: "codex CLI",
98
+ passed: false,
99
+ detail: `${version} (not authenticated)`,
100
+ hint: "Run: codex login --with-api-key (or set CODEX_API_KEY)"
101
+ };
102
+ }
103
+ return { key: "codex", name: "codex CLI", passed: true, detail: `${version} (authenticated)` };
104
+ } catch {
105
+ return {
106
+ key: "codex",
107
+ name: "codex CLI",
108
+ passed: false,
109
+ detail: "codex not found",
110
+ hint: "Install Codex CLI: https://developers.openai.com/codex/noninteractive"
111
+ };
112
+ }
113
+ }
69
114
  async function checkGit() {
70
115
  try {
71
116
  const proc = await execa("git", ["--version"], { reject: false, timeout: 1e4 });
@@ -108,6 +153,13 @@ var ACTION_ICON = {
108
153
  keep: "=",
109
154
  review: "!"
110
155
  };
156
+ function summarizePreflight(results, plan) {
157
+ const kept = plan.actions.filter((action) => action.kind === "keep").length;
158
+ const creates = plan.actions.filter((action) => action.kind === "create").length;
159
+ const env = results.every((result) => result.passed) ? "environment ok" : "environment failed";
160
+ const createBit = creates === 0 ? "nothing to create" : `${creates} to create`;
161
+ return `Preflight: ${env} \xB7 ${kept} conventions kept \xB7 ${createBit}`;
162
+ }
111
163
  function renderPlan(plan, apply) {
112
164
  const creates = plan.actions.filter((a) => a.kind === "create");
113
165
  const reviews = plan.actions.filter((a) => a.kind === "review");
@@ -139,40 +191,55 @@ function renderPlan(plan, apply) {
139
191
  }
140
192
  async function runInit(source = "github", options = {}) {
141
193
  const json = options.json === true;
142
- if (!json) {
194
+ const compact = options.compact === true;
195
+ if (!json && !compact) {
143
196
  printInfo("Checking prerequisites...\n");
144
197
  }
145
- const results = await Promise.all([checkClaude(), checkGh(), checkGit()]);
146
- const isBlocking = (r) => r.key !== "gh" || source === "github";
147
- if (!json) {
198
+ const agent = await loadAgentConfig();
199
+ const usesCodex = agent.provider === "codex" || AGENT_PHASES.some((phase) => agent.phases[phase]?.provider === "codex");
200
+ const checks = [checkClaude(), checkGh(), checkGit()];
201
+ if (usesCodex) checks.push(checkCodex());
202
+ const results = await Promise.all(checks);
203
+ const isBlocking = (r) => {
204
+ if (r.key === "gh") return source === "github";
205
+ if (r.key === "codex") return usesCodex;
206
+ if (r.key === "claude") return agent.provider === "claude" || !usesCodex;
207
+ return true;
208
+ };
209
+ if (!json && (!compact || !results.every((r) => r.passed || !isBlocking(r)))) {
148
210
  for (const r of results) {
149
211
  if (r.passed) {
150
- printSuccess(`${r.name}: ${r.detail}`);
212
+ if (!compact) printSuccess(`${r.name}: ${r.detail}`);
151
213
  } else if (isBlocking(r)) {
152
214
  printError(`${r.name}: ${r.detail}`);
153
215
  if (r.hint) {
154
216
  console.log(` ${r.hint}`);
155
217
  }
156
- } else {
218
+ } else if (!compact) {
157
219
  printWarning(`${r.name}: ${r.detail} (not required for ${source} issues)`);
158
220
  }
159
221
  }
160
222
  }
161
223
  const allPassed = results.filter(isBlocking).every((r) => r.passed);
162
- if (!json) {
224
+ if (!json && !compact) {
163
225
  console.log("");
164
226
  if (allPassed) {
165
227
  printSuccess("All prerequisites met. Ready to run the pipeline.");
166
228
  } else {
167
229
  printError("Some prerequisites are missing. Please fix the issues above.");
168
230
  }
231
+ } else if (!json && compact && !allPassed) {
232
+ printError("Prerequisites not met. Fix the issues above and try again.");
233
+ }
234
+ if (usesCodex) {
235
+ await warnEscalatingCodexConfig();
169
236
  }
170
237
  if (options.checkOnly === true) {
171
238
  return allPassed ? 0 : 1;
172
239
  }
173
240
  let plan;
174
241
  try {
175
- const { planRepositoryScaffold } = await import("./apply-ZIA3C52S.js");
242
+ const { planRepositoryScaffold } = await import("./apply-JNOI2LR4.js");
176
243
  plan = await planRepositoryScaffold({ scope: options.scope ?? null });
177
244
  } catch (err) {
178
245
  if (json) {
@@ -192,7 +259,7 @@ async function runInit(source = "github", options = {}) {
192
259
  }
193
260
  let applied = null;
194
261
  if (options.apply === true) {
195
- const { applyScaffoldPlan } = await import("./apply-ZIA3C52S.js");
262
+ const { applyScaffoldPlan } = await import("./apply-JNOI2LR4.js");
196
263
  applied = await applyScaffoldPlan(plan);
197
264
  }
198
265
  if (json) {
@@ -224,7 +291,11 @@ async function runInit(source = "github", options = {}) {
224
291
  );
225
292
  return allPassed ? 0 : 1;
226
293
  }
227
- renderPlan(plan, options.apply === true);
294
+ if (compact) {
295
+ printInfo(summarizePreflight(results, plan));
296
+ } else {
297
+ renderPlan(plan, options.apply === true);
298
+ }
228
299
  if (applied !== null) {
229
300
  console.log("");
230
301
  for (const path of applied.written) {
@@ -237,10 +308,68 @@ async function runInit(source = "github", options = {}) {
237
308
  printInfo("Nothing was written \u2014 the repository already had everything.");
238
309
  }
239
310
  }
311
+ await maybeOfferAgentChoice(options, agent);
312
+ if (!json) {
313
+ try {
314
+ const { resolveContract } = await import("./contract-JH2WBIO6.js");
315
+ const { getProjectRoot } = await import("./git-W72QQ6GT.js");
316
+ const { loadVerifyConfig } = await import("./config-HMFMCY2M.js");
317
+ const cwd = await getProjectRoot();
318
+ const verify = await loadVerifyConfig({ projectRoot: cwd });
319
+ const contract = await resolveContract({ cwd, declared: verify.contract });
320
+ if (contract.source === "empty") {
321
+ printWarning(
322
+ "No acceptance contract declared or discovered \u2014 runs will finish unverified."
323
+ );
324
+ }
325
+ } catch {
326
+ }
327
+ }
240
328
  return allPassed ? 0 : 1;
241
329
  }
330
+ var ESCALATING_CODEX_KEYS = ["approvals_reviewer", "sandbox_mode", "sandbox_workspace_write"];
331
+ async function warnEscalatingCodexConfig() {
332
+ const configPath = join(homedir(), ".codex", "config.toml");
333
+ try {
334
+ const raw = await readFile(configPath, "utf-8");
335
+ const hits = ESCALATING_CODEX_KEYS.filter((key) => raw.includes(key));
336
+ if (hits.length === 0) return;
337
+ printWarning(
338
+ `$CODEX_HOME/config.toml contains ${hits.join(", ")}, which can escalate --sandbox. Set agent.codex.ignoreUserConfig: true for reproducible runs (recommended in CI). Claude's equivalent is --setting-sources project (agent.claude.ignoreUserConfig).`
339
+ );
340
+ } catch {
341
+ }
342
+ }
343
+ function isInteractiveInit() {
344
+ const ci = process.env.CI;
345
+ const inCi = ci !== void 0 && ci !== "" && ci !== "0" && ci.toLowerCase() !== "false";
346
+ return Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY) && !inCi;
347
+ }
348
+ async function maybeOfferAgentChoice(options, agent) {
349
+ if (options.json === true || options.noAgentPrompt === true) return;
350
+ if (!isInteractiveInit()) return;
351
+ if (hasExplicitAgentSelection(agent, getAgentCliOverrides())) return;
352
+ const { createInterface } = await import("readline");
353
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
354
+ const answer = await new Promise((resolve) => {
355
+ rl.question("Agent [claude/codex] (default claude): ", resolve);
356
+ });
357
+ rl.close();
358
+ const trimmed = answer.trim().toLowerCase();
359
+ const chosen = trimmed === "codex" ? "codex" : "claude";
360
+ if (options.apply === true) {
361
+ const { persistFirstAgentChoice } = await import("./agent-OX3KPHE4.js");
362
+ const path = await persistFirstAgentChoice(chosen);
363
+ printSuccess(`Saved agent '${chosen}' to ${path}`);
364
+ return;
365
+ }
366
+ printInfo(
367
+ `Using ${chosen} for this check. Persist with: issue-flow agent use ${chosen} --global`
368
+ );
369
+ }
242
370
 
243
371
  export {
372
+ summarizePreflight,
244
373
  runInit
245
374
  };
246
- //# sourceMappingURL=chunk-NS6R37II.js.map
375
+ //# sourceMappingURL=chunk-F6TOYSYY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/init.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { execa } from 'execa';\nimport { hasExplicitAgentSelection } from '../agents/resolve.js';\nimport { AGENT_PHASES } from '../agents/types.js';\nimport { getAgentCliOverrides, loadAgentConfig } from '../config.js';\nimport type { IssueSource } from '../issues/types.js';\nimport type { ScaffoldActionKind, ScaffoldPlan } from '../scaffold/plan.js';\nimport { printError, printInfo, printSuccess, printWarning } from '../ui/logger.js';\n\n/** Stable identifier of a check, used to decide whether it blocks. */\ntype CheckKey = 'claude' | 'codex' | 'gh' | 'git';\n\ninterface CheckResult {\n key: CheckKey;\n name: string;\n passed: boolean;\n detail: string;\n hint?: string;\n}\n\nasync function checkClaude(): Promise<CheckResult> {\n try {\n const proc = await execa('claude', ['--version'], { reject: false, timeout: 10_000 });\n if (proc.exitCode === 0) {\n const version = proc.stdout?.toString().trim() ?? 'unknown';\n return { key: 'claude', name: 'claude CLI', passed: true, detail: version };\n }\n return {\n key: 'claude',\n name: 'claude CLI',\n passed: false,\n detail: 'claude command failed',\n hint: 'Install Claude Code: https://docs.anthropic.com/en/docs/claude-code',\n };\n } catch {\n return {\n key: 'claude',\n name: 'claude CLI',\n passed: false,\n detail: 'claude not found',\n hint: 'Install Claude Code: https://docs.anthropic.com/en/docs/claude-code',\n };\n }\n}\n\nasync function checkGh(): Promise<CheckResult> {\n try {\n const proc = await execa('gh', ['--version'], { reject: false, timeout: 10_000 });\n if (proc.exitCode !== 0) {\n return {\n key: 'gh',\n name: 'gh CLI',\n passed: false,\n detail: 'gh command failed',\n hint: 'Install GitHub CLI: https://cli.github.com/',\n };\n }\n const version = proc.stdout?.toString().split('\\n')[0]?.trim() ?? 'unknown';\n\n // Check auth status\n const auth = await execa('gh', ['auth', 'status'], { reject: false, timeout: 10_000 });\n if (auth.exitCode !== 0) {\n return {\n key: 'gh',\n name: 'gh CLI',\n passed: false,\n detail: `${version} (not authenticated)`,\n hint: 'Run: gh auth login',\n };\n }\n return { key: 'gh', name: 'gh CLI', passed: true, detail: `${version} (authenticated)` };\n } catch {\n return {\n key: 'gh',\n name: 'gh CLI',\n passed: false,\n detail: 'gh not found',\n hint: 'Install GitHub CLI: https://cli.github.com/',\n };\n }\n}\n\nasync function checkCodex(): Promise<CheckResult> {\n try {\n const proc = await execa('codex', ['--version'], { reject: false, timeout: 10_000 });\n if (proc.exitCode !== 0) {\n return {\n key: 'codex',\n name: 'codex CLI',\n passed: false,\n detail: 'codex command failed',\n hint: 'Install Codex CLI: https://developers.openai.com/codex/noninteractive',\n };\n }\n const version = proc.stdout?.toString().trim() ?? 'unknown';\n const auth = await execa('codex', ['login', 'status'], { reject: false, timeout: 10_000 });\n if (auth.exitCode !== 0) {\n return {\n key: 'codex',\n name: 'codex CLI',\n passed: false,\n detail: `${version} (not authenticated)`,\n hint: 'Run: codex login --with-api-key (or set CODEX_API_KEY)',\n };\n }\n return { key: 'codex', name: 'codex CLI', passed: true, detail: `${version} (authenticated)` };\n } catch {\n return {\n key: 'codex',\n name: 'codex CLI',\n passed: false,\n detail: 'codex not found',\n hint: 'Install Codex CLI: https://developers.openai.com/codex/noninteractive',\n };\n }\n}\n\nasync function checkGit(): Promise<CheckResult> {\n try {\n const proc = await execa('git', ['--version'], { reject: false, timeout: 10_000 });\n if (proc.exitCode !== 0) {\n return {\n key: 'git',\n name: 'git',\n passed: false,\n detail: 'git command failed',\n hint: 'Install git: https://git-scm.com/',\n };\n }\n const version = proc.stdout?.toString().trim() ?? 'unknown';\n\n // Check if current directory is a git repo\n const repo = await execa('git', ['rev-parse', '--is-inside-work-tree'], {\n reject: false,\n timeout: 5_000,\n });\n if (repo.exitCode !== 0) {\n return {\n key: 'git',\n name: 'git',\n passed: false,\n detail: `${version} (not a git repository)`,\n hint: 'Run this command inside a git repository',\n };\n }\n return { key: 'git', name: 'git', passed: true, detail: `${version} (inside repo)` };\n } catch {\n return {\n key: 'git',\n name: 'git',\n passed: false,\n detail: 'git not found',\n hint: 'Install git: https://git-scm.com/',\n };\n }\n}\n\nexport interface InitOptions {\n /** Write the missing files instead of only reporting them. */\n apply?: boolean;\n /** Emit the plan as JSON — the bridge the initialization skill reads. */\n json?: boolean;\n /** Subdirectory the conventions apply to, in a monorepo. */\n scope?: string;\n /** Skip the convention report entirely and only check prerequisites. */\n checkOnly?: boolean;\n /** Skip the first-run agent choice. */\n noAgentPrompt?: boolean;\n /**\n * One-line preflight for `issue-flow run` in clean mode. `issue-flow init`\n * itself never passes this — its product is the full report.\n */\n compact?: boolean;\n}\n\nconst ACTION_ICON: Record<ScaffoldActionKind, string> = {\n create: '+',\n keep: '=',\n review: '!',\n};\n\n/**\n * One-line preflight for the clean terminal. The full report stays on\n * `issue-flow init` and on `--verbose`.\n */\nexport function summarizePreflight(\n results: ReadonlyArray<{ passed: boolean }>,\n plan: { actions: ReadonlyArray<{ kind: string }> },\n): string {\n const kept = plan.actions.filter((action) => action.kind === 'keep').length;\n const creates = plan.actions.filter((action) => action.kind === 'create').length;\n const env = results.every((result) => result.passed) ? 'environment ok' : 'environment failed';\n const createBit = creates === 0 ? 'nothing to create' : `${creates} to create`;\n return `Preflight: ${env} · ${kept} conventions kept · ${createBit}`;\n}\n\n/**\n * Render the plan for a human.\n *\n * `keep` lines are printed, not hidden: the most valuable thing this report\n * says is usually *what it is not going to touch*, and a list of only the\n * missing files would read as if the repository had nothing.\n */\nfunction renderPlan(plan: ScaffoldPlan, apply: boolean): void {\n const creates = plan.actions.filter((a) => a.kind === 'create');\n const reviews = plan.actions.filter((a) => a.kind === 'review');\n\n console.log('');\n printInfo(`Repository conventions (${plan.root})\\n`);\n\n for (const item of plan.actions) {\n console.log(` ${ACTION_ICON[item.kind]} ${item.path}`);\n console.log(` ${item.reason}`);\n }\n\n if (plan.notes.length > 0) {\n console.log('');\n for (const note of plan.notes) {\n printWarning(note);\n }\n }\n\n console.log('');\n if (creates.length === 0 && reviews.length === 0) {\n printSuccess('This repository already declares everything Issue Flow would add.');\n return;\n }\n if (creates.length === 0) {\n printSuccess('Nothing to create.');\n return;\n }\n if (!apply) {\n printInfo(`${creates.length} file(s) would be created. Re-run with --apply to write them.`);\n }\n}\n\n/**\n * Verify the prerequisites of the pipeline and report the repository's\n * conventions.\n *\n * `source` is the Issue origin the run is headed for. `gh` only blocks when\n * that origin is GitHub: no other origin shells out to it, so a missing or\n * unauthenticated gh is reported as a warning instead of failing the\n * environment. `claude` and `git` stay blocking for every origin, and the\n * default ('github') keeps the previous behaviour byte for byte.\n *\n * The convention report is additive: the prerequisite checks run first and still\n * decide the exit code, so an existing script calling `issue-flow init` sees the\n * same pass/fail it always did. Nothing is written without `--apply`.\n */\nexport async function runInit(\n source: IssueSource = 'github',\n options: InitOptions = {},\n): Promise<number> {\n const json = options.json === true;\n const compact = options.compact === true;\n\n if (!json && !compact) {\n printInfo('Checking prerequisites...\\n');\n }\n\n const agent = await loadAgentConfig();\n const usesCodex =\n agent.provider === 'codex' ||\n AGENT_PHASES.some((phase) => agent.phases[phase]?.provider === 'codex');\n\n const checks = [checkClaude(), checkGh(), checkGit()];\n if (usesCodex) checks.push(checkCodex());\n const results = await Promise.all(checks);\n const isBlocking = (r: CheckResult): boolean => {\n if (r.key === 'gh') return source === 'github';\n if (r.key === 'codex') return usesCodex;\n if (r.key === 'claude') return agent.provider === 'claude' || !usesCodex;\n return true;\n };\n\n if (!json && (!compact || !results.every((r) => r.passed || !isBlocking(r)))) {\n for (const r of results) {\n if (r.passed) {\n if (!compact) printSuccess(`${r.name}: ${r.detail}`);\n } else if (isBlocking(r)) {\n printError(`${r.name}: ${r.detail}`);\n if (r.hint) {\n console.log(` ${r.hint}`);\n }\n } else if (!compact) {\n printWarning(`${r.name}: ${r.detail} (not required for ${source} issues)`);\n }\n }\n }\n\n const allPassed = results.filter(isBlocking).every((r) => r.passed);\n\n if (!json && !compact) {\n console.log('');\n if (allPassed) {\n printSuccess('All prerequisites met. Ready to run the pipeline.');\n } else {\n printError('Some prerequisites are missing. Please fix the issues above.');\n }\n } else if (!json && compact && !allPassed) {\n printError('Prerequisites not met. Fix the issues above and try again.');\n }\n\n if (usesCodex) {\n await warnEscalatingCodexConfig();\n }\n\n if (options.checkOnly === true) {\n return allPassed ? 0 : 1;\n }\n\n // The conventions half. It never changes the exit code: a repository missing\n // a template is not a broken environment, and failing here would break every\n // script that treats `init` as a prerequisite gate.\n let plan: ScaffoldPlan;\n try {\n const { planRepositoryScaffold } = await import('../scaffold/apply.js');\n plan = await planRepositoryScaffold({ scope: options.scope ?? null });\n } catch (err) {\n if (json) {\n console.log(\n JSON.stringify(\n { schemaVersion: 1, error: err instanceof Error ? err.message : String(err) },\n null,\n 2,\n ),\n );\n return allPassed ? 0 : 1;\n }\n printWarning(\n `Could not inspect the repository conventions: ${err instanceof Error ? err.message : String(err)}`,\n );\n return allPassed ? 0 : 1;\n }\n\n let applied: { written: string[]; skipped: string[] } | null = null;\n if (options.apply === true) {\n const { applyScaffoldPlan } = await import('../scaffold/apply.js');\n applied = await applyScaffoldPlan(plan);\n }\n\n if (json) {\n console.log(\n JSON.stringify(\n {\n schemaVersion: 1,\n prerequisites: results.map((r) => ({\n key: r.key,\n passed: r.passed,\n detail: r.detail,\n blocking: isBlocking(r),\n })),\n root: plan.root,\n // Content is omitted: a skill decides from the actions, and the bodies\n // would make the payload unreadable for no gain.\n actions: plan.actions.map(({ path, kind, tier, reason }) => ({\n path,\n kind,\n tier,\n reason,\n })),\n notes: plan.notes,\n applied,\n },\n null,\n 2,\n ),\n );\n return allPassed ? 0 : 1;\n }\n\n if (compact) {\n printInfo(summarizePreflight(results, plan));\n } else {\n renderPlan(plan, options.apply === true);\n }\n\n if (applied !== null) {\n console.log('');\n for (const path of applied.written) {\n printSuccess(`Created ${path}`);\n }\n for (const path of applied.skipped) {\n printWarning(`Skipped ${path}: it already exists.`);\n }\n if (applied.written.length === 0) {\n printInfo('Nothing was written — the repository already had everything.');\n }\n }\n\n await maybeOfferAgentChoice(options, agent);\n\n if (!json) {\n try {\n const { resolveContract } = await import('../verify/contract.js');\n const { getProjectRoot } = await import('../utils/git.js');\n const { loadVerifyConfig } = await import('../config.js');\n const cwd = await getProjectRoot();\n const verify = await loadVerifyConfig({ projectRoot: cwd });\n const contract = await resolveContract({ cwd, declared: verify.contract });\n if (contract.source === 'empty') {\n printWarning(\n 'No acceptance contract declared or discovered — runs will finish unverified.',\n );\n }\n } catch {\n // Observational: init still reports prerequisites if discovery fails.\n }\n }\n\n return allPassed ? 0 : 1;\n}\n\nconst ESCALATING_CODEX_KEYS = ['approvals_reviewer', 'sandbox_mode', 'sandbox_workspace_write'];\n\nasync function warnEscalatingCodexConfig(): Promise<void> {\n const configPath = join(homedir(), '.codex', 'config.toml');\n try {\n const raw = await readFile(configPath, 'utf-8');\n const hits = ESCALATING_CODEX_KEYS.filter((key) => raw.includes(key));\n if (hits.length === 0) return;\n printWarning(\n `$CODEX_HOME/config.toml contains ${hits.join(', ')}, which can escalate --sandbox. Set agent.codex.ignoreUserConfig: true for reproducible runs (recommended in CI). Claude's equivalent is --setting-sources project (agent.claude.ignoreUserConfig).`,\n );\n } catch {\n // Absence is the common case.\n }\n}\n\nfunction isInteractiveInit(): boolean {\n const ci = process.env.CI;\n const inCi = ci !== undefined && ci !== '' && ci !== '0' && ci.toLowerCase() !== 'false';\n return Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY) && !inCi;\n}\n\nasync function maybeOfferAgentChoice(\n options: InitOptions,\n agent: Awaited<ReturnType<typeof loadAgentConfig>>,\n): Promise<void> {\n if (options.json === true || options.noAgentPrompt === true) return;\n if (!isInteractiveInit()) return;\n if (hasExplicitAgentSelection(agent, getAgentCliOverrides())) return;\n\n const { createInterface } = await import('node:readline');\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n rl.question('Agent [claude/codex] (default claude): ', resolve);\n });\n rl.close();\n const trimmed = answer.trim().toLowerCase();\n const chosen = trimmed === 'codex' ? 'codex' : 'claude';\n\n if (options.apply === true) {\n const { persistFirstAgentChoice } = await import('./agent.js');\n const path = await persistFirstAgentChoice(chosen);\n printSuccess(`Saved agent '${chosen}' to ${path}`);\n return;\n }\n printInfo(\n `Using ${chosen} for this check. Persist with: issue-flow agent use ${chosen} --global`,\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ trimErrorMessage
4
+ } from "./chunk-J3SOTUVI.js";
5
+
6
+ // src/telemetry/redact.ts
7
+ var SECRET = /(?:sk-ant-|sk-|ghp_|gho_|github_pat_|xox[baprs]-)[A-Za-z0-9_-]{8,}/g;
8
+ var BEARER = /Bearer\s+[A-Za-z0-9\-._~+/]+=*/gi;
9
+ var SENSITIVE_FIELD = /(["']?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|password|secret|authorization)["']?\s*[:=]\s*)["']?([^"',\s}]+)/gi;
10
+ var ENV_ASSIGN = /\b(?=[A-Z0-9_]*(?:TOKEN|SECRET|KEY|PASSWORD|PASS|AUTH))[A-Z][A-Z0-9_]*=([^\s]+)/g;
11
+ function redactSecrets(text) {
12
+ return text.replace(SECRET, "[redacted]").replace(BEARER, "Bearer [redacted]").replace(SENSITIVE_FIELD, "$1[redacted]").replace(
13
+ ENV_ASSIGN,
14
+ (match, _value) => `${match.slice(0, match.indexOf("="))}=[redacted]`
15
+ );
16
+ }
17
+ function redactFailureMessage(message) {
18
+ return trimErrorMessage(redactSecrets(message));
19
+ }
20
+
21
+ export {
22
+ redactSecrets,
23
+ redactFailureMessage
24
+ };
25
+ //# sourceMappingURL=chunk-G5EK2XRN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/telemetry/redact.ts"],"sourcesContent":["import { trimErrorMessage } from '../core/state-manager.js';\n\nconst SECRET = /(?:sk-ant-|sk-|ghp_|gho_|github_pat_|xox[baprs]-)[A-Za-z0-9_-]{8,}/g;\nconst BEARER = /Bearer\\s+[A-Za-z0-9\\-._~+/]+=*/gi;\nconst SENSITIVE_FIELD =\n /([\"']?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|password|secret|authorization)[\"']?\\s*[:=]\\s*)[\"']?([^\"',\\s}]+)/gi;\nconst ENV_ASSIGN =\n /\\b(?=[A-Z0-9_]*(?:TOKEN|SECRET|KEY|PASSWORD|PASS|AUTH))[A-Z][A-Z0-9_]*=([^\\s]+)/g;\n\n/** Strip credentials from a message that will be persisted. */\nexport function redactSecrets(text: string): string {\n return text\n .replace(SECRET, '[redacted]')\n .replace(BEARER, 'Bearer [redacted]')\n .replace(SENSITIVE_FIELD, '$1[redacted]')\n .replace(\n ENV_ASSIGN,\n (match, _value: string) => `${match.slice(0, match.indexOf('='))}=[redacted]`,\n );\n}\n\n/** Sanitize a failure message: secrets out, then the existing 8-line cap. */\nexport function redactFailureMessage(message: string): string {\n return trimErrorMessage(redactSecrets(message));\n}\n"],"mappings":";;;;;;AAEA,IAAM,SAAS;AACf,IAAM,SAAS;AACf,IAAM,kBACJ;AACF,IAAM,aACJ;AAGK,SAAS,cAAc,MAAsB;AAClD,SAAO,KACJ,QAAQ,QAAQ,YAAY,EAC5B,QAAQ,QAAQ,mBAAmB,EACnC,QAAQ,iBAAiB,cAAc,EACvC;AAAA,IACC;AAAA,IACA,CAAC,OAAO,WAAmB,GAAG,MAAM,MAAM,GAAG,MAAM,QAAQ,GAAG,CAAC,CAAC;AAAA,EAClE;AACJ;AAGO,SAAS,qBAAqB,SAAyB;AAC5D,SAAO,iBAAiB,cAAc,OAAO,CAAC;AAChD;","names":[]}