issue-flow 0.13.0 → 0.15.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.
- package/dist/agent-AT64RXTA.js +30 -0
- package/dist/{analyze-WS47UYGN.js → analyze-O2PYDIFK.js} +21 -18
- package/dist/{analyze-WS47UYGN.js.map → analyze-O2PYDIFK.js.map} +1 -1
- package/dist/{apply-OS62UWRN.js → apply-SSU6QCD4.js} +14 -11
- package/dist/{apply-OS62UWRN.js.map → apply-SSU6QCD4.js.map} +1 -1
- package/dist/{bench-SA3BOME5.js → bench-ODFPAGW6.js} +30 -26
- package/dist/{bench-SA3BOME5.js.map → bench-ODFPAGW6.js.map} +1 -1
- package/dist/{chunk-HJGGNLWI.js → chunk-2ZAM45PZ.js} +9 -9
- package/dist/{chunk-QCXPNSEL.js → chunk-3BWZO4YI.js} +2 -2
- package/dist/{chunk-J62QSVP6.js → chunk-4RXYFWP7.js} +8 -7
- package/dist/{chunk-J62QSVP6.js.map → chunk-4RXYFWP7.js.map} +1 -1
- package/dist/{chunk-ARFVHC2F.js → chunk-5ZKBIXET.js} +115 -23
- package/dist/chunk-5ZKBIXET.js.map +1 -0
- package/dist/{chunk-HEF2RMKN.js → chunk-6E2PEBFT.js} +18 -16
- package/dist/{chunk-HEF2RMKN.js.map → chunk-6E2PEBFT.js.map} +1 -1
- package/dist/{agent-BXRIEKVM.js → chunk-6FXOU2KR.js} +22 -22
- package/dist/chunk-6FXOU2KR.js.map +1 -0
- package/dist/{chunk-IYV6KNVF.js → chunk-6QYMSNVA.js} +66 -240
- package/dist/chunk-6QYMSNVA.js.map +1 -0
- package/dist/{chunk-UOCPC2Y2.js → chunk-6SRE4KD7.js} +4 -4
- package/dist/{chunk-MIVHK5YI.js → chunk-A35HE4V7.js} +3 -3
- package/dist/{chunk-TM67EHSV.js → chunk-ARWNYXFL.js} +19 -19
- package/dist/chunk-ARWNYXFL.js.map +1 -0
- package/dist/chunk-AYYMW33T.js +163 -0
- package/dist/chunk-AYYMW33T.js.map +1 -0
- package/dist/chunk-BMHGRYL6.js +890 -0
- package/dist/chunk-BMHGRYL6.js.map +1 -0
- package/dist/{chunk-PV4OX5TC.js → chunk-F4OK7KEP.js} +11 -11
- package/dist/{chunk-QXDNBYQF.js → chunk-FK4IDY6P.js} +21 -10
- package/dist/chunk-FK4IDY6P.js.map +1 -0
- package/dist/{chunk-KQHB7ZT3.js → chunk-GSZCQUCY.js} +82 -16
- package/dist/chunk-GSZCQUCY.js.map +1 -0
- package/dist/{chunk-TX5WIVYP.js → chunk-HAKDLR6N.js} +6 -1
- package/dist/chunk-HAKDLR6N.js.map +1 -0
- package/dist/{chunk-OPNGPUKJ.js → chunk-HGSYD57B.js} +143 -48
- package/dist/chunk-HGSYD57B.js.map +1 -0
- package/dist/{chunk-PIVGJM6K.js → chunk-KAHQ6F5C.js} +11 -11
- package/dist/{chunk-BHJCGWQX.js → chunk-MEFY4B7T.js} +9 -9
- package/dist/{chunk-BQDQTIM7.js → chunk-MGCOQU6N.js} +4 -4
- package/dist/{chunk-5TB6KLC2.js → chunk-MROS3SKL.js} +8 -8
- package/dist/chunk-NVZMBXTE.js +243 -0
- package/dist/chunk-NVZMBXTE.js.map +1 -0
- package/dist/{chunk-664Y3NDX.js → chunk-PCN7ZQND.js} +8 -8
- package/dist/{chunk-IV5SS4JN.js → chunk-QRCGW2ZO.js} +9 -7
- package/dist/{chunk-IV5SS4JN.js.map → chunk-QRCGW2ZO.js.map} +1 -1
- package/dist/{chunk-7KD66LIM.js → chunk-RPXDBX6R.js} +3 -3
- package/dist/{chunk-SNTTOQAD.js → chunk-RWEXK55D.js} +2 -2
- package/dist/{chunk-6FDFRNXZ.js → chunk-TBDP6QPJ.js} +25 -20
- package/dist/chunk-TBDP6QPJ.js.map +1 -0
- package/dist/chunk-UNQYMR3H.js +25 -0
- package/dist/chunk-UNQYMR3H.js.map +1 -0
- package/dist/{chunk-HQAHNIAR.js → chunk-VR34TXHF.js} +14 -14
- package/dist/{chunk-CNBYCMSU.js → chunk-WM3Y7Q4A.js} +27 -18
- package/dist/{chunk-CNBYCMSU.js.map → chunk-WM3Y7Q4A.js.map} +1 -1
- package/dist/{chunk-NEZZ6KDR.js → chunk-XDKGA6UX.js} +52 -3
- package/dist/chunk-XDKGA6UX.js.map +1 -0
- package/dist/{chunk-FZDR7CGH.js → chunk-XG2NYDRA.js} +3 -3
- package/dist/{chunk-3XLCNVMD.js → chunk-XLVGPXNL.js} +2 -2
- package/dist/{chunk-DIG5XKQQ.js → chunk-XQHFC62U.js} +2 -2
- package/dist/{chunk-UJ7XWK7J.js → chunk-XRLRKTQA.js} +16 -14
- package/dist/{chunk-UJ7XWK7J.js.map → chunk-XRLRKTQA.js.map} +1 -1
- package/dist/{chunk-LZ6GFQAG.js → chunk-ZFIXEYUJ.js} +44 -31
- package/dist/chunk-ZFIXEYUJ.js.map +1 -0
- package/dist/{chunk-37N2RJW2.js → chunk-ZPIVCM7Q.js} +3 -3
- package/dist/{chunk-TVN2JVOF.js → chunk-ZXPASFHG.js} +3 -3
- package/dist/cli.js +58 -64
- package/dist/cli.js.map +1 -1
- package/dist/{config-MEM2IWWN.js → config-UMP6DBJB.js} +12 -9
- package/dist/{conventions-WV4NDXGH.js → conventions-DKH7AE4T.js} +14 -11
- package/dist/{conventions-WV4NDXGH.js.map → conventions-DKH7AE4T.js.map} +1 -1
- package/dist/diagnostics-GOGCLTRS.js +23 -0
- package/dist/execute-E3BRMDAQ.js +35 -0
- package/dist/{generate-MVQI7A45.js → generate-AGBT7EHX.js} +23 -20
- package/dist/{generate-MVQI7A45.js.map → generate-AGBT7EHX.js.map} +1 -1
- package/dist/{git-YRVRUN3C.js → git-AC542GU2.js} +4 -2
- package/dist/init-LLBVJNPE.js +24 -0
- package/dist/{operations-LU6JA3BX.js → operations-JQYK2EMT.js} +17 -14
- package/dist/{operations-LU6JA3BX.js.map → operations-JQYK2EMT.js.map} +1 -1
- package/dist/{permissions-7NMDFU27.js → permissions-6HL52K54.js} +4 -4
- package/dist/plan-HSLWDJEZ.js +34 -0
- package/dist/{policy-JSYEK5B2.js → policy-IMRXGG7X.js} +13 -10
- package/dist/{policy-JSYEK5B2.js.map → policy-IMRXGG7X.js.map} +1 -1
- package/dist/pr-6TCZXG6K.js +39 -0
- package/dist/pr-review-6MWJO2NP.js +32 -0
- package/dist/prd-D6YDYAFX.js +33 -0
- package/dist/{ps-TNE44R5V.js → ps-KUUZ6TUL.js} +11 -8
- package/dist/{ps-TNE44R5V.js.map → ps-KUUZ6TUL.js.map} +1 -1
- package/dist/{recorder-XGF55WXI.js → recorder-BJ2KIAWT.js} +5 -4
- package/dist/registry-SB7XTMGE.js +15 -0
- package/dist/{resume-QMEPMSZW.js → resume-QNLQSCR5.js} +44 -40
- package/dist/{resume-QMEPMSZW.js.map → resume-QNLQSCR5.js.map} +1 -1
- package/dist/review-3KJ4BH2V.js +35 -0
- package/dist/{routing-2ZUMZPJB.js → routing-TN7GLMGU.js} +13 -10
- package/dist/{routing-2ZUMZPJB.js.map → routing-TN7GLMGU.js.map} +1 -1
- package/dist/run-5EHIFF2V.js +54 -0
- package/dist/run-5EHIFF2V.js.map +1 -0
- package/dist/session-publisher-T7EI3CIP.js +11 -0
- package/dist/session-publisher-T7EI3CIP.js.map +1 -0
- package/dist/{state-manager-X3PT3FGT.js → state-manager-ZEPWTCA6.js} +3 -3
- package/dist/state-manager-ZEPWTCA6.js.map +1 -0
- package/dist/{usage-VCFLDA5Y.js → usage-QL563I7F.js} +13 -10
- package/dist/{usage-VCFLDA5Y.js.map → usage-QL563I7F.js.map} +1 -1
- package/dist/{web-XVHLX62B.js → web-PPSMNTQ6.js} +22 -57
- package/dist/{web-XVHLX62B.js.map → web-PPSMNTQ6.js.map} +1 -1
- package/package.json +1 -1
- package/web/AGENTS.md +154 -11
- package/web/public/app.css +343 -110
- package/web/public/app.js +436 -27
- package/web/public/index.html +44 -1
- package/dist/agent-BXRIEKVM.js.map +0 -1
- package/dist/chunk-6FDFRNXZ.js.map +0 -1
- package/dist/chunk-ARFVHC2F.js.map +0 -1
- package/dist/chunk-IHIEXUTC.js +0 -483
- package/dist/chunk-IHIEXUTC.js.map +0 -1
- package/dist/chunk-IYV6KNVF.js.map +0 -1
- package/dist/chunk-KQHB7ZT3.js.map +0 -1
- package/dist/chunk-LZ6GFQAG.js.map +0 -1
- package/dist/chunk-NEZZ6KDR.js.map +0 -1
- package/dist/chunk-OPNGPUKJ.js.map +0 -1
- package/dist/chunk-QXDNBYQF.js.map +0 -1
- package/dist/chunk-TM67EHSV.js.map +0 -1
- package/dist/chunk-TX5WIVYP.js.map +0 -1
- package/dist/execute-NITIHHCK.js +0 -31
- package/dist/init-OKWEC3EV.js +0 -21
- package/dist/plan-LEJJF3DE.js +0 -31
- package/dist/pr-HPVUZ7S3.js +0 -36
- package/dist/pr-review-R2QZBT3F.js +0 -29
- package/dist/prd-5O6GYCC6.js +0 -30
- package/dist/registry-LGPE53QD.js +0 -15
- package/dist/review-YKWD6SNN.js +0 -32
- package/dist/run-YU4TR62R.js +0 -50
- /package/dist/{config-MEM2IWWN.js.map → agent-AT64RXTA.js.map} +0 -0
- /package/dist/{chunk-HJGGNLWI.js.map → chunk-2ZAM45PZ.js.map} +0 -0
- /package/dist/{chunk-QCXPNSEL.js.map → chunk-3BWZO4YI.js.map} +0 -0
- /package/dist/{chunk-UOCPC2Y2.js.map → chunk-6SRE4KD7.js.map} +0 -0
- /package/dist/{chunk-MIVHK5YI.js.map → chunk-A35HE4V7.js.map} +0 -0
- /package/dist/{chunk-PV4OX5TC.js.map → chunk-F4OK7KEP.js.map} +0 -0
- /package/dist/{chunk-PIVGJM6K.js.map → chunk-KAHQ6F5C.js.map} +0 -0
- /package/dist/{chunk-BHJCGWQX.js.map → chunk-MEFY4B7T.js.map} +0 -0
- /package/dist/{chunk-BQDQTIM7.js.map → chunk-MGCOQU6N.js.map} +0 -0
- /package/dist/{chunk-5TB6KLC2.js.map → chunk-MROS3SKL.js.map} +0 -0
- /package/dist/{chunk-664Y3NDX.js.map → chunk-PCN7ZQND.js.map} +0 -0
- /package/dist/{chunk-7KD66LIM.js.map → chunk-RPXDBX6R.js.map} +0 -0
- /package/dist/{chunk-SNTTOQAD.js.map → chunk-RWEXK55D.js.map} +0 -0
- /package/dist/{chunk-HQAHNIAR.js.map → chunk-VR34TXHF.js.map} +0 -0
- /package/dist/{chunk-FZDR7CGH.js.map → chunk-XG2NYDRA.js.map} +0 -0
- /package/dist/{chunk-3XLCNVMD.js.map → chunk-XLVGPXNL.js.map} +0 -0
- /package/dist/{chunk-DIG5XKQQ.js.map → chunk-XQHFC62U.js.map} +0 -0
- /package/dist/{chunk-37N2RJW2.js.map → chunk-ZPIVCM7Q.js.map} +0 -0
- /package/dist/{chunk-TVN2JVOF.js.map → chunk-ZXPASFHG.js.map} +0 -0
- /package/dist/{execute-NITIHHCK.js.map → config-UMP6DBJB.js.map} +0 -0
- /package/dist/{git-YRVRUN3C.js.map → diagnostics-GOGCLTRS.js.map} +0 -0
- /package/dist/{init-OKWEC3EV.js.map → execute-E3BRMDAQ.js.map} +0 -0
- /package/dist/{permissions-7NMDFU27.js.map → git-AC542GU2.js.map} +0 -0
- /package/dist/{plan-LEJJF3DE.js.map → init-LLBVJNPE.js.map} +0 -0
- /package/dist/{pr-HPVUZ7S3.js.map → permissions-6HL52K54.js.map} +0 -0
- /package/dist/{pr-review-R2QZBT3F.js.map → plan-HSLWDJEZ.js.map} +0 -0
- /package/dist/{prd-5O6GYCC6.js.map → pr-6TCZXG6K.js.map} +0 -0
- /package/dist/{recorder-XGF55WXI.js.map → pr-review-6MWJO2NP.js.map} +0 -0
- /package/dist/{registry-LGPE53QD.js.map → prd-D6YDYAFX.js.map} +0 -0
- /package/dist/{review-YKWD6SNN.js.map → recorder-BJ2KIAWT.js.map} +0 -0
- /package/dist/{run-YU4TR62R.js.map → registry-SB7XTMGE.js.map} +0 -0
- /package/dist/{state-manager-X3PT3FGT.js.map → review-3KJ4BH2V.js.map} +0 -0
package/web/public/index.html
CHANGED
|
@@ -3,10 +3,29 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
-
<meta name="color-scheme" content="light dark" />
|
|
7
6
|
<meta name="robots" content="noindex, nofollow" />
|
|
8
7
|
<link rel="icon" href="data:," />
|
|
9
8
|
<title>issue-flow</title>
|
|
9
|
+
<script>
|
|
10
|
+
// Aplica o tema antes do primeiro paint: sem isto o painel pintaria a
|
|
11
|
+
// paleta do SO e só trocaria quando o app.js rodasse — o flash da paleta
|
|
12
|
+
// oposta a cada reload. Roda antes do <link> do app.css de propósito.
|
|
13
|
+
// A leitura de 'issue-flow:theme' é deliberadamente duplicada aqui e no
|
|
14
|
+
// app.js (readStoredTheme): este script não pode depender do app.js, que
|
|
15
|
+
// carrega no fim do <body>. Mudou o formato do valor, mude nos dois.
|
|
16
|
+
// 'system', ausente ou desconhecido não define data-theme — é a ausência
|
|
17
|
+
// do atributo que deixa o @media (prefers-color-scheme) decidir.
|
|
18
|
+
(function () {
|
|
19
|
+
try {
|
|
20
|
+
var theme = window.localStorage.getItem('issue-flow:theme');
|
|
21
|
+
if (theme === 'light' || theme === 'dark') {
|
|
22
|
+
document.documentElement.setAttribute('data-theme', theme);
|
|
23
|
+
}
|
|
24
|
+
} catch (err) {
|
|
25
|
+
// localStorage bloqueado (ex.: janela privada) — segue no modo sistema.
|
|
26
|
+
}
|
|
27
|
+
})();
|
|
28
|
+
</script>
|
|
10
29
|
<link rel="stylesheet" href="app.css" />
|
|
11
30
|
</head>
|
|
12
31
|
<body>
|
|
@@ -26,6 +45,14 @@
|
|
|
26
45
|
Atualizar
|
|
27
46
|
<select id="refresh-select-dashboard" aria-label="Intervalo de atualização"></select>
|
|
28
47
|
</label>
|
|
48
|
+
<label class="theme-control">
|
|
49
|
+
Tema
|
|
50
|
+
<select id="theme-select-dashboard" aria-label="Tema do painel">
|
|
51
|
+
<option value="system">Sistema</option>
|
|
52
|
+
<option value="light">Claro</option>
|
|
53
|
+
<option value="dark">Escuro</option>
|
|
54
|
+
</select>
|
|
55
|
+
</label>
|
|
29
56
|
</div>
|
|
30
57
|
</header>
|
|
31
58
|
<div id="dashboard" class="dashboard-grid"></div>
|
|
@@ -56,6 +83,14 @@
|
|
|
56
83
|
Atualizar
|
|
57
84
|
<select id="refresh-select" aria-label="Intervalo de atualização"></select>
|
|
58
85
|
</label>
|
|
86
|
+
<label class="theme-control">
|
|
87
|
+
Tema
|
|
88
|
+
<select id="theme-select" aria-label="Tema do painel">
|
|
89
|
+
<option value="system">Sistema</option>
|
|
90
|
+
<option value="light">Claro</option>
|
|
91
|
+
<option value="dark">Escuro</option>
|
|
92
|
+
</select>
|
|
93
|
+
</label>
|
|
59
94
|
</div>
|
|
60
95
|
</header>
|
|
61
96
|
|
|
@@ -104,6 +139,14 @@
|
|
|
104
139
|
<div id="resilience"></div>
|
|
105
140
|
</section>
|
|
106
141
|
|
|
142
|
+
<section class="card">
|
|
143
|
+
<div class="section-head">
|
|
144
|
+
<h2>Harnesses e configuração efetiva</h2>
|
|
145
|
+
<span class="muted">preferências futuras e overrides desta execução</span>
|
|
146
|
+
</div>
|
|
147
|
+
<div id="configuration"></div>
|
|
148
|
+
</section>
|
|
149
|
+
|
|
107
150
|
<div class="columns">
|
|
108
151
|
<section class="card">
|
|
109
152
|
<h2>Fases</h2>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/agent.ts"],"sourcesContent":["import { mkdir, readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { probeAgent } from '../agents/availability.js';\nimport { describeRunAgents } from '../agents/resolve.js';\nimport {\n AGENT_PHASES,\n AGENT_SCHEMA_VERSION,\n type AgentPhase,\n type AgentProviderId,\n isAgentPhase,\n isAgentProviderId,\n} from '../agents/types.js';\nimport { GLOBAL_CONFIG_FILENAME, loadAgentConfig, PROJECT_CONFIG_FILENAME } from '../config.js';\nimport { getGlobalRoot } from '../storage/paths.js';\nimport { printError, printSuccess } from '../ui/logger.js';\nimport { writeFileAtomic } from '../utils/fs.js';\nimport { getProjectRoot } from '../utils/git.js';\n\nexport const AGENT_COMMAND_SCHEMA_VERSION = AGENT_SCHEMA_VERSION;\n\nexport interface AgentCommandOptions {\n json?: boolean;\n}\n\nexport interface AgentUseOptions {\n model?: string;\n global?: boolean;\n project?: boolean;\n phase?: string;\n}\n\nfunction originLabel(origin: string): string {\n switch (origin) {\n case 'default':\n return 'default';\n case 'global':\n return '~/.issue-flow/config.json';\n case 'project':\n return '.issue-flow.json';\n case 'env':\n return 'ISSUE_FLOW_*';\n case 'cli':\n return 'CLI';\n default:\n return origin;\n }\n}\n\nfunction formatPhaseLine(\n phase: AgentPhase,\n provider: string,\n model: string | null,\n origin: string,\n inherited: boolean,\n): string {\n const modelBit = model ? ` · ${model}` : '';\n const source = inherited ? 'herdado do padrão' : originLabel(origin);\n return `${` ${phase.padEnd(12)} ${provider}${modelBit}`.padEnd(40)}(${source})`;\n}\n\nexport async function runAgent(options: AgentCommandOptions = {}): Promise<number> {\n const config = await loadAgentConfig();\n const summary = await describeRunAgents();\n const [claude, codex, cursor, antigravity] = await Promise.all([\n probeAgent('claude'),\n probeAgent('codex'),\n probeAgent('cursor'),\n probeAgent('antigravity'),\n ]);\n\n if (options.json === true) {\n const phases: Record<string, unknown> = {};\n for (const phase of AGENT_PHASES) {\n const resolved = summary.byPhase[phase];\n const inherited = config.phases[phase] === undefined;\n phases[phase] = {\n provider: resolved.provider,\n model: resolved.model,\n inherited,\n };\n }\n console.log(\n JSON.stringify(\n {\n schemaVersion: AGENT_COMMAND_SCHEMA_VERSION,\n default: {\n provider: summary.defaultProvider,\n model: summary.defaultModel,\n },\n phases,\n availability: [\n {\n id: 'claude',\n installed: claude.installed,\n version: claude.version,\n authenticated: claude.authenticated,\n },\n {\n id: 'codex',\n installed: codex.installed,\n version: codex.version,\n authenticated: codex.authenticated,\n },\n {\n id: 'cursor',\n installed: cursor.installed,\n version: cursor.version,\n authenticated: cursor.authenticated,\n },\n {\n id: 'antigravity',\n installed: antigravity.installed,\n version: antigravity.version,\n authenticated: antigravity.authenticated,\n authProbe: 'none',\n },\n ],\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n\n const modelLabel = summary.defaultModel ?? '(default do provider)';\n console.log(`Agente padrão ${summary.defaultProvider.padEnd(22)} (${originLabel('default')})`);\n console.log(`Modelo ${modelLabel}`);\n console.log('');\n console.log('Por fase');\n for (const phase of AGENT_PHASES) {\n const resolved = summary.byPhase[phase];\n const inherited = config.phases[phase] === undefined;\n console.log(\n formatPhaseLine(\n phase,\n resolved.provider,\n resolved.model,\n inherited ? 'default' : 'project',\n inherited,\n ),\n );\n }\n console.log('');\n console.log('Disponibilidade');\n console.log(` claude ${(claude.version ?? '—').padEnd(16)} ${claude.detail}`);\n console.log(` codex ${(codex.version ?? '—').padEnd(16)} ${codex.detail}`);\n console.log(` cursor ${(cursor.version ?? '—').padEnd(16)} ${cursor.detail}`);\n console.log(\n ` antigravity ${(antigravity.version ?? '—').padEnd(16)} ${antigravity.detail} (no auth probe)`,\n );\n if (antigravity.installed) {\n console.log(\n ' Warning: every Antigravity invocation passes --dangerously-skip-permissions. --mode plan is the write containment.',\n );\n }\n return 0;\n}\n\nexport async function runAgentUse(\n providerRaw: string,\n options: AgentUseOptions = {},\n): Promise<number> {\n if (!isAgentProviderId(providerRaw)) {\n printError(\n `Unknown agent provider '${providerRaw}'. Valid providers: claude, codex, cursor, antigravity.`,\n );\n return 1;\n }\n const provider = providerRaw as AgentProviderId;\n\n let phase: AgentPhase | undefined;\n if (options.phase !== undefined) {\n if (!isAgentPhase(options.phase)) {\n printError(\n `Unknown agent phase '${options.phase}'. Valid phases: ${AGENT_PHASES.join(', ')}.`,\n );\n return 1;\n }\n phase = options.phase;\n }\n\n const target: 'global' | 'project' = options.project === true ? 'project' : 'global';\n try {\n const path = await writeAgentPreference({\n target,\n provider,\n model: options.model,\n phase,\n });\n printSuccess(`Wrote agent preference to ${path}`);\n return 0;\n } catch (err) {\n printError(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n\nexport async function writeAgentPreference(input: {\n target: 'global' | 'project';\n provider: AgentProviderId;\n model?: string;\n phase?: AgentPhase;\n projectRoot?: string;\n}): Promise<string> {\n const path =\n input.target === 'global'\n ? join(getGlobalRoot(), GLOBAL_CONFIG_FILENAME)\n : join(input.projectRoot ?? (await getProjectRoot()), PROJECT_CONFIG_FILENAME);\n\n let existing: Record<string, unknown> = {};\n try {\n const raw = await readFile(path, 'utf-8');\n const parsed: unknown = JSON.parse(raw);\n if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {\n existing = parsed as Record<string, unknown>;\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw new Error(`Could not read ${path}: ${(err as Error).message}`);\n }\n }\n\n const currentAgent =\n existing.agent !== null && typeof existing.agent === 'object' && !Array.isArray(existing.agent)\n ? { ...(existing.agent as Record<string, unknown>) }\n : {};\n\n if (input.phase) {\n const phases =\n currentAgent.phases !== null &&\n typeof currentAgent.phases === 'object' &&\n !Array.isArray(currentAgent.phases)\n ? { ...(currentAgent.phases as Record<string, unknown>) }\n : {};\n phases[input.phase] = {\n provider: input.provider,\n ...(input.model ? { model: input.model } : {}),\n };\n currentAgent.phases = phases;\n } else {\n currentAgent.provider = input.provider;\n if (input.model) currentAgent.model = input.model;\n else delete currentAgent.model;\n }\n\n existing.agent = currentAgent;\n await mkdir(dirname(path), { recursive: true });\n await writeFileAtomic(path, `${JSON.stringify(existing, null, 2)}\\n`);\n if (input.provider === 'cursor') {\n const { ensureCursorStorageGrant } = await import('../agents/permissions.js');\n await ensureCursorStorageGrant({\n mode: input.target === 'project' ? 'project' : 'global',\n ...(input.projectRoot === undefined ? {} : { projectRoot: input.projectRoot }),\n });\n }\n return path;\n}\n\n/** Used by init to persist a first-run choice without touching other keys. */\nexport async function persistFirstAgentChoice(provider: AgentProviderId): Promise<string> {\n return writeAgentPreference({ target: 'global', provider });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/telemetry/recorder.ts","../src/telemetry/pricing.ts","../src/telemetry/redact.ts","../src/telemetry/types.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { hostname } from 'node:os';\nimport type { ClaudeUsage } from '../core/metrics.js';\nimport { isoNow, loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { classify } from '../resilience/errors.js';\nimport type { TaskPlan } from '../types.js';\nimport { resolveCost } from './pricing.js';\nimport { redactFailureMessage } from './redact.js';\nimport { getTelemetrySessionId, setTelemetrySessionId } from './session-id.js';\nimport {\n DEFAULT_TELEMETRY_CONFIG,\n type ExecutionPurpose,\n type ExecutionRecord,\n type ExecutionStatus,\n type ExecutionTrigger,\n type NormalizedUsage,\n type StopReason,\n type TelemetryConfig,\n} from './types.js';\n\nexport interface TelemetryContext {\n tasksPath: string;\n sessionId?: string | null;\n config?: TelemetryConfig;\n}\n\nlet context: TelemetryContext | null = null;\nlet discardedCount = 0;\n\nexport function bindTelemetry(next: TelemetryContext | null): void {\n context = next;\n}\n\nexport function getTelemetryContext(): TelemetryContext | null {\n return context;\n}\n\nexport function discardedExecutionCount(): number {\n return discardedCount;\n}\n\nexport function resetTelemetryState(): void {\n context = null;\n discardedCount = 0;\n setTelemetrySessionId(null);\n}\n\nasync function resolveConfig(ctx: TelemetryContext): Promise<TelemetryConfig> {\n if (ctx.config !== undefined) return ctx.config;\n try {\n const { loadTelemetryConfig } = await import('../config.js');\n ctx.config = await loadTelemetryConfig();\n return ctx.config;\n } catch {\n return DEFAULT_TELEMETRY_CONFIG;\n }\n}\n\nfunction cap(records: ExecutionRecord[], max: number): ExecutionRecord[] {\n if (records.length <= max) return records;\n discardedCount += records.length - max;\n return records.slice(records.length - max);\n}\n\nasync function mutate(tasksPath: string, update: (plan: TaskPlan) => TaskPlan): Promise<void> {\n const plan = await loadTaskPlan(tasksPath);\n await saveTaskPlan(tasksPath, update(plan));\n}\n\nexport function usageFromClaude(usage: ClaudeUsage | null | undefined): NormalizedUsage | null {\n if (usage === undefined || usage === null) return null;\n const next: NormalizedUsage = { source: 'provider' };\n if (usage.inputTokens !== undefined) next.inputTokens = usage.inputTokens;\n if (usage.outputTokens !== undefined) next.outputTokens = usage.outputTokens;\n if (usage.cacheReadTokens !== undefined) next.cacheReadTokens = usage.cacheReadTokens;\n if (usage.cacheCreationTokens !== undefined) next.cacheCreationTokens = usage.cacheCreationTokens;\n return next;\n}\n\nexport interface BeginExecutionInput {\n purpose: ExecutionPurpose;\n attempt?: number;\n trigger?: ExecutionTrigger;\n triggerReason?: ExecutionRecord['triggerReason'];\n harness: string;\n provider?: string | null;\n harnessVersion?: string | null;\n modelRequested?: string | null;\n modelResolved?: string | null;\n modelSource?: ExecutionRecord['agent']['model']['source'];\n iteration?: number;\n routingDecision?: ExecutionRecord['routingDecision'];\n}\n\nexport async function beginExecution(input: BeginExecutionInput): Promise<string | null> {\n const ctx = context;\n if (ctx === null) return null;\n const cfg = await resolveConfig(ctx);\n if (!cfg.enabled) return null;\n\n const id = randomUUID();\n const record: ExecutionRecord = {\n id,\n sessionId: ctx.sessionId ?? getTelemetrySessionId(),\n purpose: input.purpose,\n attempt: input.attempt ?? 1,\n trigger: input.trigger ?? 'initial',\n triggerReason: input.triggerReason ?? null,\n agent: {\n harness: input.harness,\n provider: input.provider ?? null,\n harnessVersion: input.harnessVersion ?? null,\n model: {\n requested: input.modelRequested ?? null,\n resolved: input.modelResolved ?? null,\n source: input.modelSource ?? (input.modelResolved ? 'provider' : 'unavailable'),\n },\n providerSessionId: null,\n },\n startedAt: isoNow(),\n finishedAt: null,\n durationMs: null,\n usage: null,\n cost: { status: 'unknown', reason: 'not_reported' },\n status: 'running',\n failure: null,\n owner: { pid: process.pid, host: hostname() },\n ...(input.iteration === undefined ? {} : { iteration: input.iteration }),\n ...(input.routingDecision === undefined || input.routingDecision === null\n ? {}\n : { routingDecision: input.routingDecision }),\n };\n\n try {\n await mutate(ctx.tasksPath, (plan) => ({\n ...plan,\n executions: cap([...(plan.executions ?? []), record], cfg.maxExecutions),\n }));\n return id;\n } catch {\n return null;\n }\n}\n\n/** Wall clock vs CLI envelope: startup the harness does not report. */\nexport function timingFromUsage(\n wallClockMs: number | null,\n usage: ClaudeUsage | null | undefined,\n): Pick<\n ExecutionRecord,\n 'cliDurationMs' | 'harnessStartupMs' | 'apiDurationMs' | 'ttftMs' | 'numTurns'\n> {\n const cli = usage?.cliDurationMs;\n const cliDurationMs = cli === undefined ? null : cli;\n const harnessStartupMs =\n wallClockMs !== null && cli !== undefined ? Math.max(0, wallClockMs - cli) : null;\n return {\n cliDurationMs,\n harnessStartupMs,\n apiDurationMs: usage?.apiDurationMs ?? null,\n ttftMs: usage?.ttftMs ?? null,\n numTurns: usage?.numTurns ?? null,\n };\n}\n\nexport async function attachVerdict(verdict: ExecutionRecord['verdict']): Promise<void> {\n const ctx = context;\n if (ctx === null || verdict == null) return;\n try {\n await mutate(ctx.tasksPath, (plan) => {\n const records = [...(plan.executions ?? [])];\n if (records.length === 0) return plan;\n const index = records.length - 1;\n const current = records[index];\n if (current === undefined) return plan;\n records[index] = { ...current, verdict };\n return { ...plan, executions: records };\n });\n } catch {\n // Observational: a failed write must never change the invocation outcome.\n }\n}\n\nexport interface EndExecutionInput {\n id: string;\n status?: ExecutionStatus;\n usage?: ClaudeUsage | null;\n reportedUsd?: number | null;\n error?: string | null;\n exitCode?: number | null;\n storyIds?: string[];\n cancelled?: boolean;\n timedOut?: boolean;\n modelResolved?: string | null;\n modelSource?: ExecutionRecord['agent']['model']['source'];\n harnessVersion?: string | null;\n providerSessionId?: string | null;\n stopReason?: StopReason | null;\n}\n\nexport async function endExecution(input: EndExecutionInput): Promise<void> {\n const ctx = context;\n if (ctx === null) return;\n const cfg = await resolveConfig(ctx);\n if (!cfg.enabled) return;\n\n const usage = usageFromClaude(input.usage);\n const timedOut = input.timedOut === true || /\\btimed out\\b/i.test(input.error ?? '');\n const cancelled = input.cancelled === true;\n let status: ExecutionStatus = input.status ?? 'completed';\n if (input.status === undefined) {\n if (cancelled) status = 'cancelled';\n else if (timedOut) status = 'timeout';\n else if (input.error) status = 'failed';\n }\n\n const failure =\n status === 'completed'\n ? null\n : {\n kind: classify({\n source: 'agent',\n stdout: input.error ?? '',\n exitCode: input.exitCode,\n timedOut,\n }).kind,\n message: redactFailureMessage(input.error ?? status),\n exitCode: input.exitCode ?? null,\n };\n\n try {\n await mutate(ctx.tasksPath, (plan) => {\n const records = [...(plan.executions ?? [])];\n const index = records.findIndex((record) => record.id === input.id);\n if (index === -1) return plan;\n const current = records[index];\n if (current === undefined) return plan;\n const started = Date.parse(current.startedAt);\n const finishedAt = isoNow();\n const modelResolved = input.modelResolved ?? current.agent.model.resolved;\n const modelKey = modelResolved ?? current.agent.model.requested;\n records[index] = {\n ...current,\n agent: {\n ...current.agent,\n harnessVersion: input.harnessVersion ?? current.agent.harnessVersion,\n providerSessionId: input.providerSessionId ?? current.agent.providerSessionId,\n model: {\n ...current.agent.model,\n resolved: modelResolved,\n source:\n input.modelSource ??\n (modelResolved\n ? current.agent.model.source === 'unavailable'\n ? 'provider'\n : current.agent.model.source\n : current.agent.model.source),\n },\n },\n finishedAt,\n durationMs: Number.isFinite(started) ? Math.max(0, Date.now() - started) : null,\n ...timingFromUsage(\n Number.isFinite(started) ? Math.max(0, Date.now() - started) : null,\n input.usage,\n ),\n usage,\n cost: resolveCost({\n reportedUsd: input.reportedUsd ?? input.usage?.costUsd,\n usage,\n modelKey,\n estimate: cfg.pricing.estimate,\n overrides: cfg.pricing.overrides,\n }),\n status,\n failure,\n owner: null,\n ...(input.storyIds === undefined ? {} : { storyIds: input.storyIds }),\n ...(input.stopReason === undefined ? {} : { stopReason: input.stopReason }),\n };\n return { ...plan, executions: records };\n });\n } catch {\n // Observational: a failed write must never change the invocation outcome.\n }\n}\n\nexport async function recordInvocation<T>(\n input: BeginExecutionInput,\n invoke: () => Promise<T>,\n finish: (result: T) => EndExecutionInput,\n): Promise<T> {\n const id = await beginExecution(input);\n try {\n const result = await invoke();\n if (id !== null) {\n await endExecution({ ...finish(result), id });\n }\n return result;\n } catch (err) {\n if (id !== null) {\n await endExecution({\n id,\n status: 'failed',\n error: err instanceof Error ? err.message : String(err),\n });\n }\n throw err;\n }\n}\n","import { isoNow } from '../core/state-manager.js';\nimport type { CostRecord, NormalizedUsage, PricingSnapshot, TelemetryConfig } from './types.js';\n\nexport const PRICING_TABLE_VERSION = '2026-08-30';\n\ninterface PricingRow {\n inputPerMillion: number;\n outputPerMillion: number;\n cacheReadPerMillion?: number;\n cacheWritePerMillion?: number;\n}\n\n/** Microdollars-per-million would be more precise; dollars keep the snapshot readable. */\nconst TABLE: Record<string, PricingRow> = {\n 'claude-sonnet-4': {\n inputPerMillion: 3,\n outputPerMillion: 15,\n cacheReadPerMillion: 0.3,\n cacheWritePerMillion: 3.75,\n },\n 'claude-sonnet-4-5': {\n inputPerMillion: 3,\n outputPerMillion: 15,\n cacheReadPerMillion: 0.3,\n cacheWritePerMillion: 3.75,\n },\n 'claude-opus-4': {\n inputPerMillion: 15,\n outputPerMillion: 75,\n cacheReadPerMillion: 1.5,\n cacheWritePerMillion: 18.75,\n },\n 'gpt-5': { inputPerMillion: 1.25, outputPerMillion: 10 },\n 'gpt-5.1': { inputPerMillion: 1.25, outputPerMillion: 10 },\n};\n\n/** Aliases a harness accepts in place of a model id. */\nconst ALIASES: Record<string, string> = {\n sonnet: 'claude-sonnet-4-5',\n opus: 'claude-opus-4',\n};\n\n/**\n * Map a resolved model id onto a table key.\n *\n * What reaches here is whatever the harness reported: a dated snapshot\n * (`claude-sonnet-4-5-20250929`), a vendor-prefixed id\n * (`anthropic/claude-sonnet-4-5`) or a configured alias (`sonnet`). An exact\n * lookup misses all three, and the estimate silently degrades to `unknown`.\n * An override is always honoured under the key the user wrote.\n */\nexport function normalizeModelKey(modelKey: string): string {\n const lower = modelKey.trim().toLowerCase();\n const withoutVendor = lower.slice(lower.lastIndexOf('/') + 1);\n const withoutSnapshot = withoutVendor.replace(/-\\d{8}$/, '').replace(/-latest$/, '');\n return ALIASES[withoutSnapshot] ?? withoutSnapshot;\n}\n\nfunction rowFor(\n modelKey: string,\n overrides: TelemetryConfig['pricing']['overrides'],\n): PricingRow | null {\n const normalized = normalizeModelKey(modelKey);\n const override = overrides[modelKey] ?? overrides[normalized];\n const base = TABLE[modelKey] ?? TABLE[normalized];\n if (override === undefined && base === undefined) return null;\n return {\n inputPerMillion: override?.inputPerMillion ?? base?.inputPerMillion ?? 0,\n outputPerMillion: override?.outputPerMillion ?? base?.outputPerMillion ?? 0,\n cacheReadPerMillion: override?.cacheReadPerMillion ?? base?.cacheReadPerMillion,\n cacheWritePerMillion: override?.cacheWritePerMillion ?? base?.cacheWritePerMillion,\n };\n}\n\nfunction dollars(tokens: number | undefined, perMillion: number | undefined): number {\n if (tokens === undefined || perMillion === undefined) return 0;\n return (tokens * perMillion) / 1_000_000;\n}\n\nexport function resolveCost(options: {\n reportedUsd?: number | null;\n usage: NormalizedUsage | null;\n modelKey: string | null;\n estimate: boolean;\n overrides?: TelemetryConfig['pricing']['overrides'];\n}): CostRecord {\n if (options.reportedUsd !== undefined && options.reportedUsd !== null) {\n return { status: 'reported', amount: options.reportedUsd, currency: 'USD' };\n }\n if (!options.estimate) {\n return { status: 'unknown', reason: 'not_reported' };\n }\n if (options.modelKey === null || options.modelKey === '') {\n return { status: 'unknown', reason: 'unknown_model' };\n }\n const row = rowFor(options.modelKey, options.overrides ?? {});\n if (row === null) {\n return { status: 'unknown', reason: 'unknown_model' };\n }\n if (options.usage === null || options.usage.source === 'unavailable') {\n return { status: 'unknown', reason: 'not_reported' };\n }\n const amount =\n dollars(options.usage.inputTokens, row.inputPerMillion) +\n dollars(options.usage.outputTokens, row.outputPerMillion) +\n dollars(options.usage.cacheReadTokens, row.cacheReadPerMillion) +\n dollars(options.usage.cacheCreationTokens, row.cacheWritePerMillion);\n const pricing: PricingSnapshot = {\n tableVersion: PRICING_TABLE_VERSION,\n modelKey: options.modelKey,\n inputPerMillion: row.inputPerMillion,\n outputPerMillion: row.outputPerMillion,\n capturedAt: isoNow(),\n ...(row.cacheReadPerMillion === undefined\n ? {}\n : { cacheReadPerMillion: row.cacheReadPerMillion }),\n ...(row.cacheWritePerMillion === undefined\n ? {}\n : { cacheWritePerMillion: row.cacheWritePerMillion }),\n };\n return { status: 'estimated', amount, currency: 'USD', pricing };\n}\n\nexport function estimateCost(\n usage: NormalizedUsage,\n modelKey: string,\n overrides: TelemetryConfig['pricing']['overrides'] = {},\n): CostRecord {\n return resolveCost({ usage, modelKey, estimate: true, overrides });\n}\n","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 ENV_ASSIGN =\n /\\b(?:[A-Z][A-Z0-9_]*(?:TOKEN|SECRET|KEY|PASSWORD|PASS|AUTH)[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(\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","import type { FailureKind } from '../resilience/errors.js';\n\nexport const EXECUTION_PURPOSES = [\n 'analyze',\n 'generate',\n 'prd',\n 'plan',\n 'execute',\n 'review',\n 'pr',\n 'pr-review',\n 'verify',\n] as const;\n\nexport type ExecutionPurpose = (typeof EXECUTION_PURPOSES)[number];\n\nexport type ExecutionTrigger = 'initial' | 'retry' | 'fallback' | 'correction' | 'escalation';\n\nexport type ExecutionStatus =\n | 'running'\n | 'completed'\n | 'failed'\n | 'timeout'\n | 'cancelled'\n | 'interrupted';\n\nexport type StopReason =\n | 'completed'\n | 'failed'\n | 'timeout'\n | 'cancelled'\n | 'max_attempts'\n | 'max_cost'\n | 'max_duration';\n\nexport type VerdictStatus = 'passed' | 'failed' | 'unverified';\n\nexport interface NormalizedUsage {\n inputTokens?: number;\n outputTokens?: number;\n cacheReadTokens?: number;\n cacheCreationTokens?: number;\n reasoningTokens?: number;\n details?: Record<string, number>;\n source: 'provider' | 'unavailable';\n}\n\nexport interface PricingSnapshot {\n tableVersion: string;\n modelKey: string;\n inputPerMillion: number;\n outputPerMillion: number;\n cacheReadPerMillion?: number;\n cacheWritePerMillion?: number;\n capturedAt: string;\n}\n\nexport type CostRecord =\n | { status: 'reported'; amount: number; currency: 'USD' }\n | { status: 'estimated'; amount: number; currency: 'USD'; pricing: PricingSnapshot }\n | {\n status: 'unknown';\n reason: 'not_reported' | 'no_pricing' | 'unknown_model' | 'subscription' | 'zero_rated';\n };\n\nexport interface ExecutionAgent {\n harness: string;\n provider: string | null;\n harnessVersion?: string | null;\n model: {\n requested: string | null;\n resolved: string | null;\n source: 'provider' | 'config' | 'unavailable';\n };\n providerSessionId: string | null;\n}\n\nexport interface ExecutionOwner {\n pid: number;\n host: string;\n}\n\nexport interface ExecutionVerdict {\n status: VerdictStatus;\n level?: string | null;\n independence?: string | null;\n}\n\nexport interface RoutingDecision {\n selected: string;\n actual?: string;\n candidates?: unknown[];\n reasonCodes?: string[];\n [key: string]: unknown;\n}\n\nexport interface ExecutionRecord {\n id: string;\n sessionId: string | null;\n purpose: ExecutionPurpose;\n attempt: number;\n trigger: ExecutionTrigger;\n triggerReason: FailureKind | null;\n agent: ExecutionAgent;\n startedAt: string;\n finishedAt: string | null;\n durationMs: number | null;\n /** Envelope duration when the CLI reports it. */\n cliDurationMs?: number | null;\n /** wallClock − cliDuration: startup the CLI does not see. */\n harnessStartupMs?: number | null;\n /** Envelope `duration_api_ms` when reported. */\n apiDurationMs?: number | null;\n /** Time to first output, when reported. */\n ttftMs?: number | null;\n numTurns?: number | null;\n usage: NormalizedUsage | null;\n cost: CostRecord;\n status: ExecutionStatus;\n failure: {\n kind: FailureKind;\n message: string;\n exitCode: number | null;\n } | null;\n stopReason?: StopReason | null;\n iteration?: number;\n storyIds?: string[];\n owner?: ExecutionOwner | null;\n routingDecision?: RoutingDecision | null;\n verdict?: ExecutionVerdict | null;\n}\n\nexport interface CostTotals {\n reported: number;\n estimated: number;\n unknownExecutions: number;\n}\n\nexport interface ExecutionSummary {\n count: number;\n discarded: number;\n byStatus: Partial<Record<ExecutionStatus, number>>;\n usage: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n reasoningTokens: number;\n };\n totalCost: CostTotals;\n}\n\nexport interface TelemetryConfig {\n enabled: boolean;\n maxExecutions: number;\n pricing: {\n estimate: boolean;\n overrides: Record<string, Partial<PricingSnapshot>>;\n };\n}\n\nexport const DEFAULT_TELEMETRY_CONFIG: TelemetryConfig = {\n enabled: true,\n maxExecutions: 500,\n pricing: { estimate: false, overrides: {} },\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
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 type { ProviderHealthRecord } from '../storage/schemas.js';\nimport { beginExecution, endExecution } from '../telemetry/recorder.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(selection: AgentSelection, attempt: number): ExecutionTrigger {\n if (selection.failover) return 'fallback';\n if (attempt > 1) return 'retry';\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 }\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),\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 ...(routingDecision === null\n ? {}\n : { routingDecision: routingDecision as unknown as ExecutionRecord['routingDecision'] }),\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 publisher.publish({\n type: 'agent:activity',\n at: isoNow(),\n provider: selection.provider,\n });\n invocation.onLine?.(line);\n },\n },\n selection.settings,\n );\n } catch (err) {\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\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 });\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 { 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}\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 },\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 } = 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 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 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":"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","names":["run","failure","readFile","readFile","prefix"]}
|